Ensure schedules are deleted when bookmarks are deleted

This commit is contained in:
Sipke Schoorstra 2023-07-20 13:00:09 +02:00
parent 9eaac89470
commit f71e5c89ce
8 changed files with 94 additions and 7 deletions

View file

@ -3,6 +3,7 @@ using Elsa.Scheduling.Contracts;
using Elsa.Workflows.Management.Notifications;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Filters;
using Elsa.Workflows.Runtime.Notifications;
namespace Elsa.Scheduling.Handlers;
@ -14,7 +15,7 @@ public class DeleteSchedules :
INotificationHandler<WorkflowDefinitionsDeleting>,
INotificationHandler<WorkflowDefinitionVersionDeleting>,
INotificationHandler<WorkflowDefinitionVersionsDeleting>,
INotificationHandler<WorkflowInstancesDeleting>
INotificationHandler<BookmarksDeleting>
{
private readonly ITriggerScheduler _triggerScheduler;
private readonly IBookmarkScheduler _bookmarkScheduler;
@ -32,9 +33,10 @@ public class DeleteSchedules :
_bookmarkStore = bookmarkStore;
}
async Task INotificationHandler<WorkflowInstancesDeleting>.HandleAsync(WorkflowInstancesDeleting notification, CancellationToken cancellationToken)
async Task INotificationHandler<BookmarksDeleting>.HandleAsync(BookmarksDeleting notification, CancellationToken cancellationToken)
{
var bookmarks = await _bookmarkStore.FindManyAsync(new BookmarkFilter { WorkflowInstanceIds = notification.Ids }, cancellationToken);
var ids = notification.Bookmarks.Select(x => x.BookmarkId).ToList();
var bookmarks = await _bookmarkStore.FindManyAsync(new BookmarkFilter { BookmarkIds = ids }, cancellationToken);
await _bookmarkScheduler.UnscheduleAsync(bookmarks, cancellationToken);
}

View file

@ -0,0 +1,17 @@
using Elsa.Workflows.Runtime.Filters;
namespace Elsa.Workflows.Runtime.Contracts;
/// <summary>
/// Manages bookmarks.
/// </summary>
public interface IBookmarkManager
{
/// <summary>
/// Deletes all bookmarks matching the specified filter.
/// </summary>
/// <param name="filter">The filter.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
/// <returns>The number of deleted bookmarks.</returns>
Task<long> DeleteManyAsync(BookmarkFilter filter, CancellationToken cancellationToken = default);
}

View file

@ -149,6 +149,7 @@ public class WorkflowRuntimeFeature : FeatureBase
.AddSingleton(WorkflowExecutionLogStore)
.AddSingleton(RunTaskDispatcher)
.AddSingleton(BackgroundActivityInvoker)
.AddSingleton<IBookmarkManager, DefaultBookmarkManager>()
.AddSingleton<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
.AddSingleton<IRegistriesPopulator, DefaultRegistriesPopulator>()
.AddSingleton<ITaskReporter, TaskReporter>()

View file

@ -7,6 +7,16 @@ namespace Elsa.Workflows.Runtime.Filters;
/// </summary>
public class BookmarkFilter
{
/// <summary>
/// Gets or sets the ID of the bookmark.
/// </summary>
public string? BookmarkId { get; set; }
/// <summary>
/// Gets or sets the IDs of the bookmark.
/// </summary>
public ICollection<string>? BookmarkIds { get; set; }
/// <summary>
/// Gets or sets the IDs of the workflow instance.
/// </summary>
@ -43,6 +53,8 @@ public class BookmarkFilter
public IQueryable<StoredBookmark> Apply(IQueryable<StoredBookmark> query)
{
var filter = this;
if (filter.BookmarkId != null) query = query.Where(x => x.BookmarkId == filter.BookmarkId);
if (filter.BookmarkIds != null) query = query.Where(x => filter.BookmarkIds.Contains(x.BookmarkId));
if (filter.CorrelationId != null) query = query.Where(x => x.CorrelationId == filter.CorrelationId);
if (filter.Hash != null) query = query.Where(x => x.Hash == filter.Hash);
if (filter.WorkflowInstanceId != null) query = query.Where(x => x.WorkflowInstanceId == filter.WorkflowInstanceId);

View file

@ -10,19 +10,19 @@ namespace Elsa.Workflows.Runtime.Handlers;
/// </summary>
public class DeleteBookmarks : INotificationHandler<WorkflowInstancesDeleting>
{
private readonly IBookmarkStore _bookmarkStore;
private readonly IBookmarkManager _bookmarkManager;
/// <summary>
/// Initializes a new instance of the <see cref="DeleteBookmarks"/> class.
/// </summary>
public DeleteBookmarks(IBookmarkStore bookmarkStore)
public DeleteBookmarks(IBookmarkManager bookmarkManager)
{
_bookmarkStore = bookmarkStore;
_bookmarkManager = bookmarkManager;
}
/// <inheritdoc />
public async Task HandleAsync(WorkflowInstancesDeleting notification, CancellationToken cancellationToken)
{
await _bookmarkStore.DeleteAsync(new BookmarkFilter { WorkflowInstanceIds = notification.Ids }, cancellationToken);
await _bookmarkManager.DeleteManyAsync(new BookmarkFilter { WorkflowInstanceIds = notification.Ids }, cancellationToken);
}
}

View file

@ -0,0 +1,10 @@
using Elsa.Mediator.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Workflows.Runtime.Notifications;
/// <summary>
/// Triggered when bookmarks have been deleted.
/// </summary>
/// <param name="Bookmarks">The bookmarks that have been deleted.</param>
public record BookmarksDeleted(ICollection<StoredBookmark> Bookmarks) : INotification;

View file

@ -0,0 +1,10 @@
using Elsa.Mediator.Contracts;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Workflows.Runtime.Notifications;
/// <summary>
/// Triggered when bookmarks are being deleted.
/// </summary>
/// <param name="Bookmarks">The bookmarks being deleted.</param>
public record BookmarksDeleting(ICollection<StoredBookmark> Bookmarks) : INotification;

View file

@ -0,0 +1,35 @@
using Elsa.Extensions;
using Elsa.Mediator.Contracts;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Filters;
using Elsa.Workflows.Runtime.Notifications;
namespace Elsa.Workflows.Runtime.Services;
/// <summary>
/// Default implementation of <see cref="IBookmarkManager"/>.
/// </summary>
public class DefaultBookmarkManager : IBookmarkManager
{
private readonly IBookmarkStore _bookmarkStore;
private readonly INotificationSender _notificationSender;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultBookmarkManager"/> class.
/// </summary>
public DefaultBookmarkManager(IBookmarkStore bookmarkStore, INotificationSender notificationSender)
{
_bookmarkStore = bookmarkStore;
_notificationSender = notificationSender;
}
/// <inheritdoc />
public async Task<long> DeleteManyAsync(BookmarkFilter filter, CancellationToken cancellationToken = default)
{
var bookmarks = (await _bookmarkStore.FindManyAsync(filter, cancellationToken)).ToList();
await _notificationSender.SendAsync(new BookmarksDeleting(bookmarks), cancellationToken);
var count = await _bookmarkStore.DeleteAsync(filter, cancellationToken);
await _notificationSender.SendAsync(new BookmarksDeleted(bookmarks), cancellationToken);
return count;
}
}