Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DurableTaskExtension"/>.
        /// </summary>
        /// <param name="options">The configuration options for this extension.</param>
        /// <param name="loggerFactory">The logger factory used for extension-specific logging and orchestration tracking.</param>
        /// <param name="nameResolver">The name resolver to use for looking up application settings.</param>
        /// <param name="orchestrationServiceFactory">The factory used to create orchestration service based on the configured storage provider.</param>
        /// <param name="durableHttpMessageHandlerFactory">The HTTP message handler that handles HTTP requests and HTTP responses.</param>
        /// <param name="lifeCycleNotificationHelper">The lifecycle notification helper used for custom orchestration tracking.</param>
        public DurableTaskExtension(
            IOptions <DurableTaskOptions> options,
            ILoggerFactory loggerFactory,
            INameResolver nameResolver,
            IDurabilityProviderFactory orchestrationServiceFactory,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandlerFactory = null,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper           = null)
        {
            // Options will be null in Functions v1 runtime - populated later.
            this.Options      = options?.Value ?? new DurableTaskOptions();
            this.nameResolver = nameResolver ?? throw new ArgumentNullException(nameof(nameResolver));

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            ILogger logger = loggerFactory.CreateLogger(LoggerCategoryName);

            this.TraceHelper = new EndToEndTraceHelper(logger, this.Options.Tracing.TraceReplayEvents);
            this.LifeCycleNotificationHelper = lifeCycleNotificationHelper ?? this.CreateLifeCycleNotificationHelper();
            this.durabilityProviderFactory   = orchestrationServiceFactory;
            this.defaultDurabilityProvider   = this.durabilityProviderFactory.GetDurabilityProvider();
            this.HttpApiHandler      = new HttpApiHandler(this, logger);
            this.isOptionsConfigured = true;

            if (durableHttpMessageHandlerFactory == null)
            {
                durableHttpMessageHandlerFactory = new DurableHttpMessageHandlerFactory();
            }

            DurableHttpClientFactory durableHttpClientFactory = new DurableHttpClientFactory();

            this.durableHttpClient = durableHttpClientFactory.GetClient(durableHttpMessageHandlerFactory);
        }
        public static ITestHost CreateJobHost(
            IOptions <DurableTaskOptions> options,
            string storageProvider,
            Type durabilityProviderFactoryType,
            ILoggerProvider loggerProvider,
            INameResolver nameResolver,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandler,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper,
            IMessageSerializerSettingsFactory serializerSettingsFactory,
            Action <ITelemetry> onSend)
        {
            IHost host = new HostBuilder()
                         .ConfigureLogging(
                loggingBuilder =>
            {
                loggingBuilder.AddProvider(loggerProvider);
            })
                         .ConfigureWebJobs(
                webJobsBuilder =>
            {
                webJobsBuilder.AddDurableTask(options, storageProvider, durabilityProviderFactoryType);
                webJobsBuilder.AddAzureStorage();
            })
                         .ConfigureServices(
                serviceCollection =>
            {
                ITypeLocator typeLocator = TestHelpers.GetTypeLocator();
                serviceCollection.AddSingleton(typeLocator);
                serviceCollection.AddSingleton(nameResolver);
                serviceCollection.AddSingleton(durableHttpMessageHandler);

                if (lifeCycleNotificationHelper != null)
                {
                    serviceCollection.AddSingleton(lifeCycleNotificationHelper);
                }

                if (serializerSettingsFactory != null)
                {
                    serviceCollection.AddSingleton(serializerSettingsFactory);
                }

                if (onSend != null)
                {
                    serviceCollection.AddSingleton <ITelemetryActivator>(serviceProvider =>
                    {
                        var durableTaskOptions = serviceProvider.GetService <IOptions <DurableTaskOptions> >();
                        var telemetryActivator = new TelemetryActivator(durableTaskOptions)
                        {
                            OnSend = onSend,
                        };
                        return(telemetryActivator);
                    });
                }
            })
                         .Build();

            return(new FunctionsV2HostWrapper(host, options, nameResolver));
        }
Beispiel #3
0
        public static ITestHost CreateJobHost(
            IOptions <DurableTaskOptions> options,
            string storageProvider,
            ILoggerProvider loggerProvider,
            INameResolver nameResolver,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandler,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper,
            IMessageSerializerSettingsFactory serializerSettingsFactory,
            IApplicationLifetimeWrapper shutdownNotificationService = null,
            Action <ITelemetry> onSend = null)
        {
            var config = new JobHostConfiguration {
                HostId = "durable-task-host"
            };

            config.TypeLocator = TestHelpers.GetTypeLocator();

            var connectionResolver = new WebJobsConnectionStringProvider();

            var loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(loggerProvider);

            IDurabilityProviderFactory orchestrationServiceFactory = new AzureStorageDurabilityProviderFactory(
                options,
                connectionResolver,
                nameResolver,
                loggerFactory);

            var extension = new DurableTaskExtension(
                options,
                loggerFactory,
                nameResolver,
                orchestrationServiceFactory,
                shutdownNotificationService ?? new TestHostShutdownNotificationService(),
                durableHttpMessageHandler,
                lifeCycleNotificationHelper,
                serializerSettingsFactory);

            config.UseDurableTask(extension);

            // Mock INameResolver for not setting EnvironmentVariables.
            if (nameResolver != null)
            {
                config.AddService(nameResolver);
            }

            // Performance is *significantly* worse when dashboard logging is enabled, at least
            // when running in the storage emulator. Disabling to keep tests running quickly.
            config.DashboardConnectionString = null;

            // Add test logger
            config.LoggerFactory = loggerFactory;

            var host = new JobHost(config);

            return(new FunctionsV1HostWrapper(host, options, connectionResolver));
        }
Beispiel #4
0
 internal DurableTaskExtension(
     IOptions <DurableTaskOptions> options,
     ILoggerFactory loggerFactory,
     INameResolver nameResolver,
     IDurabilityProviderFactory orchestrationServiceFactory,
     IConnectionStringResolver connectionStringResolver,
     IDurableHttpMessageHandlerFactory durableHttpMessageHandlerFactory)
     : this(options, loggerFactory, nameResolver, orchestrationServiceFactory, durableHttpMessageHandlerFactory)
 {
     this.connectionStringResolver = connectionStringResolver;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="DurableTaskExtension"/>.
        /// </summary>
        /// <param name="options">The configuration options for this extension.</param>
        /// <param name="loggerFactory">The logger factory used for extension-specific logging and orchestration tracking.</param>
        /// <param name="nameResolver">The name resolver to use for looking up application settings.</param>
        /// <param name="orchestrationServiceFactory">The factory used to create orchestration service based on the configured storage provider.</param>
        /// <param name="durableHttpMessageHandlerFactory">The HTTP message handler that handles HTTP requests and HTTP responses.</param>
        /// <param name="hostLifetimeService">The host shutdown notification service for detecting and reacting to host shutdowns.</param>
        /// <param name="lifeCycleNotificationHelper">The lifecycle notification helper used for custom orchestration tracking.</param>
        /// <param name="messageSerializerSettingsFactory">The factory used to create <see cref="JsonSerializerSettings"/> for message settings.</param>
        /// <param name="errorSerializerSettingsFactory">The factory used to create <see cref="JsonSerializerSettings"/> for error settings.</param>
        public DurableTaskExtension(
            IOptions <DurableTaskOptions> options,
            ILoggerFactory loggerFactory,
            INameResolver nameResolver,
            IDurabilityProviderFactory orchestrationServiceFactory,
            IApplicationLifetimeWrapper hostLifetimeService,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandlerFactory = null,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper           = null,
            IMessageSerializerSettingsFactory messageSerializerSettingsFactory = null,
            IErrorSerializerSettingsFactory errorSerializerSettingsFactory     = null)
        {
            // Options will be null in Functions v1 runtime - populated later.
            this.Options      = options?.Value ?? new DurableTaskOptions();
            this.nameResolver = nameResolver ?? throw new ArgumentNullException(nameof(nameResolver));
            this.ResolveAppSettingOptions();

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            ILogger logger = loggerFactory.CreateLogger(LoggerCategoryName);

            this.TraceHelper = new EndToEndTraceHelper(logger, this.Options.Tracing.TraceReplayEvents);
            this.LifeCycleNotificationHelper = lifeCycleNotificationHelper ?? this.CreateLifeCycleNotificationHelper();
            this.durabilityProviderFactory   = orchestrationServiceFactory;
            this.defaultDurabilityProvider   = this.durabilityProviderFactory.GetDurabilityProvider();
            this.isOptionsConfigured         = true;

            if (durableHttpMessageHandlerFactory == null)
            {
                durableHttpMessageHandlerFactory = new DurableHttpMessageHandlerFactory();
            }

            DurableHttpClientFactory durableHttpClientFactory = new DurableHttpClientFactory();

            this.durableHttpClient = durableHttpClientFactory.GetClient(durableHttpMessageHandlerFactory);

            this.MessageDataConverter = this.CreateMessageDataConverter(messageSerializerSettingsFactory);
            this.ErrorDataConverter   = this.CreateErrorDataConverter(errorSerializerSettingsFactory);

            this.HttpApiHandler = new HttpApiHandler(this, logger);

#if !FUNCTIONS_V1
            // The RPC server is started when the extension is initialized.
            // The RPC server is stopped when the host has finished shutting down.
            hostLifetimeService.OnStopped.Register(this.StopLocalRcpServer);
#endif
        }
        public HttpClient GetClient(IDurableHttpMessageHandlerFactory handler)
        {
            if (this.durableHttpClient == null)
            {
                this.durableHttpClient = new HttpClient(handler.CreateHttpMessageHandler());

                var     assembly        = typeof(DurableTaskExtension).Assembly;
                Version assemblyVersion = GetAssemblyVersion(assembly);

                this.durableHttpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(
                                                                               assembly.GetName().Name,
                                                                               assemblyVersion.ToString()));
            }

            return(this.durableHttpClient);
        }
        public static ITestHost CreateJobHost(
            IOptions <DurableTaskOptions> options,
            string storageProvider,
            ILoggerProvider loggerProvider,
            INameResolver nameResolver,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandler,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper,
            IMessageSerializerSettingsFactory serializerSettingsFactory)
        {
            IHost host = new HostBuilder()
                         .ConfigureLogging(
                loggingBuilder =>
            {
                loggingBuilder.AddProvider(loggerProvider);
            })
                         .ConfigureWebJobs(
                webJobsBuilder =>
            {
                webJobsBuilder.AddDurableTask(options, storageProvider);
                webJobsBuilder.AddAzureStorage();
            })
                         .ConfigureServices(
                serviceCollection =>
            {
                ITypeLocator typeLocator = TestHelpers.GetTypeLocator();
                serviceCollection.AddSingleton(typeLocator);
                serviceCollection.AddSingleton(nameResolver);
                serviceCollection.AddSingleton(durableHttpMessageHandler);

                if (lifeCycleNotificationHelper != null)
                {
                    serviceCollection.AddSingleton(lifeCycleNotificationHelper);
                }

                if (serializerSettingsFactory != null)
                {
                    serviceCollection.AddSingleton(serializerSettingsFactory);
                }
            })
                         .Build();

            return(new FunctionsV2HostWrapper(host));
        }
        public static ITestHost CreateJobHost(
            IOptions <DurableTaskOptions> options,
            string storageProvider,
            ILoggerProvider loggerProvider,
            INameResolver nameResolver,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandler,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper,
            IMessageSerializerSettingsFactory serializerSettingsFactory,
            IApplicationLifetimeWrapper shutdownNotificationService = null,
            Action <ITelemetry> onSend = null,
#pragma warning disable CS0612 // Type or member is obsolete
            IPlatformInformationService platformInformationService = null)
#pragma warning restore CS0612 // Type or member is obsolete
        {
            var config = new JobHostConfiguration {
                HostId = "durable-task-host"
            };

            config.TypeLocator = TestHelpers.GetTypeLocator();

            var connectionResolver = new WebJobsConnectionStringProvider();

            var loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(loggerProvider);

            // Unless otherwise specified, use legacy partition management for tests as it makes the task hubs start up faster.
            // These tests run on a single task hub workers, so they don't test partition management anyways, and that is tested
            // in the DTFx repo.
            if (!options.Value.StorageProvider.ContainsKey(nameof(AzureStorageOptions.UseLegacyPartitionManagement)))
            {
                options.Value.StorageProvider.Add(nameof(AzureStorageOptions.UseLegacyPartitionManagement), true);
            }

            platformInformationService = platformInformationService ?? TestHelpers.GetMockPlatformInformationService();

            IDurabilityProviderFactory orchestrationServiceFactory = new AzureStorageDurabilityProviderFactory(
                options,
                connectionResolver,
                nameResolver,
                loggerFactory,
                platformInformationService);

            var extension = new DurableTaskExtension(
                options,
                loggerFactory,
                nameResolver,
                new[] { orchestrationServiceFactory },
                shutdownNotificationService ?? new TestHostShutdownNotificationService(),
                durableHttpMessageHandler,
                lifeCycleNotificationHelper,
                serializerSettingsFactory,
                platformInformationService);

            config.UseDurableTask(extension);

            // Mock INameResolver for not setting EnvironmentVariables.
            if (nameResolver != null)
            {
                config.AddService(nameResolver);
            }

            // Performance is *significantly* worse when dashboard logging is enabled, at least
            // when running in the storage emulator. Disabling to keep tests running quickly.
            config.DashboardConnectionString = null;

            // Add test logger
            config.LoggerFactory = loggerFactory;

            var host = new JobHost(config);

            return(new FunctionsV1HostWrapper(host, options, connectionResolver));
        }
        public static ITestHost CreateJobHost(
            IOptions <DurableTaskOptions> options,
            string storageProvider,
            Type durabilityProviderFactoryType,
            ILoggerProvider loggerProvider,
            INameResolver nameResolver,
            IDurableHttpMessageHandlerFactory durableHttpMessageHandler,
            ILifeCycleNotificationHelper lifeCycleNotificationHelper,
            IMessageSerializerSettingsFactory serializerSettingsFactory,
            Action <ITelemetry> onSend,
            bool addDurableClientFactory)
        {
            // Unless otherwise specified, use legacy partition management for tests as it makes the task hubs start up faster.
            // These tests run on a single task hub workers, so they don't test partition management anyways, and that is tested
            // in the DTFx repo.
            if (!options.Value.StorageProvider.ContainsKey(nameof(AzureStorageOptions.UseLegacyPartitionManagement)))
            {
                options.Value.StorageProvider.Add(nameof(AzureStorageOptions.UseLegacyPartitionManagement), true);
            }

            IHost host = new HostBuilder()
                         .ConfigureLogging(
                loggingBuilder =>
            {
                loggingBuilder.AddProvider(loggerProvider);
            })
                         .ConfigureWebJobs(
                webJobsBuilder =>
            {
                if (addDurableClientFactory)
                {
                    webJobsBuilder.AddDurableClientFactoryDurableTask(options);
                }
                else
                {
                    webJobsBuilder.AddDurableTask(options, storageProvider, durabilityProviderFactoryType);
                }

                webJobsBuilder.AddAzureStorage();
            })
                         .ConfigureServices(
                serviceCollection =>
            {
                ITypeLocator typeLocator = TestHelpers.GetTypeLocator();
                serviceCollection.AddSingleton(typeLocator);
                serviceCollection.AddSingleton(nameResolver);
                serviceCollection.AddSingleton(durableHttpMessageHandler);

                if (lifeCycleNotificationHelper != null)
                {
                    serviceCollection.AddSingleton(lifeCycleNotificationHelper);
                }

                if (serializerSettingsFactory != null)
                {
                    serviceCollection.AddSingleton(serializerSettingsFactory);
                }

                if (onSend != null)
                {
                    serviceCollection.AddSingleton <ITelemetryActivator>(serviceProvider =>
                    {
                        var durableTaskOptions = serviceProvider.GetService <IOptions <DurableTaskOptions> >();
                        var telemetryActivator = new TelemetryActivator(durableTaskOptions)
                        {
                            OnSend = onSend,
                        };
                        return(telemetryActivator);
                    });
                }
            })
                         .Build();

            return(new FunctionsV2HostWrapper(host, options, nameResolver));
        }