Evict activity type cache upon webhook definition created or updated

This commit is contained in:
Sipke Schoorstra 2021-07-21 12:40:42 +02:00
parent 11fb572237
commit 7f0cf7e1fe
6 changed files with 38 additions and 96 deletions

View file

@ -1,5 +1,6 @@
using Elsa.Activities.Webhooks.ActivityTypes;
using Elsa.Activities.Webhooks.Bookmarks;
using Elsa.Activities.Webhooks.Handlers;
using Elsa.Services;
using Microsoft.Extensions.DependencyInjection;
@ -11,7 +12,8 @@ namespace Elsa.Activities.Webhooks.Extensions
{
elsaOptions.Services
.AddScoped<IActivityTypeProvider, WebhookActivityTypeProvider>()
.AddBookmarkProvider<WebhookBookmarkProvider>();
.AddBookmarkProvider<WebhookBookmarkProvider>()
.AddNotificationHandlersFrom<EvictWorkflowRegistryCacheHandler>();
return elsaOptions;
}

View file

@ -0,0 +1,24 @@
using System.Threading;
using System.Threading.Tasks;
using Elsa.Caching;
using Elsa.Services.Workflows;
using Elsa.Webhooks.Events;
using MediatR;
namespace Elsa.Activities.Webhooks.Handlers
{
public class EvictWorkflowRegistryCacheHandler : INotificationHandler<WebhookDefinitionSaved>
{
private readonly ICacheSignal _cacheSignal;
public EvictWorkflowRegistryCacheHandler(ICacheSignal cacheSignal)
{
_cacheSignal = cacheSignal;
}
public async Task Handle(WebhookDefinitionSaved notification, CancellationToken cancellationToken)
{
await _cacheSignal.TriggerTokenAsync(ActivityTypeService.CacheKey);
}
}
}

View file

@ -1,76 +0,0 @@
// using System.Threading;
// using System.Threading.Tasks;
// using Elsa.Persistence.Specifications;
// using Elsa.Services;
// using Elsa.Webhooks.Abstractions.Models;
// using Elsa.Webhooks.Abstractions.Persistence;
// using Elsa.Webhooks.Abstractions.Services;
// using MediatR;
//
// namespace Elsa.Activities.Webhooks.Services
// {
// public class WebhookPublisher : IWebhookPublisher
// {
// private readonly IWebhookDefinitionStore _webhookDefinitionStore;
// private readonly IIdGenerator _idGenerator;
// private readonly ICloner _cloner;
// private readonly IMediator _mediator;
//
// public WebhookPublisher(IWebhookDefinitionStore webhookDefinitionStore, IIdGenerator idGenerator, ICloner cloner, IMediator mediator)
// {
// _webhookDefinitionStore = webhookDefinitionStore;
// _idGenerator = idGenerator;
// _cloner = cloner;
// _mediator = mediator;
// }
//
// public WebhookDefinition New()
// {
// var definition = new WebhookDefinition
// {
// Id = _idGenerator.Generate(),
// Name = "New Webhook"
// };
//
// return definition;
// }
//
// public async Task<WebhookDefinition> SaveAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default)
// {
// var webhook = webhookDefinition;
// webhook = Initialize(webhook);
//
// await _webhookDefinitionStore.SaveAsync(webhook, cancellationToken);
// return webhook;
// }
//
// public async Task<WebhookDefinition> UpdateAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default)
// {
// var webhook = webhookDefinition;
// webhook = Initialize(webhook);
//
// await _webhookDefinitionStore.UpdateAsync(webhook, cancellationToken);
// return webhook;
// }
//
// public async Task DeleteAsync(string webhookId, CancellationToken cancellationToken = default)
// {
// var webhookDefinition = New();
// if (!string.IsNullOrWhiteSpace(webhookId))
// {
// webhookDefinition = await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(webhookId), cancellationToken);
// }
// await _webhookDefinitionStore.DeleteAsync(webhookDefinition, cancellationToken);
// }
//
// public Task DeleteAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default) => DeleteAsync(webhookDefinition, cancellationToken);
//
// private WebhookDefinition Initialize(WebhookDefinition webhookDefinition)
// {
// if (webhookDefinition.Id == null!)
// webhookDefinition.Id = _idGenerator.Generate();
//
// return webhookDefinition;
// }
// }
// }

View file

@ -1,15 +0,0 @@
// using System.Threading;
// using System.Threading.Tasks;
// using Elsa.Webhooks.Abstractions.Models;
//
// namespace Elsa.Webhooks.Abstractions.Services
// {
// public interface IWebhookPublisher
// {
// WebhookDefinition New();
// Task<WebhookDefinition> SaveAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default);
// Task<WebhookDefinition> UpdateAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default);
// Task DeleteAsync(string webhookId, CancellationToken cancellationToken = default);
// Task DeleteAsync(WebhookDefinition webhookDefinition, CancellationToken cancellationToken = default);
// }
// }

View file

@ -19,7 +19,7 @@ namespace Elsa.Decorators
{
public class CachingWorkflowRegistry : IWorkflowRegistry, INotificationHandler<WorkflowDefinitionSaved>, INotificationHandler<WorkflowDefinitionDeleted>
{
private const string CacheKey = "WorkflowRegistry";
public const string CacheKey = "WorkflowRegistry";
private readonly IWorkflowRegistry _workflowRegistry;
private readonly IMemoryCache _memoryCache;
private readonly ICacheSignal _cacheSignal;

View file

@ -3,6 +3,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Caching;
using Elsa.Events;
using Elsa.Exceptions;
using Elsa.Metadata;
@ -14,15 +15,18 @@ namespace Elsa.Services.Workflows
{
public class ActivityTypeService : IActivityTypeService
{
public const string CacheKey = "ActivityTypes";
private readonly IEnumerable<IActivityTypeProvider> _providers;
private readonly IMemoryCache _memoryCache;
private readonly IMediator _mediator;
private readonly ICacheSignal _cacheSignal;
public ActivityTypeService(IEnumerable<IActivityTypeProvider> providers, IMemoryCache memoryCache, IMediator mediator)
public ActivityTypeService(IEnumerable<IActivityTypeProvider> providers, IMemoryCache memoryCache, IMediator mediator, ICacheSignal cacheSignal)
{
_providers = providers;
_memoryCache = memoryCache;
_mediator = mediator;
_cacheSignal = cacheSignal;
}
public async ValueTask<IEnumerable<ActivityType>> GetActivityTypesAsync(CancellationToken cancellationToken) => (await GetDictionaryAsync(cancellationToken)).Values;
@ -61,8 +65,11 @@ namespace Elsa.Services.Workflows
private async ValueTask<IDictionary<string, ActivityType>> GetDictionaryAsync(CancellationToken cancellationToken)
{
const string key = "ActivityTypes";
return await _memoryCache.GetOrCreate(key, async _ => await GetActivityTypesInternalAsync(cancellationToken).ToDictionaryAsync(x => x.TypeName, cancellationToken));
return await _memoryCache.GetOrCreate(CacheKey, async entry =>
{
entry.Monitor(_cacheSignal.GetToken(CacheKey));
return await GetActivityTypesInternalAsync(cancellationToken).ToDictionaryAsync(x => x.TypeName, cancellationToken);
});
}
private async IAsyncEnumerable<ActivityType> GetActivityTypesInternalAsync([EnumeratorCancellation] CancellationToken cancellationToken)