WIP #564 - Rename & alter temporal activity setup

Temporal activities no longer have a generalised extension method
for registering them with a service collecton.  It is still static and has
the same rough shape as an extension method.  This way it is less
visible and less likely to be called by accident.

Also in-line with changes in this branch, things have been renamed
  Timers → Temporal
This commit is contained in:
Craig Fowler 2021-02-28 15:44:23 +00:00 committed by Sipke Schoorstra
parent a61ecda036
commit ed81b5679a
19 changed files with 98 additions and 62 deletions

View file

@ -0,0 +1,46 @@
using System;
using Elsa.Activities.Temporal.Bookmarks;
using Elsa.Activities.Temporal.Handlers;
using Elsa.Activities.Temporal.Options;
using Elsa.Activities.Temporal.StartupTasks;
using Elsa.Runtime;
using Microsoft.Extensions.DependencyInjection;
// ReSharper disable once CheckNamespace
namespace Elsa.Activities.Temporal
{
public static class CommonTemporalActivityServices
{
/// <summary>
/// Adds services which are common to temporal activities. This method is intended for internal use only.
/// </summary>
/// <remarks>
/// <para>
/// Instead of calling this method directly, when setting up Elsa for temporal (time-based) activities,
/// developers should make use of one of the implementation-specific add-temporal-activities methods.
/// Without providing an implementation-specific configuration in <paramref name="configure"/>, this method
/// will not fully set up the temporal activities.
/// </para>
/// </remarks>
/// <param name="options">Elsa options</param>
/// <param name="configure">The configuration for temporal activity options</param>
public static void AddCommonTemporalActivities(ElsaOptions options, Action<TimersOptions>? configure = default)
{
var timersOptions = new TimersOptions(options.Services);
configure?.Invoke(timersOptions);
options.Services
.AddNotificationHandlers(typeof(RemoveScheduledTriggers))
.AddStartupTask<StartJobs>()
.AddBookmarkProvider<TimerBookmarkProvider>()
.AddBookmarkProvider<CronBookmarkProvider>()
.AddBookmarkProvider<StartAtBookmarkProvider>();
options
.AddActivity<Cron>()
.AddActivity<Timer>()
.AddActivity<StartAt>()
.AddActivity<ClearTimer>();
}
}
}

View file

@ -1,34 +0,0 @@
using System;
using Elsa;
using Elsa.Activities.Temporal;
using Elsa.Activities.Temporal.Bookmarks;
using Elsa.Activities.Temporal.Handlers;
using Elsa.Activities.Temporal.Options;
using Elsa.Activities.Temporal.StartupTasks;
using Elsa.Runtime;
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
public static ElsaOptions AddTimerActivities(this ElsaOptions options, Action<TimersOptions>? configure = default)
{
var timersOptions = new TimersOptions(options.Services);
configure?.Invoke(timersOptions);
options.Services
.AddNotificationHandlers(typeof(RemoveScheduledTriggers))
.AddStartupTask<StartJobs>()
.AddBookmarkProvider<TimerBookmarkProvider>()
.AddBookmarkProvider<CronBookmarkProvider>()
.AddBookmarkProvider<StartAtBookmarkProvider>();
return options
.AddActivity<Cron>()
.AddActivity<Timer>()
.AddActivity<StartAt>()
.AddActivity<ClearTimer>();
}
}
}

View file

@ -1,12 +1,23 @@
using System;
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
using Elsa.Activities.Temporal;
// ReSharper disable once CheckNamespace
namespace Elsa
{
public static class ElsaOptionsExtensions
{
public static ElsaOptions AddHangfireTimerActivities(this ElsaOptions options, Action<IGlobalConfiguration> configure) => options.AddTimerActivities(timer => timer.UseHangfire(configure));
/// <summary>
/// Adds temporal (time-based) activities to Elsa, using the Hangfire implementation.
/// </summary>
/// <param name="options">Elsa options</param>
/// <param name="configure">A Hangfire configuration callback</param>
/// <returns>The Elsa options, enabling method chaining</returns>
public static ElsaOptions AddHangfireTemporalActivities(this ElsaOptions options,
Action<IGlobalConfiguration> configure)
{
CommonTemporalActivityServices.AddCommonTemporalActivities(options, timer => timer.UseHangfire(configure));
return options;
}
}
}

View file

@ -1,5 +1,5 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Elsa.Activities.Temporal;
using Quartz;
// ReSharper disable once CheckNamespace
@ -7,7 +7,19 @@ namespace Elsa
{
public static class ElsaOptionsExtensions
{
public static ElsaOptions AddQuartzTimerActivities(this ElsaOptions options, Action<QuartzOptions>? configureOptions = default, Action<IServiceCollectionQuartzConfigurator>? configureQuartz = default) =>
options.AddTimerActivities(timer => timer.UseQuartzProvider(configureOptions, configureQuartz));
/// <summary>
/// Adds temporal (time-based) activities to Elsa, using the Quartz implementation.
/// </summary>
/// <param name="options">Elsa options</param>
/// <param name="configure">An optional Quartz configuration callback</param>
/// <param name="configureQuartz">An optional service collection Quartz configuration callback</param>
/// <returns>The Elsa options, enabling method chaining</returns>
public static ElsaOptions AddQuartzTemporalActivities(this ElsaOptions options,
Action<QuartzOptions>? configure = default,
Action<IServiceCollectionQuartzConfigurator>? configureQuartz = default)
{
CommonTemporalActivityServices.AddCommonTemporalActivities(options, timer => timer.UseQuartzProvider(configure, configureQuartz));
return options;
}
}
}

View file

@ -15,7 +15,7 @@ namespace Elsa.Samples.ForkJoinTimerAndSignalHttp
services
.AddElsa(options => options
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddWorkflow<DemoWorkflow>()
)
.AddHostedService<WorkflowStarter<DemoWorkflow>>();

View file

@ -16,7 +16,7 @@ namespace Elsa.Samples.Interrupts
.AddElsa(options => options
.AddConsoleActivities()
.AddHttpActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddActivity<Sleep>())
.StartWorkflow<InterruptableWorkflow>();
}

View file

@ -34,7 +34,7 @@ namespace ElsaDashboard.Samples.Monolith
.AddConsoleActivities()
.AddHttpActivities(elsaSection.GetSection("Http").Bind)
.AddEmailActivities(elsaSection.GetSection("Smtp").Bind)
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddWorkflowsFrom<Startup>()
);

View file

@ -29,7 +29,7 @@ namespace Elsa.Samples.Server.Host
.AddConsoleActivities()
.AddHttpActivities(elsaSection.GetSection("Http").Bind)
.AddEmailActivities(elsaSection.GetSection("Smtp").Bind)
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddWorkflowsFrom<Startup>()
);

View file

@ -25,7 +25,7 @@ namespace Elsa.Samples.AzureServiceBusWorker
//.UseYesSqlPersistence(yesSql => yesSql.UseSqLite("Data Source=elsa.yessql.db;Cache=Shared", IsolationLevel.ReadUncommitted))
.UseEntityFrameworkPersistence(db => db.UseSqlite("Data Source=elsa.efcore.db;Cache=Shared", sqlite => sqlite.MigrationsAssembly(typeof(SqliteElsaContextFactory).Assembly.GetName().Name)), true)
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddAzureServiceBusActivities(o => o.ConnectionString = hostContext.Configuration.GetConnectionString("AzureServiceBus"))
.AddWorkflow<ProducerWorkflow>()
.AddWorkflow<ConsumerWorkflow>());

View file

@ -17,7 +17,7 @@ namespace Elsa.Samples.BreakLoop
services
.AddElsa(options => options.UseYesSqlPersistence()
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddActivitiesFrom<Program>()
.AddWorkflowsFrom<Program>());

View file

@ -19,7 +19,7 @@ namespace Elsa.Samples.CustomAttributesChildWorker
{
services
.AddElsa(options => options
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddConsoleActivities()
.AddRebusActivities<OrderReceived>()
.AddWorkflow<GenerateOrdersWorkflow>()

View file

@ -20,7 +20,7 @@ namespace Elsa.Samples.DistributedLock
services
.AddElsa(options => options.UseRedisLockProvider("localhost:6379,abortConnect=false")
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddWorkflow<RecurringWorkflow>());
});
}

View file

@ -20,7 +20,7 @@ namespace Elsa.Samples.Faulting
.AddElsa(options => options
.UseYesSqlPersistence()
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddWorkflow<FaultyWorkflow>());
});
}

View file

@ -19,7 +19,7 @@ namespace Elsa.Samples.MultiTenantChildWorker
{
services
.AddElsa(options => options
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddConsoleActivities()
.AddRebusActivities<OrderReceived>()
.AddWorkflow<GenerateOrdersWorkflow>()

View file

@ -26,7 +26,7 @@ namespace Elsa.Samples.RebusWorker
db => db.MigrationsAssembly(typeof(SqliteElsaContextFactory).Assembly.GetName().Name));
}, true)
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddRebusActivities<Greeting>()
.AddWorkflow<ProducerWorkflow>()
.AddWorkflow<ConsumerWorkflow>());

View file

@ -18,7 +18,7 @@ namespace Elsa.Samples.Timers
services
.AddElsa(options => options
.AddConsoleActivities()
.AddHangfireTimerActivities(hangfire => hangfire.UseSqlServerStorage("Server=(localdb)\\MSSQLLocalDB;Database=ElsaHangfire;Trusted_Connection=True;MultipleActiveResultSets=true"))
.AddHangfireTemporalActivities(hangfire => hangfire.UseSqlServerStorage("Server=(localdb)\\MSSQLLocalDB;Database=ElsaHangfire;Trusted_Connection=True;MultipleActiveResultSets=true"))
.AddWorkflow<RecurringTaskWorkflow>()
.AddWorkflow<CronTaskWorkflow>()
.AddWorkflow<CancelTimerWorkflow>()

View file

@ -21,7 +21,7 @@ namespace Elsa.Samples.Timers
.AddElsa(options => options
.UseEntityFrameworkPersistence(ef => ef.UseSqlite())
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddActivity<MyContainer1>()
.AddActivity<MyContainer2>()
//.AddWorkflow<SingletonTimerWorkflow>()

View file

@ -19,7 +19,7 @@ namespace Elsa.Samples.WhileLoopWorker
services
.AddElsa(options => options.UseYesSqlPersistence()
.AddConsoleActivities()
.AddQuartzTimerActivities()
.AddQuartzTemporalActivities()
.AddActivity<MakePhoneCall>()
.AddWorkflow<PhoneCallWorkflow>())
.AddSingleton<PhoneCallService>()

View file

@ -5,17 +5,18 @@ using Xunit;
using Hangfire;
using System.Threading.Tasks;
using System.Threading;
using Elsa.Activities.Temporal;
namespace Elsa.UnitTests.Extensions
{
public class TemporalServiceCollectionExtensionsTests
{
[Fact(DisplayName = "Starting a hosted app which uses only AddTimerActivities should throw InvalidOperationException because of the missing impl")]
public void AddTimerActivitiesThrowsDuringStartupIfNoTemporalImplementationPresent()
[Fact(DisplayName = "Starting a hosted app which uses only AddCommonTemporalActivities should throw InvalidOperationException because of the missing impl")]
public void AddCommonTemporalActivitiesThrowsDuringStartupIfNoTemporalImplementationPresent()
{
var hostBuilder = CreateHostBuilderUsingServices(services => {
services.AddElsa(elsa => {
elsa.AddTimerActivities();
CommonTemporalActivityServices.AddCommonTemporalActivities(elsa);
});
});
@ -32,12 +33,12 @@ namespace Elsa.UnitTests.Extensions
}
}
[Fact(DisplayName = "Starting a hosted app which uses AddHangfireTimerActivities should not throw")]
public void AddHangfireTimerActivitiesDoesNotThrowDuringStartup()
[Fact(DisplayName = "Starting a hosted app which uses AddHangfireTemporalActivities should not throw")]
public void AddHangfireTemporalActivitiesDoesNotThrowDuringStartup()
{
var hostBuilder = CreateHostBuilderUsingServices(services => {
services.AddElsa(elsa => {
elsa.AddHangfireTimerActivities(config => config.UseInMemoryStorage());
elsa.AddHangfireTemporalActivities(config => config.UseInMemoryStorage());
});
});
@ -56,12 +57,12 @@ namespace Elsa.UnitTests.Extensions
}
}
[Fact(DisplayName = "Starting a hosted app which uses AddQuartzTimerActivities should not throw")]
public void AddQuartzTimerActivitiesDoesNotThrowDuringStartup()
[Fact(DisplayName = "Starting a hosted app which uses AddQuartzTemporalActivities should not throw")]
public void AddQuartzTemporalActivitiesDoesNotThrowDuringStartup()
{
var hostBuilder = CreateHostBuilderUsingServices(services => {
services.AddElsa(elsa => {
elsa.AddQuartzTimerActivities();
elsa.AddQuartzTemporalActivities();
});
});