Example #1
0
        private void RegisterCommandHandlersForCommandsWithNoAssociatedHandler(FunctionHostBuilder builder, ICommandRegistry commandRegistry)
        {
            // IN PROGRESS: This looks from the loaded set of assemblies and looks for a command handler for each command associated with a function.
            // If the handler is not already registered in the command registry then this registers it.
            IRegistrationCatalogue registrationCatalogue  = (IRegistrationCatalogue)commandRegistry;
            HashSet <Type>         registeredCommandTypes = new HashSet <Type>(registrationCatalogue.GetRegisteredCommands());

            Dictionary <Type, List <Type> > commandTypesToHandlerTypes = null;

            foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions)
            {
                if (registeredCommandTypes.Contains(functionDefinition.CommandType))
                {
                    continue;
                }

                if (commandTypesToHandlerTypes == null)
                {
                    commandTypesToHandlerTypes = HarvestCommandHandlers();
                }

                if (commandTypesToHandlerTypes.TryGetValue(functionDefinition.CommandType, out List <Type> handlerTypes))
                {
                    foreach (Type handlerType in handlerTypes)
                    {
                        commandRegistry.Register(handlerType);
                    }
                }
            }
        }
        public async Task ExecuteAsync(ScheduledMessage scheduledMessage)
        {
            Type wrappedCommandType = _registry.GetRegisteredCommands()
                                      .FirstOrDefault(x => x.FullName == scheduledMessage.WrappedCommandFullTypeName);

            if (wrappedCommandType == null)
            {
                throw new ConfigurationException($"Command type {scheduledMessage.WrappedCommandFullTypeName} has not been registered");
            }

            ICommand <bool> wrappedCommand   = (ICommand <bool>)JsonConvert.DeserializeObject(scheduledMessage.WrappedCommandJson, wrappedCommandType);
            bool            shouldReschedule = await _dispatcher.DispatchAsync(wrappedCommand);

            if (shouldReschedule)
            {
                // this should be the very last thing we do - otherwise an exception may cause a double queue of
                // the rescheduled message
                await _commandRescheduler.Reschedule(scheduledMessage);
            }

            // there is a chance that between here and this message being removed from the queue
            // that an exception occurs meaning the message will be popped and rescheduled again
            // leading to duplication
            // to protect against this the message ID is set on the service bus message and Service Bus
            // Deduplication should be turned on, consider the message ID time window based on the
            // recurrence interval - do not set the deuplication window to be larger than the interval
            // otherwise legitimate reschedules will be detected as duplicates by SB.
        }
Example #3
0
        private void RegisterCommandHandlersForCommandsWithNoAssociatedHandler(FunctionHostBuilder builder, ICommandRegistry commandRegistry)
        {
            // TODO: We can improve this so that auto-registration is decoupled and can be provided by a mediator package
            if (builder.MediatorType != typeof(DefaultMediatorDecorator))
            {
                return;
            }

            // IN PROGRESS: This looks from the loaded set of assemblies and looks for a command handler for each command associated with a function.
            // If the handler is not already registered in the command registry then this registers it.
            IRegistrationCatalogue registrationCatalogue  = (IRegistrationCatalogue)commandRegistry;
            HashSet <Type>         registeredCommandTypes = new HashSet <Type>(registrationCatalogue.GetRegisteredCommands());

            Dictionary <Type, List <Type> > commandTypesToHandlerTypes = null;

            foreach (AbstractFunctionDefinition functionDefinition in builder.FunctionDefinitions)
            {
                if (registeredCommandTypes.Contains(functionDefinition.CommandType))
                {
                    continue;
                }

                if (commandTypesToHandlerTypes == null)
                {
                    commandTypesToHandlerTypes = HarvestCommandHandlers();
                }

                if (commandTypesToHandlerTypes.TryGetValue(functionDefinition.CommandType, out List <Type> handlerTypes))
                {
                    foreach (Type handlerType in handlerTypes)
                    {
                        commandRegistry.Register(handlerType);
                    }
                }
            }
        }
Example #4
0
        private IReadOnlyCollection <string> GetExternalAssemblyLocations(
            IReadOnlyCollection <AbstractFunctionDefinition> functionDefinitions)
        {
            HashSet <Assembly> assemblies = new HashSet <Assembly>();

            foreach (AbstractFunctionDefinition functionDefinition in functionDefinitions)
            {
                assemblies.Add(_triggerReferenceProvider.GetTriggerReference(functionDefinition));
                assemblies.Add(functionDefinition.CommandType.Assembly);

                if (functionDefinition.CommandResultType != null)
                {
                    // skip system types
                    if (functionDefinition.CommandResultType.Assembly != typeof(string).Assembly)
                    {
                        assemblies.Add(functionDefinition.CommandResultType.Assembly);
                    }
                }
            }

            // TODO: Do we need this any more? We no longer run the startup code in the compilation process?
            foreach (ServiceDescriptor descriptor in _serviceCollection)
            {
                assemblies.Add(descriptor.ServiceType.Assembly);
                if (descriptor.ImplementationType != null)
                {
                    assemblies.Add(descriptor.ImplementationType.Assembly);
                }

                if (descriptor.ImplementationInstance != null)
                {
                    assemblies.Add(descriptor.ImplementationInstance.GetType().Assembly);
                }
            }

            IRegistrationCatalogue catalogue = (IRegistrationCatalogue)_commandRegistry;

            foreach (Type handler in catalogue.GetRegisteredHandlers())
            {
                assemblies.Add(handler.Assembly);
            }

            foreach (Type command in catalogue.GetRegisteredCommands())
            {
                assemblies.Add(command.Assembly);
            }

            assemblies.Add(_configurationSourceAssembly);

            // we have to add directly referenced assemblies in case the commands and result types make use of external types
            // TODO: their is an argument to restricting this
            foreach (Assembly assembly in assemblies.ToArray())
            {
                AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies();
                foreach (var referencedAssemblyName in referencedAssemblies)
                {
                    if (referencedAssemblyName.Name == "netstandard" || referencedAssemblyName.Name == "System.Runtime")
                    {
                        continue;
                    }
                    var referencedAssembly = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(x => x.FullName == referencedAssemblyName.FullName);
                    if (referencedAssembly != null)
                    {
                        assemblies.Add(referencedAssembly);
                    }
                }
            }

            // at the moment we can't get the actual dispatcher types without actually calling the function and looking at ther result - needs thought
            return(assemblies.Select(x => x.Location).ToArray());
        }