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