public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProvider, IScopeProvider scopeProvider, IDateTimeProvider datetimeProvider, IExecutionResultProcessor executionResultProcessor, ILifeCycleEventPublisher publisher, ICancellationProcessor cancellationProcessor, WorkflowOptions options, ILoggerFactory loggerFactory) { _serviceProvider = serviceProvider; _scopeProvider = scopeProvider; _registry = registry; _datetimeProvider = datetimeProvider; _publisher = publisher; _cancellationProcessor = cancellationProcessor; _options = options; _logger = loggerFactory.CreateLogger <WorkflowExecutor>(); _executionResultProcessor = executionResultProcessor; }
public WorkflowHost(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, WorkflowOptions options, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IEnumerable <IBackgroundTask> backgroundTasks) { PersistenceStore = persistenceStore; QueueProvider = queueProvider; Options = options; Logger = loggerFactory.CreateLogger <WorkflowHost>(); _serviceProvider = serviceProvider; Registry = registry; LockProvider = lockProvider; _backgroundTasks = backgroundTasks; persistenceStore.EnsureStoreExists(); }
public static IServiceCollection AddWorkflow(this IServiceCollection services, Action <WorkflowOptions> setupAction = null) { if (services.Any(x => x.ServiceType == typeof(WorkflowOptions))) { throw new InvalidOperationException("Workflow services already registered"); } var options = new WorkflowOptions(services); setupAction?.Invoke(options); services.AddSingleton <ISingletonMemoryProvider, MemoryPersistenceProvider>(); services.AddTransient <IPersistenceProvider>(options.PersistanceFactory); services.AddSingleton <IQueueProvider>(options.QueueFactory); services.AddSingleton <IDistributedLockProvider>(options.LockFactory); services.AddSingleton <ILifeCycleEventHub>(options.EventHubFactory); services.AddSingleton <ISearchIndex>(options.SearchIndexFactory); services.AddSingleton <IWorkflowRegistry, WorkflowRegistry>(); services.AddSingleton <WorkflowOptions>(options); services.AddSingleton <ILifeCycleEventPublisher, LifeCycleEventPublisher>(); services.AddTransient <IBackgroundTask, WorkflowConsumer>(); services.AddTransient <IBackgroundTask, EventConsumer>(); services.AddTransient <IBackgroundTask, IndexConsumer>(); services.AddTransient <IBackgroundTask, RunnablePoller>(); services.AddTransient <IBackgroundTask>(sp => sp.GetService <ILifeCycleEventPublisher>()); services.AddTransient <IWorkflowErrorHandler, CompensateHandler>(); services.AddTransient <IWorkflowErrorHandler, RetryHandler>(); services.AddTransient <IWorkflowErrorHandler, TerminateHandler>(); services.AddTransient <IWorkflowErrorHandler, SuspendHandler>(); services.AddSingleton <IWorkflowController, WorkflowController>(); services.AddSingleton <IWorkflowHost, WorkflowHost>(); services.AddTransient <IScopeProvider, ScopeProvider>(); services.AddTransient <IWorkflowExecutor, WorkflowExecutor>(); services.AddTransient <ICancellationProcessor, CancellationProcessor>(); services.AddTransient <IWorkflowBuilder, WorkflowBuilder>(); services.AddTransient <IDateTimeProvider, DateTimeProvider>(); services.AddTransient <IExecutionResultProcessor, ExecutionResultProcessor>(); services.AddTransient <IExecutionPointerFactory, ExecutionPointerFactory>(); services.AddTransient <IPooledObjectPolicy <IPersistenceProvider>, InjectedObjectPoolPolicy <IPersistenceProvider> >(); services.AddTransient <IPooledObjectPolicy <IWorkflowExecutor>, InjectedObjectPoolPolicy <IWorkflowExecutor> >(); services.AddTransient <ISyncWorkflowRunner, SyncWorkflowRunner>(); services.AddTransient <IDefinitionLoader, DefinitionLoader>(); services.AddTransient <Foreach>(); return(services); }
public WorkflowHost(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, WorkflowOptions options, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IEnumerable <IBackgroundTask> backgroundTasks, IWorkflowController workflowController, ILifeCycleEventHub lifeCycleEventHub) { PersistenceStore = persistenceStore; QueueProvider = queueProvider; Options = options; Logger = loggerFactory.CreateLogger <WorkflowHost>(); _serviceProvider = serviceProvider; Registry = registry; LockProvider = lockProvider; _backgroundTasks = backgroundTasks; _workflowController = workflowController; lifeCycleEventHub.Subscribe(HandleLifeCycleEvent); }
public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, IConnectionFactory connectionFactory) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (connectionFactory == null) { throw new ArgumentNullException(nameof(connectionFactory)); } return(options .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(name))); }
public ExecutionResultProcessorFixture() { PointerFactory = A.Fake <IExecutionPointerFactory>(); DateTimeProvider = A.Fake <IClockProvider>(); Options = new WorkflowOptions(); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); //config logging var loggerFactory = new LoggerFactory(); Subject = new ExecutionResultProcessor(PointerFactory, Options, loggerFactory); }
public WorkflowHost(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, WorkflowOptions options, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IEnumerable <IBackgroundTask> backgroundTasks, IWorkflowController workflowController, ILifeCycleEventHub lifeCycleEventHub, ISearchIndex searchIndex, IActivityController activityController) { PersistenceStore = persistenceStore; QueueProvider = queueProvider; Options = options; Logger = loggerFactory.CreateLogger <WorkflowHost>(); _serviceProvider = serviceProvider; Registry = registry; LockProvider = lockProvider; _backgroundTasks = backgroundTasks; _workflowController = workflowController; _searchIndex = searchIndex; _activityController = activityController; _lifeCycleEventHub = lifeCycleEventHub; }
public WorkflowExecutorFixture() { Host = A.Fake <IWorkflowHost>(); PersistenceProvider = A.Fake <IPersistenceProvider>(); ServiceProvider = A.Fake <IServiceProvider>(); ScopeProvider = A.Fake <IScopeProvider>(); Registry = A.Fake <IWorkflowRegistry>(); ResultProcesser = A.Fake <IExecutionResultProcessor>(); EventHub = A.Fake <ILifeCycleEventPublisher>(); CancellationProcessor = A.Fake <ICancellationProcessor>(); DateTimeProvider = A.Fake <IDateTimeProvider>(); MiddlewareRunner = A.Fake <IWorkflowMiddlewareRunner>(); StepExecutor = A.Fake <IStepExecutor>(); Options = new WorkflowOptions(A.Fake <IServiceCollection>()); var scope = A.Fake <IServiceScope>(); A.CallTo(() => ScopeProvider.CreateScope(A <IStepExecutionContext> ._)).Returns(scope); A.CallTo(() => scope.ServiceProvider).Returns(ServiceProvider); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); A.CallTo(() => DateTimeProvider.UtcNow).Returns(DateTime.UtcNow); A .CallTo(() => ServiceProvider.GetService(typeof(IWorkflowMiddlewareRunner))) .Returns(MiddlewareRunner); A .CallTo(() => ServiceProvider.GetService(typeof(IStepExecutor))) .Returns(StepExecutor); A.CallTo(() => MiddlewareRunner .RunPostMiddleware(A <WorkflowInstance> ._, A <WorkflowDefinition> ._)) .Returns(Task.CompletedTask); A.CallTo(() => StepExecutor.ExecuteStep(A <IStepExecutionContext> ._, A <IStepBody> ._)) .ReturnsLazily(call => call.Arguments[1].As <IStepBody>().RunAsync( call.Arguments[0].As <IStepExecutionContext>())); //config logging var loggerFactory = new LoggerFactory(); //loggerFactory.AddConsole(LogLevel.Debug); Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, loggerFactory); }
public static WorkflowOptions UseMongoDB(this WorkflowOptions options, string mongoUrl, string databaseName) { options.UsePersistence(sp => { var client = new MongoClient(mongoUrl); var db = client.GetDatabase(databaseName); return(new MongoPersistenceProvider(db)); }); options.Services.AddTransient <IWorkflowPurger>(sp => { var client = new MongoClient(mongoUrl); var db = client.GetDatabase(databaseName); return(new WorkflowPurger(db)); }); return(options); }
public ExecutionResultProcessorFixture() { PointerFactory = A.Fake <IExecutionPointerFactory>(); DateTimeProvider = A.Fake <IDateTimeProvider>(); Options = new WorkflowOptions(A.Fake <IServiceCollection>()); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); //config logging var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole(LogLevel.Debug); Subject = new ExecutionResultProcessor(PointerFactory, DateTimeProvider, Options, loggerFactory); }
public void LaunchWorkflow_ShouldInvokeCallToGetNextAction_When_Called() { WorkflowOptions launchOptions = new WorkflowOptions() { ExecutionTimeout = 1000, StateObject = RequestBuilder.LinkRequestGetDeviceStatus() }; subject.LaunchWorkflow(launchOptions); var stack = TestHelper.Helper.GetFieldValueFromInstance <Stack <object> >("savedStackState", false, false, subject); Assert.Empty(stack); subject.Dispose(); }
public static WorkflowOptions UseCosmosDbPersistence( this WorkflowOptions options, string connectionString, string databaseId, CosmosDbStorageOptions cosmosDbStorageOptions = null) { if (cosmosDbStorageOptions == null) { cosmosDbStorageOptions = new CosmosDbStorageOptions(); } options.Services.AddSingleton <ICosmosClientFactory>(sp => new CosmosClientFactory(connectionString)); options.Services.AddTransient <ICosmosDbProvisioner>(sp => new CosmosDbProvisioner(sp.GetService <ICosmosClientFactory>(), cosmosDbStorageOptions)); options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService <ICosmosClientFactory>(), databaseId, sp.GetService <ICosmosDbProvisioner>(), cosmosDbStorageOptions)); return(options); }
public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, RabbitMqConnectionFactory rabbitMqConnectionFactory) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (rabbitMqConnectionFactory == null) { throw new ArgumentNullException(nameof(rabbitMqConnectionFactory)); } options.Services.AddSingleton(rabbitMqConnectionFactory); options.Services.TryAddSingleton <IRabbitMqQueueNameProvider, DefaultRabbitMqQueueNameProvider>(); options.UseQueueProvider(RabbitMqQueueProviderFactory); return(options); }
public ExecutionResultProcessorFixture() { PointerFactory = A.Fake <IExecutionPointerFactory>(); DateTimeProvider = A.Fake <IDateTimeProvider>(); EventHub = A.Fake <ILifeCycleEventPublisher>(); ErrorHandlers = new HashSet <IWorkflowErrorHandler>(); Options = new WorkflowOptions(A.Fake <IServiceCollection>()); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); //config logging var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole(LogLevel.Debug); Subject = new ExecutionResultProcessor(PointerFactory, DateTimeProvider, EventHub, ErrorHandlers, Options, loggerFactory); }
public WorkflowExecutorFixture() { Host = A.Fake <IWorkflowHost>(); PersistenceProvider = A.Fake <IPersistenceProvider>(); ServiceProvider = A.Fake <IServiceProvider>(); Registry = A.Fake <IWorkflowRegistry>(); ResultProcesser = A.Fake <IExecutionResultProcessor>(); DateTimeProvider = A.Fake <IClockProvider>(); Options = new WorkflowOptions(); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); //config logging var loggerFactory = new LoggerFactory(); Subject = new WorkflowExecutor(Registry, ServiceProvider, ResultProcesser, Options, loggerFactory); }
public async Task Activity_Fail() { await SyncContext.ClearAsync; // Verify that we can call a workflow that calls an activity // which throws an exception and that we see the error. var options = new WorkflowOptions() { TaskStartToCloseTimeout = TimeSpan.FromSeconds(60) }; var stub = client.NewWorkflowStub <IWorkflowActivityFail>(options); var error = await stub.RunAsync(); Assert.NotNull(error); Assert.Contains("ArgumentException", error); Assert.Contains("forced-failure", error); }
public WorkflowExecutorFixture() { Host = A.Fake <IWorkflowHost>(); PersistenceProvider = A.Fake <IPersistenceProvider>(); ServiceProvider = A.Fake <IServiceProvider>(); Registry = A.Fake <IWorkflowRegistry>(); ResultProcesser = A.Fake <IExecutionResultProcessor>(); DateTimeProvider = A.Fake <IDateTimeProvider>(); Options = new WorkflowOptions(A.Fake <IServiceCollection>()); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); //config logging var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole(LogLevel.Debug); Subject = new WorkflowExecutor(Registry, ServiceProvider, DateTimeProvider, ResultProcesser, Options, loggerFactory, PersistenceProvider); }
public void LaunchWorkflow_ShouldFireGlobalTimer_When_Timeout() { LinkRequest linkRequest = RequestBuilder.LinkRequestGetDeviceStatus(); WorkflowOptions launchOptions = new WorkflowOptions() { ExecutionTimeout = linkRequest.Timeout, StateObject = linkRequest }; subject.LaunchWorkflow(launchOptions); // linkRequest.Timeout should be less then 2000 ms. asyncManager.WaitFor(); Assert.Equal(subject.Complete(stateIDeviceSubStateAction), Task.CompletedTask); Assert.True(subject.DidTimeoutOccur); subject.Dispose(); }
/// <summary> /// Use SQL Server as a queue provider /// </summary> /// <param name="options"></param> /// <param name="connectionString"></param> /// <returns></returns> public static WorkflowOptions UseSqlServerBroker(this WorkflowOptions options, string connectionString, bool canCreateDb, bool canMigrateDb) { options.Services.AddTransient <IQueueConfigProvider, QueueConfigProvider>(); options.Services.AddTransient <ISqlCommandExecutor, SqlCommandExecutor>(); options.Services.AddTransient <ISqlServerQueueProviderMigrator>(sp => new SqlServerQueueProviderMigrator(connectionString, sp.GetService <IQueueConfigProvider>(), sp.GetService <ISqlCommandExecutor>())); var sqlOptions = new SqlServerQueueProviderOptions() { ConnectionString = connectionString, CanCreateDb = canCreateDb, CanMigrateDb = canMigrateDb }; options.UseQueueProvider(sp => { return(new SqlServerQueueProvider(sqlOptions, sp.GetService <IQueueConfigProvider>(), sp.GetService <ISqlServerQueueProviderMigrator>(), sp.GetService <ISqlCommandExecutor>())); }); return(options); }
public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, IConnectionFactory connectionFactory, IEnumerable <string> hostnames) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (connectionFactory == null) { throw new ArgumentNullException(nameof(connectionFactory)); } if (hostnames == null) { throw new ArgumentNullException(nameof(hostnames)); } return(options .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(hostnames.ToList(), name))); }
public static WorkflowOptions UseRavenDB(this WorkflowOptions options, RavenStoreOptions configOptions) { IDocumentStore store = new DocumentStore { Urls = new[] { configOptions.ServerUrl }, Database = configOptions.DatabaseName, Certificate = new X509Certificate2(configOptions.CertificatePath, configOptions.CertificatePassword) }.Initialize(); options.UsePersistence(sp => { return(new RavendbPersistenceProvider(store)); }); options.Services.AddTransient <IWorkflowPurger>(sp => { return(new WorkflowPurger(store)); }); return(options); }
public static void AddWorkflow(this IServiceCollection services, Action <WorkflowOptions> setupAction = null) { WorkflowOptions options = new WorkflowOptions(); if (setupAction != null) { setupAction.Invoke(options); } services.AddTransient <IPersistenceProvider>(options.PersistanceFactory); services.AddSingleton <IQueueProvider>(options.QueueFactory); services.AddSingleton <IDistributedLockProvider>(options.LockFactory); services.AddSingleton <IWorkflowRegistry, WorkflowRegistry>(); services.AddSingleton <WorkflowOptions>(options); services.AddSingleton <IWorkflowHost, WorkflowHost>(); services.AddTransient <IWorkflowExecutor, WorkflowExecutor>(); services.AddTransient <IWorkflowBuilder, WorkflowBuilder>(); services.AddTransient <IWorkflowThread, WorkflowThread>(); services.AddTransient <IEventThread, EventThread>(); services.AddTransient <IRunnablePoller, RunnablePoller>(); services.AddTransient <Foreach>(); }
public async Task Workflow_ExternalIdNoReuse() { await SyncContext.Clear; // Verify that default Cadence settings allow duplicate workflow IDs // and then change this to prevent reuse. var settings = fixture.Settings.Clone(); Assert.Equal(WorkflowIdReusePolicy.AllowDuplicate, settings.WorkflowIdReusePolicy); settings.WorkflowIdReusePolicy = WorkflowIdReusePolicy.RejectDuplicate; using (var client = await CadenceClient.ConnectAsync(settings)) { await client.RegisterAssemblyAsync(Assembly.GetExecutingAssembly()); await client.StartWorkerAsync(CadenceTestHelper.TaskList); var options = new WorkflowOptions() { WorkflowId = $"Workflow_ExternalIdNoReuse-{Guid.NewGuid().ToString("d")}" }; // Do the first run; this should succeed. var stub = client.NewWorkflowStub <IWorkflowIdReuse>(options); Assert.Equal("Hello Jack!", await stub.HelloAsync("Jack")); // Do the second run with the same ID. This shouldn't actually start // another workflow and will return the result from the original // workflow instead. stub = client.NewWorkflowStub <IWorkflowIdReuse>(options); Assert.Equal("Hello Jack!", await stub.HelloAsync("Jill")); } }
public async Task Simultaneous() { await SyncContext.Clear; // We're going to establish two simultaneous client connections, // register a workflow on each, and then verify that these workflows work. using (var client1 = await CadenceClient.ConnectAsync(fixture.Settings)) { await client1.RegisterWorkflowAsync <WorkflowWithResult1>(); await client1.StartWorkerAsync("tasklist-1"); using (var client2 = await CadenceClient.ConnectAsync(fixture.Settings)) { await client2.RegisterWorkflowAsync <WorkflowWithResult2>(); await client2.StartWorkerAsync("tasklist-2"); var options1 = new WorkflowOptions() { TaskList = "tasklist-1" }; var options2 = new WorkflowOptions() { TaskList = "tasklist-2" }; var stub1 = client1.NewWorkflowStub <IWorkflowWithResult1>(options: options1); var stub2 = client2.NewWorkflowStub <IWorkflowWithResult2>(options: options2); Assert.Equal("WF1 says: Hello Jeff!", await stub1.HelloAsync("Jeff")); Assert.Equal("WF2 says: Hello Jeff!", await stub2.HelloAsync("Jeff")); } } }
public static IServiceCollection AddWorkflow(this IServiceCollection services, Action <WorkflowOptions> setupAction = null) { if (services.Any(x => x.ServiceType == typeof(WorkflowOptions))) { throw new InvalidOperationException("Workflow services already registered"); } var options = new WorkflowOptions(services); setupAction?.Invoke(options); services.AddTransient <IPersistenceProvider>(options.PersistanceFactory); services.AddSingleton <IQueueProvider>(options.QueueFactory); services.AddSingleton <IDistributedLockProvider>(options.LockFactory); services.AddSingleton <IWorkflowRegistry, WorkflowRegistry>(); services.AddSingleton <WorkflowOptions>(options); services.AddTransient <IBackgroundTask, WorkflowConsumer>(); services.AddTransient <IBackgroundTask, EventConsumer>(); services.AddTransient <IBackgroundTask, RunnablePoller>(); services.AddSingleton <IWorkflowController, WorkflowController>(); services.AddSingleton <IWorkflowHost, WorkflowHost>(); services.AddTransient <IWorkflowExecutor, WorkflowExecutor>(); services.AddTransient <IWorkflowBuilder, WorkflowBuilder>(); services.AddTransient <IDateTimeProvider, DateTimeProvider>(); services.AddTransient <IExecutionResultProcessor, ExecutionResultProcessor>(); services.AddTransient <IExecutionPointerFactory, ExecutionPointerFactory>(); services.AddTransient <IPooledObjectPolicy <IPersistenceProvider>, InjectedObjectPoolPolicy <IPersistenceProvider> >(); services.AddTransient <IPooledObjectPolicy <IWorkflowExecutor>, InjectedObjectPoolPolicy <IWorkflowExecutor> >(); services.AddTransient <IDefinitionLoader, DefinitionLoader>(); services.AddTransient <Foreach>(); return(services); }
public static WorkflowOptions UseMongoDB( this WorkflowOptions options, string mongoUrl, string databaseName, Action <MongoClientSettings> configureClient = default) { options.UsePersistence(sp => { var mongoClientSettings = MongoClientSettings.FromConnectionString(mongoUrl); configureClient?.Invoke(mongoClientSettings); var client = new MongoClient(mongoClientSettings); var db = client.GetDatabase(databaseName); return(new MongoPersistenceProvider(db)); }); options.Services.AddTransient <IWorkflowPurger>(sp => { var mongoClientSettings = MongoClientSettings.FromConnectionString(mongoUrl); configureClient?.Invoke(mongoClientSettings); var client = new MongoClient(mongoClientSettings); var db = client.GetDatabase(databaseName); return(new WorkflowPurger(db)); }); return(options); }
public void PublishNotification_Disabled() { // Arrange var eventHubMock = new Mock <ILifeCycleEventHub>(); var serviceCollectionMock = new Mock <IServiceCollection>(); var workflowOptions = new WorkflowOptions(serviceCollectionMock.Object) { EnableLifeCycleEventsPublisher = false }; eventHubMock .Setup(hub => hub.PublishNotification(It.IsAny <StepCompleted>())) .Returns(Task.CompletedTask); LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, workflowOptions, new LoggerFactory()); // Act publisher.Start(); publisher.PublishNotification(new StepCompleted()); publisher.Stop(); // Assert eventHubMock.Verify(hub => hub.PublishNotification(It.IsAny <StepCompleted>()), Times.Never()); }
public WorkflowExecutorFixture() { //setup dependency injection IServiceCollection services = new ServiceCollection(); services.AddLogging(); Options = new WorkflowOptions(); services.AddTransient <IWorkflowBuilder, WorkflowBuilder>(); services.AddTransient <IWorkflowRegistry, WorkflowRegistry>(); Host = A.Fake <IWorkflowHost>(); PersistenceProvider = A.Fake <IPersistenceProvider>(); var serviceProvider = services.BuildServiceProvider(); //config logging var loggerFactory = serviceProvider.GetService <ILoggerFactory>(); loggerFactory.AddConsole(LogLevel.Debug); Registry = serviceProvider.GetService <IWorkflowRegistry>(); Subject = new WorkflowExecutor(Registry, serviceProvider, new DateTimeProvider(), loggerFactory); }
public static WorkflowOptions UseMySqlLocking(this WorkflowOptions options, string connectionString) { options.UseDistributedLockManager(sp => new MySqlLockProvider(connectionString, sp.GetService <ILoggerFactory>())); return(options); }
protected QueueConsumer(IQueueProvider queueProvider, ILoggerFactory loggerFactory, WorkflowOptions options) { QueueProvider = queueProvider; Options = options; Logger = loggerFactory.CreateLogger(GetType()); }