< Summary

Information
Class: Elsa.Workflows.Runtime.Stores.CachingTriggerStore
Assembly: Elsa.Workflows.Runtime
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs
Line coverage
59%
Covered lines: 22
Uncovered lines: 15
Coverable lines: 37
Total lines: 88
Line coverage: 59.4%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.cctor()100%11100%
SaveAsync()100%210%
SaveManyAsync()100%210%
FindAsync()100%11100%
<FindAsync()100%11100%
FindManyAsync()100%11100%
<FindManyAsync()100%11100%
FindManyAsync()100%210%
<FindManyAsync()100%210%
FindManyAsync()100%210%
<FindManyAsync()100%210%
ReplaceAsync()100%11100%
DeleteManyAsync()100%210%
GetOrCreateAsync()75%44100%
<GetOrCreateAsync()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs

#LineLine coverage
 1using Elsa.Caching;
 2using Elsa.Common.Models;
 3using Elsa.Common.Multitenancy;
 4using Elsa.Workflows.Runtime.Entities;
 5using Elsa.Workflows.Runtime.Filters;
 6using Elsa.Workflows.Runtime.OrderDefinitions;
 7using Microsoft.Extensions.Caching.Memory;
 8
 9namespace Elsa.Workflows.Runtime.Stores;
 10
 11/// <summary>
 12/// A decorator for <see cref="ITriggerStore"/> that caches trigger records.
 13/// </summary>
 32114public class CachingTriggerStore(ITriggerStore decoratedStore, ICacheManager cacheManager, IHasher hasher, ITenantAccess
 15{
 16    /// <summary>
 17    /// The token key to evict all cached triggers.
 18    /// </summary>
 119    public static readonly string CacheInvalidationTokenKey = typeof(CachingTriggerStore).FullName!;
 20
 21    /// <inheritdoc />
 22    public async ValueTask SaveAsync(StoredTrigger record, CancellationToken cancellationToken = default)
 23    {
 024        await cacheManager.TriggerTokenAsync(CacheInvalidationTokenKey, cancellationToken);
 025        await decoratedStore.SaveAsync(record, cancellationToken);
 026    }
 27
 28    /// <inheritdoc />
 29    public async ValueTask SaveManyAsync(IEnumerable<StoredTrigger> records, CancellationToken cancellationToken = defau
 30    {
 031        await cacheManager.TriggerTokenAsync(CacheInvalidationTokenKey, cancellationToken);
 032        await decoratedStore.SaveManyAsync(records, cancellationToken);
 033    }
 34
 35    /// <inheritdoc />
 36    public async ValueTask<StoredTrigger?> FindAsync(TriggerFilter filter, CancellationToken cancellationToken = default
 37    {
 238        var cacheKey = hasher.Hash(filter);
 439        return (await GetOrCreateAsync(cacheKey, async () => await decoratedStore.FindAsync(filter, cancellationToken)))
 240    }
 41
 42    /// <inheritdoc />
 43    public async ValueTask<IEnumerable<StoredTrigger>> FindManyAsync(TriggerFilter filter, CancellationToken cancellatio
 44    {
 71445        var cacheKey = hasher.Hash(filter);
 123846        return (await GetOrCreateAsync(cacheKey, async () => await decoratedStore.FindManyAsync(filter, cancellationToke
 71447    }
 48
 49    public async ValueTask<Page<StoredTrigger>> FindManyAsync(TriggerFilter filter, PageArgs pageArgs, CancellationToken
 50    {
 051        var cacheKey = hasher.Hash(filter);
 052        return (await GetOrCreateAsync(cacheKey, async () => await decoratedStore.FindManyAsync(filter, pageArgs, cancel
 053    }
 54
 55    public async ValueTask<Page<StoredTrigger>> FindManyAsync<TProp>(TriggerFilter filter, PageArgs pageArgs, StoredTrig
 56    {
 057        var cacheKey = hasher.Hash(filter);
 058        return (await GetOrCreateAsync(cacheKey, async () => await decoratedStore.FindManyAsync(filter, pageArgs, order,
 059    }
 60
 61    /// <inheritdoc />
 62    public async ValueTask ReplaceAsync(IEnumerable<StoredTrigger> removed, IEnumerable<StoredTrigger> added, Cancellati
 63    {
 48864        await cacheManager.TriggerTokenAsync(CacheInvalidationTokenKey, cancellationToken);
 48865        await decoratedStore.ReplaceAsync(removed, added, cancellationToken);
 48866    }
 67
 68    /// <inheritdoc />
 69    public async ValueTask<long> DeleteManyAsync(TriggerFilter filter, CancellationToken cancellationToken = default)
 70    {
 071        await cacheManager.TriggerTokenAsync(CacheInvalidationTokenKey, cancellationToken);
 072        return await decoratedStore.DeleteManyAsync(filter, cancellationToken);
 073    }
 74
 75    private async Task<T?> GetOrCreateAsync<T>(string key, Func<Task<T>> factory)
 76    {
 71677        var tenantId = tenantAccessor.Tenant?.Id;
 71678        var tenantIdPrefix = !string.IsNullOrEmpty(tenantId) ? $"{tenantId}:" : string.Empty;
 71679        var internalKey = $"{tenantIdPrefix}{typeof(T).Name}:{key}";
 71680        return await cacheManager.GetOrCreateAsync(internalKey, async entry =>
 71681        {
 52682            var invalidationRequestToken = cacheManager.GetToken(CacheInvalidationTokenKey);
 52683            entry.AddExpirationToken(invalidationRequestToken);
 52684            entry.SetAbsoluteExpiration(cacheManager.CachingOptions.Value.CacheDuration);
 52685            return await factory();
 124286        });
 71687    }
 88}