From 856f7b40b4a61535b0d67259d1c76ab7d761ac41 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:11:02 +0100 Subject: [PATCH] Fix cross-tenant cache collision in CachingWorkflowDefinitionService (#7318) * Initial plan * Fix cross-tenant cache collision in WorkflowDefinitionCacheManager Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com> --- .../WorkflowDefinitionCacheManager.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionCacheManager.cs b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionCacheManager.cs index 8fdbd6d74..973a2e718 100644 --- a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionCacheManager.cs +++ b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionCacheManager.cs @@ -1,43 +1,44 @@ using Elsa.Caching; using Elsa.Common.Models; +using Elsa.Common.Multitenancy; using Elsa.Workflows.Management.Filters; namespace Elsa.Workflows.Management.Services; /// -public class WorkflowDefinitionCacheManager(ICacheManager cache, IHasher hasher) : IWorkflowDefinitionCacheManager +public class WorkflowDefinitionCacheManager(ICacheManager cache, IHasher hasher, ITenantAccessor tenantAccessor) : IWorkflowDefinitionCacheManager { /// public ICacheManager Cache => cache; /// - public string CreateWorkflowDefinitionVersionCacheKey(string definitionId, VersionOptions versionOptions) => $"WorkflowDefinition:{definitionId}:{versionOptions}"; + public string CreateWorkflowDefinitionVersionCacheKey(string definitionId, VersionOptions versionOptions) => TenantPrefix() + $"WorkflowDefinition:{definitionId}:{versionOptions}"; /// public string CreateWorkflowDefinitionFilterCacheKey(WorkflowDefinitionFilter filter) { var hash = hasher.Hash(filter); - return $"WorkflowDefinition:{hash}"; + return TenantPrefix() + $"WorkflowDefinition:{hash}"; } /// - public string CreateWorkflowVersionCacheKey(string definitionId, VersionOptions versionOptions) => $"Workflow:{definitionId}:{versionOptions}"; + public string CreateWorkflowVersionCacheKey(string definitionId, VersionOptions versionOptions) => TenantPrefix() + $"Workflow:{definitionId}:{versionOptions}"; /// - public string CreateWorkflowVersionCacheKey(string definitionVersionId) => $"Workflow:{definitionVersionId}"; + public string CreateWorkflowVersionCacheKey(string definitionVersionId) => TenantPrefix() + $"Workflow:{definitionVersionId}"; /// public string CreateWorkflowFilterCacheKey(WorkflowDefinitionFilter filter) { var hash = hasher.Hash(filter); - return $"Workflow:{hash}"; + return TenantPrefix() + $"Workflow:{hash}"; } /// - public string CreateWorkflowDefinitionVersionCacheKey(string definitionVersionId) => $"WorkflowDefinition:{definitionVersionId}"; + public string CreateWorkflowDefinitionVersionCacheKey(string definitionVersionId) => TenantPrefix() + $"WorkflowDefinition:{definitionVersionId}"; /// - public string CreateWorkflowDefinitionChangeTokenKey(string definitionId) => $"WorkflowChangeToken:{definitionId}"; + public string CreateWorkflowDefinitionChangeTokenKey(string definitionId) => TenantPrefix() + $"WorkflowChangeToken:{definitionId}"; /// public async Task EvictWorkflowDefinitionAsync(string definitionId, CancellationToken cancellationToken = default) @@ -45,4 +46,10 @@ public class WorkflowDefinitionCacheManager(ICacheManager cache, IHasher hasher) var changeTokenKey = CreateWorkflowDefinitionChangeTokenKey(definitionId); await cache.TriggerTokenAsync(changeTokenKey, cancellationToken); } + + private string TenantPrefix() + { + var tenantId = tenantAccessor.TenantId; + return string.IsNullOrEmpty(tenantId) ? string.Empty : $"{tenantId}:"; + } } \ No newline at end of file