diff --git a/src/modules/Elsa.Common/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa.Common/Extensions/DependencyInjectionExtensions.cs index b36c7f024..b4c8a42b2 100644 --- a/src/modules/Elsa.Common/Extensions/DependencyInjectionExtensions.cs +++ b/src/modules/Elsa.Common/Extensions/DependencyInjectionExtensions.cs @@ -1,4 +1,5 @@ using Elsa.Common; +using Elsa.Common.RecurringTasks; using Elsa.Common.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -44,4 +45,10 @@ public static class DependencyInjectionExtensions { return services.AddScoped(); } + + public static IServiceCollection AddRecurringTask(this IServiceCollection services, TimeSpan interval) where T : class, IRecurringTask + { + services.Configure(options => options.Schedule.ConfigureTask(interval)); + return services.AddRecurringTask(); + } } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/CleanupStrategies/DeleteActivityExecutionRecordStrategy.cs b/src/modules/Elsa.Retention/CleanupStrategies/DeleteActivityExecutionRecordStrategy.cs index dec5d49a0..e43828c9d 100644 --- a/src/modules/Elsa.Retention/CleanupStrategies/DeleteActivityExecutionRecordStrategy.cs +++ b/src/modules/Elsa.Retention/CleanupStrategies/DeleteActivityExecutionRecordStrategy.cs @@ -9,29 +9,20 @@ namespace Elsa.Retention.CleanupStrategies; /// /// Deletes activity execution records. /// -public class DeleteActivityExecutionRecordStrategy : IDeletionCleanupStrategy +public class DeleteActivityExecutionRecordStrategy(IActivityExecutionStore store, ILogger logger) : IDeletionCleanupStrategy { - private readonly ILogger _logger; - private readonly IActivityExecutionStore _store; - - public DeleteActivityExecutionRecordStrategy(IActivityExecutionStore store, ILogger logger) - { - _store = store; - _logger = logger; - } - public async Task Cleanup(ICollection collection) { - ActivityExecutionRecordFilter filter = new() + var filter = new ActivityExecutionRecordFilter() { Ids = collection.Select(x => x.Id).ToList() }; - long deletedRecords = await _store.DeleteManyAsync(filter); + var deletedRecords = await store.DeleteManyAsync(filter); if (deletedRecords != collection.Count) { - _logger.LogWarning("Expected to delete {Expected} activity execution records, actually deleted {Actual} activity execution records", collection.Count, deletedRecords); + logger.LogWarning("Expected to delete {Expected} activity execution records, actually deleted {Actual} activity execution records", collection.Count, deletedRecords); } } } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/CleanupStrategies/DeleteBookmarkStrategy.cs b/src/modules/Elsa.Retention/CleanupStrategies/DeleteBookmarkStrategy.cs index af13d77fa..dc7ba248a 100644 --- a/src/modules/Elsa.Retention/CleanupStrategies/DeleteBookmarkStrategy.cs +++ b/src/modules/Elsa.Retention/CleanupStrategies/DeleteBookmarkStrategy.cs @@ -9,29 +9,20 @@ namespace Elsa.Retention.CleanupStrategies; /// /// Deletes a collection of bookmarks /// -public class DeleteBookmarkStrategy : IDeletionCleanupStrategy +public class DeleteBookmarkStrategy(IBookmarkStore store, ILogger logger) : IDeletionCleanupStrategy { - private readonly ILogger _logger; - private readonly IBookmarkStore _store; - - public DeleteBookmarkStrategy(IBookmarkStore store, ILogger logger) - { - _store = store; - _logger = logger; - } - public async Task Cleanup(ICollection collection) { - BookmarkFilter bookmarkFilter = new() + var bookmarkFilter = new BookmarkFilter { BookmarkIds = collection.Select(x => x.Id).ToList() }; - long deletedRecords = await _store.DeleteAsync(bookmarkFilter); + var deletedRecords = await store.DeleteAsync(bookmarkFilter); if (deletedRecords != collection.Count) { - _logger.LogWarning("Expected to delete {Expected} bookmarks, actually deleted {Actual} bookmarks", collection.Count, deletedRecords); + logger.LogWarning("Expected to delete {Expected} bookmarks, actually deleted {Actual} bookmarks", collection.Count, deletedRecords); } } } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/CleanupStrategies/DeleteWorkflowExecutionRecordStrategy.cs b/src/modules/Elsa.Retention/CleanupStrategies/DeleteWorkflowExecutionRecordStrategy.cs index 72ab19298..9868b1577 100644 --- a/src/modules/Elsa.Retention/CleanupStrategies/DeleteWorkflowExecutionRecordStrategy.cs +++ b/src/modules/Elsa.Retention/CleanupStrategies/DeleteWorkflowExecutionRecordStrategy.cs @@ -9,29 +9,20 @@ namespace Elsa.Retention.CleanupStrategies; /// /// Deletes /// -public class DeleteWorkflowExecutionRecordStrategy : IDeletionCleanupStrategy +public class DeleteWorkflowExecutionRecordStrategy(IWorkflowExecutionLogStore store, ILogger logger) : IDeletionCleanupStrategy { - private readonly ILogger _logger; - private readonly IWorkflowExecutionLogStore _store; - - public DeleteWorkflowExecutionRecordStrategy(IWorkflowExecutionLogStore store, ILogger logger) - { - _store = store; - _logger = logger; - } - public async Task Cleanup(ICollection collection) { - WorkflowExecutionLogRecordFilter filter = new() + var filter = new WorkflowExecutionLogRecordFilter() { Ids = collection.Select(x => x.Id).ToList() }; - long deletedRecords = await _store.DeleteManyAsync(filter); + var deletedRecords = await store.DeleteManyAsync(filter); if (deletedRecords != collection.Count) { - _logger.LogWarning("Expected to delete {Expected} workflow execution records, actually deleted {Actual} workflow execution records", collection.Count, deletedRecords); + logger.LogWarning("Expected to delete {Expected} workflow execution records, actually deleted {Actual} workflow execution records", collection.Count, deletedRecords); } } } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/Collectors/ActivityExecutionRecordCollector.cs b/src/modules/Elsa.Retention/Collectors/ActivityExecutionRecordCollector.cs index 1500f6c58..edaee1a28 100644 --- a/src/modules/Elsa.Retention/Collectors/ActivityExecutionRecordCollector.cs +++ b/src/modules/Elsa.Retention/Collectors/ActivityExecutionRecordCollector.cs @@ -9,27 +9,20 @@ namespace Elsa.Retention.Collectors; /// /// Collects all related to the /// -public class ActivityExecutionRecordCollector : IRelatedEntityCollector +public class ActivityExecutionRecordCollector(IActivityExecutionStore store) : IRelatedEntityCollector { - private readonly IActivityExecutionStore _store; - - public ActivityExecutionRecordCollector(IActivityExecutionStore store) - { - _store = store; - } - public async IAsyncEnumerable> GetRelatedEntities(ICollection workflowInstances) { - IEnumerable chunks = workflowInstances.Chunk(5); + var chunks = workflowInstances.Chunk(5); - foreach (WorkflowInstance[] chunk in chunks) + foreach (var chunk in chunks) { - ActivityExecutionRecordFilter filter = new() + var filter = new ActivityExecutionRecordFilter() { WorkflowInstanceIds = chunk.Select(x => x.Id).ToArray() }; - IEnumerable records = await _store.FindManyAsync(filter); + var records = await store.FindManyAsync(filter); yield return records.ToArray(); } } diff --git a/src/modules/Elsa.Retention/Collectors/BookmarkCollector.cs b/src/modules/Elsa.Retention/Collectors/BookmarkCollector.cs index 6a7e43af4..7eecdfc79 100644 --- a/src/modules/Elsa.Retention/Collectors/BookmarkCollector.cs +++ b/src/modules/Elsa.Retention/Collectors/BookmarkCollector.cs @@ -9,27 +9,20 @@ namespace Elsa.Retention.Collectors; /// /// Collects all related to the /// -public class BookmarkCollector : IRelatedEntityCollector +public class BookmarkCollector(IBookmarkStore store) : IRelatedEntityCollector { - private readonly IBookmarkStore _store; - - public BookmarkCollector(IBookmarkStore store) - { - _store = store; - } - public async IAsyncEnumerable> GetRelatedEntities(ICollection workflowInstances) { - IEnumerable batches = workflowInstances.Chunk(25); + var batches = workflowInstances.Chunk(25); - foreach (WorkflowInstance[] batch in batches) + foreach (var batch in batches) { - BookmarkFilter filter = new() + var filter = new BookmarkFilter() { WorkflowInstanceIds = batch.Select(x => x.Id).ToArray() }; - IEnumerable bookmarks = await _store.FindManyAsync(filter); + var bookmarks = await store.FindManyAsync(filter); yield return bookmarks.ToArray(); } } diff --git a/src/modules/Elsa.Retention/Collectors/WorkflowExecutionLogRecordCollector.cs b/src/modules/Elsa.Retention/Collectors/WorkflowExecutionLogRecordCollector.cs index 634bfbc14..9f6a93ecf 100644 --- a/src/modules/Elsa.Retention/Collectors/WorkflowExecutionLogRecordCollector.cs +++ b/src/modules/Elsa.Retention/Collectors/WorkflowExecutionLogRecordCollector.cs @@ -10,31 +10,24 @@ namespace Elsa.Retention.Collectors; /// /// Collects all related to the /// -public class WorkflowExecutionLogRecordCollector : IRelatedEntityCollector +public class WorkflowExecutionLogRecordCollector(IWorkflowExecutionLogStore store) : IRelatedEntityCollector { - private readonly IWorkflowExecutionLogStore _store; - - public WorkflowExecutionLogRecordCollector(IWorkflowExecutionLogStore store) - { - _store = store; - } - public async IAsyncEnumerable> GetRelatedEntities(ICollection workflowInstances) { - IEnumerable chunks = workflowInstances.Chunk(25); + var chunks = workflowInstances.Chunk(25); - foreach (WorkflowInstance[] chunk in chunks) + foreach (var chunk in chunks) { - WorkflowExecutionLogRecordFilter filter = new() + var filter = new WorkflowExecutionLogRecordFilter() { WorkflowInstanceIds = chunk.Select(x => x.Id).ToArray() }; - PageArgs pageArgs = PageArgs.FromPage(0, 100); + var pageArgs = PageArgs.FromPage(0, 100); while (true) { - Page page = await _store.FindManyAsync(filter, pageArgs); + var page = await store.FindManyAsync(filter, pageArgs); yield return page.Items.ToArray(); if (page.TotalCount <= pageArgs.Offset + page.Items.Count) diff --git a/src/modules/Elsa.Retention/Contracts/IRelatedEntityCollector.cs b/src/modules/Elsa.Retention/Contracts/IRelatedEntityCollector.cs index 007ef2033..02c13e10a 100644 --- a/src/modules/Elsa.Retention/Contracts/IRelatedEntityCollector.cs +++ b/src/modules/Elsa.Retention/Contracts/IRelatedEntityCollector.cs @@ -18,7 +18,7 @@ public interface IRelatedEntityCollector : IRelatedEntityCollector wher { async IAsyncEnumerable> IRelatedEntityCollector.GetRelatedEntitiesGeneric(ICollection workflowInstances) { - await foreach (ICollection entity in GetRelatedEntities(workflowInstances).ConfigureAwait(false)) + await foreach (var entity in GetRelatedEntities(workflowInstances).ConfigureAwait(false)) { yield return entity.Select(x => (object)x).ToArray(); } diff --git a/src/modules/Elsa.Retention/Elsa.Retention.csproj.DotSettings b/src/modules/Elsa.Retention/Elsa.Retention.csproj.DotSettings new file mode 100644 index 000000000..4163ed86e --- /dev/null +++ b/src/modules/Elsa.Retention/Elsa.Retention.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/modules/Elsa.Retention/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Retention/Extensions/ModuleExtensions.cs index b36b1ee58..f6ce8f315 100644 --- a/src/modules/Elsa.Retention/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Retention/Extensions/ModuleExtensions.cs @@ -1,15 +1,17 @@ using Elsa.Features.Services; using Elsa.Retention.Feature; +using JetBrains.Annotations; namespace Elsa.Retention.Extensions; /// -/// Provides extensions to install the feature. +/// Provides extensions to install the feature. /// +[UsedImplicitly] public static class ModuleExtensions { /// - /// Install the feature. + /// Installs the feature. /// public static IModule UseRetention(this IModule module, Action? configure = default) { diff --git a/src/modules/Elsa.Retention/Extensions/RetentionFeatureExtensions.cs b/src/modules/Elsa.Retention/Extensions/RetentionFeatureExtensions.cs index ad1854503..bbc57e51e 100644 --- a/src/modules/Elsa.Retention/Extensions/RetentionFeatureExtensions.cs +++ b/src/modules/Elsa.Retention/Extensions/RetentionFeatureExtensions.cs @@ -19,7 +19,7 @@ public static class RetentionFeatureExtensions /// public static RetentionFeature AddDeletePolicy(this RetentionFeature feature, string name, Func filterFactory) { - List policies = feature.Module.Properties.GetOrAdd(PoliciesKey, () => new List()); + var policies = feature.Module.Properties.GetOrAdd(PoliciesKey, () => new List()); policies.Add(new DeletionRetentionPolicy(name, filterFactory)); return feature; } diff --git a/src/modules/Elsa.Retention/Extensions/WorkflowInstanceFilterExtensions.cs b/src/modules/Elsa.Retention/Extensions/WorkflowInstanceFilterExtensions.cs deleted file mode 100644 index 4d92dccd1..000000000 --- a/src/modules/Elsa.Retention/Extensions/WorkflowInstanceFilterExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Elsa.Workflows; -using Elsa.Workflows.Management.Filters; -using Elsa.Workflows.Management.Models; - -namespace Elsa.Retention.Extensions; - -public static class WorkflowInstanceFilterExtensions -{ - /// - /// Clone the current filter - /// - /// - /// - public static WorkflowInstanceFilter Clone(this WorkflowInstanceFilter filter) - { - return new WorkflowInstanceFilter - { - Id = filter.Id, - Ids = filter.Ids == null ? null : new List(filter.Ids), - Version = filter.Version, - CorrelationId = filter.CorrelationId, - CorrelationIds = filter.CorrelationIds == null ? null : new List(filter.CorrelationIds), - DefinitionId = filter.DefinitionId, - DefinitionIds = filter.DefinitionIds == null ? null : new List(filter.DefinitionIds), - HasIncidents = filter.HasIncidents, - IsSystem = filter.IsSystem, - SearchTerm = filter.SearchTerm, - TimestampFilters = filter.TimestampFilters?.Select(x => new TimestampFilter - { - Column = x.Column, - Operator = x.Operator, - Timestamp = x.Timestamp - }).ToList(), - WorkflowStatus = filter.WorkflowStatus, - WorkflowStatuses = filter.WorkflowStatuses == null ? null : new List(filter.WorkflowStatuses), - DefinitionVersionId = filter.DefinitionVersionId, - DefinitionVersionIds = filter.DefinitionVersionIds == null ? null : new List(filter.DefinitionVersionIds), - WorkflowSubStatus = filter.WorkflowSubStatus, - WorkflowSubStatuses = filter.WorkflowSubStatuses == null ? null : new List(filter.WorkflowSubStatuses), - ParentWorkflowInstanceIds = - filter.ParentWorkflowInstanceIds == null ? null : new List(filter.ParentWorkflowInstanceIds) - }; - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Retention/Feature/RetentionFeature.cs b/src/modules/Elsa.Retention/Feature/RetentionFeature.cs index 38295d252..cd8b661d2 100644 --- a/src/modules/Elsa.Retention/Feature/RetentionFeature.cs +++ b/src/modules/Elsa.Retention/Feature/RetentionFeature.cs @@ -1,10 +1,10 @@ +using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Services; using Elsa.Retention.CleanupStrategies; using Elsa.Retention.Collectors; using Elsa.Retention.Contracts; using Elsa.Retention.Extensions; -using Elsa.Retention.HostedServices; using Elsa.Retention.Jobs; using Elsa.Retention.Options; using Elsa.Workflows.Runtime.Entities; @@ -44,15 +44,11 @@ public class RetentionFeature : FeatureBase Services.AddScoped(); Services.AddScoped(); - foreach (IRetentionPolicy policy in this.GetPolicies()) + Services.AddRecurringTask(TimeSpan.FromHours(4)); + + foreach (var policy in this.GetPolicies()) { Services.AddSingleton(policy); } } - - /// - public override void ConfigureHostedServices() - { - ConfigureHostedService(); - } } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/HostedServices/CleanupHostedService.cs b/src/modules/Elsa.Retention/HostedServices/CleanupHostedService.cs deleted file mode 100644 index d15aab4f0..000000000 --- a/src/modules/Elsa.Retention/HostedServices/CleanupHostedService.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Elsa.Retention.Jobs; -using Elsa.Retention.Options; -using Medallion.Threading; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Elsa.Retention.HostedServices; - -/// -/// Periodically wipes workflow instances and their execution logs. -/// -public class CleanupHostedService : BackgroundService -{ - private readonly TimeSpan _interval; - private readonly ILogger _logger; - private readonly IServiceScopeFactory _serviceScopeFactory; - - /// - /// Creates new Cleanup hosted service - /// - /// - /// - /// - public CleanupHostedService(IOptions options, IServiceScopeFactory serviceScopeFactory, ILogger logger) - { - _serviceScopeFactory = serviceScopeFactory; - _logger = logger; - _interval = options.Value.SweepInterval; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - while (!stoppingToken.IsCancellationRequested) - { - using IServiceScope scope = _serviceScopeFactory.CreateScope(); - CleanupJob job = scope.ServiceProvider.GetRequiredService(); - - IDistributedLockProvider distributedLockProvider = scope.ServiceProvider.GetRequiredService(); - - await Task.Delay(_interval, stoppingToken); - await using IDistributedSynchronizationHandle handle = await distributedLockProvider.AcquireLockAsync(nameof(CleanupHostedService), cancellationToken: stoppingToken); - - try - { - await job.ExecuteAsync(stoppingToken); - } - catch (Exception e) - { - _logger.LogError(e, "Failed to perform cleanup this time around. Next cleanup attempt will happen in {Interval}", _interval); - } - } - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Retention/Jobs/CleanupJob.cs b/src/modules/Elsa.Retention/Jobs/CleanupJob.cs index 38bffdbf2..701ab32f3 100644 --- a/src/modules/Elsa.Retention/Jobs/CleanupJob.cs +++ b/src/modules/Elsa.Retention/Jobs/CleanupJob.cs @@ -15,31 +15,15 @@ namespace Elsa.Retention.Jobs; /// Deletes all workflow instances that match any of the defined /// [SuppressMessage("Trimming", "IL2055:Either the type on which the MakeGenericType is called can\'t be statically determined, or the type parameters to be used for generic arguments can\'t be statically determined.")] -public class CleanupJob +public class CleanupJob( + IWorkflowInstanceStore workflowInstanceStore, + IEnumerable policies, + IOptions options, + IServiceProvider serviceProvider, + ILogger logger) { - private readonly ILogger _logger; - private readonly CleanupOptions _options; - private readonly IServiceProvider _serviceProvider; - private readonly IWorkflowInstanceStore _workflowInstanceStore; - - /// - /// Creates a new cleanup job - /// - /// - /// - /// - /// - public CleanupJob( - IWorkflowInstanceStore workflowInstanceStore, - IOptions options, - IServiceProvider serviceProvider, - ILogger logger) - { - _workflowInstanceStore = workflowInstanceStore; - _options = options.Value; - _serviceProvider = serviceProvider; - _logger = logger; - } + private readonly ILogger _logger = logger; + private readonly CleanupOptions _options = options.Value; /// /// Executes the cleanup job @@ -47,34 +31,28 @@ public class CleanupJob /// public async Task ExecuteAsync(CancellationToken cancellationToken = default) { - await using AsyncServiceScope scope = _serviceProvider.CreateAsyncScope(); - - IEnumerable policies = scope.ServiceProvider.GetServices(); - Dictionary collectors = GetServices(typeof(IRelatedEntityCollector), typeof(IRelatedEntityCollector<>)); - - - foreach (IRetentionPolicy policy in policies) + var collectors = GetServices(typeof(IRelatedEntityCollector), typeof(IRelatedEntityCollector<>)); + var deletedWorkflowInstances = 0L; + + foreach (var policy in policies) { - WorkflowInstanceFilter filter = policy.FilterFactory(scope.ServiceProvider).Build(); - PageArgs pageArgs = PageArgs.FromPage(0, _options.PageSize); - - long deletedWorkflowInstances = 0; + var filter = policy.FilterFactory(serviceProvider).Build(); + var pageArgs = PageArgs.FromPage(0, _options.PageSize); while (true) { - Page page = await _workflowInstanceStore.FindManyAsync(filter, pageArgs, cancellationToken); + var page = await workflowInstanceStore.FindManyAsync(filter, pageArgs, cancellationToken); if (page.Items.Count == 0) { break; } - foreach (KeyValuePair collectorService in collectors) + foreach (var collectorService in collectors) { - Type cleanupStrategyConcreteType = policy.CleanupStrategy.MakeGenericType(collectorService.Key); - - IRelatedEntityCollector? collector = collectorService.Value as IRelatedEntityCollector; - ICleanupStrategy? cleanupService = _serviceProvider.GetService(cleanupStrategyConcreteType) as ICleanupStrategy; + var cleanupStrategyConcreteType = policy.CleanupStrategy.MakeGenericType(collectorService.Key); + var collector = collectorService.Value as IRelatedEntityCollector; + var cleanupService = serviceProvider.GetService(cleanupStrategyConcreteType) as ICleanupStrategy; if (collector == null) { @@ -88,13 +66,13 @@ public class CleanupJob continue; } - await foreach (ICollection entities in collector.GetRelatedEntitiesGeneric(page.Items).WithCancellation(cancellationToken)) + await foreach (var entities in collector.GetRelatedEntitiesGeneric(page.Items).WithCancellation(cancellationToken)) { await cleanupService.Cleanup(entities); } } - deletedWorkflowInstances += await _workflowInstanceStore.DeleteAsync(new WorkflowInstanceFilter + deletedWorkflowInstances += await workflowInstanceStore.DeleteAsync(new WorkflowInstanceFilter { Ids = page.Items.Select(x => x.Id).ToArray() }, cancellationToken); @@ -111,7 +89,7 @@ public class CleanupJob private Dictionary GetServices(Type baseType, Type openType) { - IEnumerable services = _serviceProvider.GetServices(baseType); + var services = serviceProvider.GetServices(baseType); return services .Where(x => x?.GetType() != null) diff --git a/src/modules/Elsa.Retention/Options/CleanupOptions.cs b/src/modules/Elsa.Retention/Options/CleanupOptions.cs index 33452ea57..50ff0a428 100644 --- a/src/modules/Elsa.Retention/Options/CleanupOptions.cs +++ b/src/modules/Elsa.Retention/Options/CleanupOptions.cs @@ -5,11 +5,6 @@ namespace Elsa.Retention.Options; /// public class CleanupOptions { - /// - /// Controls how often the database is checked for workflow instances and execution log records to remove. - /// - public TimeSpan SweepInterval { get; set; } = TimeSpan.FromHours(4); - /// /// Controls the page size of the workflow instance that are retained in a single batch /// diff --git a/src/modules/Elsa.Retention/Policies/DeletionRetentionPolicy.cs b/src/modules/Elsa.Retention/Policies/DeletionRetentionPolicy.cs index d049ee55a..758d1ec58 100644 --- a/src/modules/Elsa.Retention/Policies/DeletionRetentionPolicy.cs +++ b/src/modules/Elsa.Retention/Policies/DeletionRetentionPolicy.cs @@ -6,16 +6,10 @@ namespace Elsa.Retention.Policies; /// /// A policy that will delete the workflow instance and its related entities /// -public class DeletionRetentionPolicy : IRetentionPolicy +public class DeletionRetentionPolicy(string name, Func filter) : IRetentionPolicy { - public DeletionRetentionPolicy(string name, Func filter) - { - Name = name; - FilterFactory = filter; - } - - public string Name { get; } - public Func FilterFactory { get; } + public string Name { get; } = name; + public Func FilterFactory { get; } = filter; public Type CleanupStrategy => typeof(IDeletionCleanupStrategy<>); } \ No newline at end of file diff --git a/src/modules/Elsa.Retention/Tasks/CleanupRecurringTask.cs b/src/modules/Elsa.Retention/Tasks/CleanupRecurringTask.cs new file mode 100644 index 000000000..8f39eff09 --- /dev/null +++ b/src/modules/Elsa.Retention/Tasks/CleanupRecurringTask.cs @@ -0,0 +1,19 @@ +using Elsa.Common; +using Elsa.Common.RecurringTasks; +using Elsa.Retention.Jobs; +using JetBrains.Annotations; + +namespace Elsa.Retention; + +/// +/// Periodically deletes workflow instances and their execution logs. +/// +[SingleNodeTask] +[UsedImplicitly] +public class CleanupRecurringTask(CleanupJob job) : RecurringTask +{ + public override async Task ExecuteAsync(CancellationToken stoppingToken) + { + await job.ExecuteAsync(stoppingToken); + } +} \ No newline at end of file