-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Distributed locks to prevent multiple pods executing Reload and Refresh #7311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sfmskywalker
merged 23 commits into
release/3.6.0
from
feat/multi-trigger-publish-update
Feb 23, 2026
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
a0e6a4a
Distributed locks to prevent multiple pods executing Reload and Refresh
lukhipolito 3cb85ca
Update src/modules/Elsa.Workflows.Runtime/Services/WorkflowDefinition…
lukhipolito-nexxbiz d6e28f0
Update src/modules/Elsa.Workflows.Runtime/Services/WorkflowDefinition…
lukhipolito-nexxbiz 3aa143b
Update src/modules/Elsa.Workflows.Runtime/Services/WorkflowDefinition…
lukhipolito-nexxbiz fcb7b04
Moving distributed lock decorators to proper folder
lukhipolito 5fea6f2
Adding logging for missing lock
lukhipolito 0f648b6
Fixing logger use in distributed classes
lukhipolito 789d8e8
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz c8c6b48
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz 2521c3f
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz d4bfe8a
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz a8cae08
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz 444e248
Update src/modules/Elsa.Workflows.Runtime/Distributed/WorkflowDefinit…
lukhipolito-nexxbiz 84d335d
Moving and renaming for clearer purpose
lukhipolito 348559a
Fixing build after file moves
lukhipolito 33cb21b
Addressing workflow refresher empty query leaking distributed lock logic
lukhipolito b0abe55
Merge branch 'release/3.6.0' into feat/multi-trigger-publish-update
lukhipolito c3d4e67
Merge branch 'release/3.6.0' into feat/multi-trigger-publish-update
lukhipolito 7279619
Add status to WorkflowRefresherResponse model for in progress operation
lukhipolito 37915ed
Merge branch 'release/3.6.0' into feat/multi-trigger-publish-update
lukhipolito 82fd7e3
Removing typo, fixing build
lukhipolito 0618f52
Update src/modules/Elsa.Workflows.Runtime.Distributed/Services/Distri…
lukhipolito-nexxbiz 5bf7538
Refactor `RefreshWorkflowDefinitionsAsync` for lock acquisition logic…
sfmskywalker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...es/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowDefinitionsRefresher.cs
lukhipolito-nexxbiz marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| using Elsa.Workflows.Runtime.Requests; | ||
| using Elsa.Workflows.Runtime.Responses; | ||
| using JetBrains.Annotations; | ||
| using Medallion.Threading; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| namespace Elsa.Workflows.Runtime.Distributed; | ||
|
|
||
| /// <summary> | ||
| /// Decorator class that adds distributed locking to the Workflow Definitions Refresher. | ||
| /// </summary> | ||
| [UsedImplicitly] | ||
| public class DistributedWorkflowDefinitionsRefresher(IWorkflowDefinitionsRefresher inner, | ||
| IDistributedLockProvider distributedLockProvider, | ||
| ILogger<DistributedWorkflowDefinitionsRefresher> logger) : IWorkflowDefinitionsRefresher | ||
| { | ||
| /// <summary> | ||
| /// This ensures that only one instance of the application can refresh a set of workflow definitions at a time, preventing potential conflicts and ensuring consistency across distributed environments. | ||
| /// </summary> | ||
| public async Task<RefreshWorkflowDefinitionsResponse> RefreshWorkflowDefinitionsAsync(RefreshWorkflowDefinitionsRequest request, CancellationToken cancellationToken = default) | ||
| { | ||
| var isRefreshingAll = request.DefinitionIds == null || request.DefinitionIds.Count == 0; | ||
| var lockKey = isRefreshingAll | ||
| ? "WorkflowDefinitionsRefresher:All" | ||
| : $"WorkflowDefinitionsRefresher:{string.Join(",", request.DefinitionIds!.OrderBy(x => x))}"; | ||
|
|
||
| await using var distributedLock = await distributedLockProvider.TryAcquireLockAsync( | ||
| lockKey, | ||
| TimeSpan.Zero, | ||
| cancellationToken); | ||
|
|
||
| if (distributedLock == null) | ||
| { | ||
| var logMessage = isRefreshingAll | ||
| ? "Could not acquire lock for refreshing all workflow definitions. Another instance is already refreshing all workflow definitions" | ||
| : "Could not acquire lock for refreshing workflow definitions. Another instance is already refreshing these workflow definitions"; | ||
|
|
||
| logger.LogInformation(logMessage); | ||
|
|
||
| var failedDefinitionIds = isRefreshingAll ? Array.Empty<string>() : request.DefinitionIds!; | ||
| return new(Array.Empty<string>(), failedDefinitionIds, RefreshWorkflowDefinitionsStatus.AlreadyInProgress); | ||
| } | ||
|
|
||
| return await inner.RefreshWorkflowDefinitionsAsync(request, cancellationToken); | ||
| } | ||
| } |
36 changes: 36 additions & 0 deletions
36
...les/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowDefinitionsReloader.cs
lukhipolito-nexxbiz marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| using JetBrains.Annotations; | ||
| using Medallion.Threading; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| namespace Elsa.Workflows.Runtime.Distributed; | ||
|
|
||
| /// <summary> | ||
| /// Decorator class that adds distributed locking to the Workflow Definitions Reloader. | ||
| /// </summary> | ||
| [UsedImplicitly] | ||
| public class DistributedWorkflowDefinitionsReloader( | ||
| IWorkflowDefinitionsReloader inner, | ||
| IDistributedLockProvider distributedLockProvider, | ||
| ILogger<DistributedWorkflowDefinitionsReloader> logger) : IWorkflowDefinitionsReloader | ||
| { | ||
| private const string LockKey = "WorkflowDefinitionsReloader"; | ||
|
|
||
| /// <summary> | ||
| /// This ensures that only one instance of the application can reload workflow definitions at a time, preventing potential conflicts and ensuring consistency across distributed environments. | ||
| /// </summary> | ||
| public async Task ReloadWorkflowDefinitionsAsync(CancellationToken cancellationToken = default) | ||
| { | ||
| await using var distributedLock = await distributedLockProvider.TryAcquireLockAsync( | ||
| LockKey, | ||
| TimeSpan.Zero, | ||
| cancellationToken); | ||
|
|
||
| if (distributedLock == null) | ||
| { | ||
| logger.LogInformation("Could not acquire lock for workflow definitions reload. Another instance is already reloading workflow definitions"); | ||
| return; | ||
| } | ||
|
|
||
| await inner.ReloadWorkflowDefinitionsAsync(cancellationToken); | ||
| } | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/modules/Elsa.Workflows.Runtime/Enums/RefreshWorkflowDefinitionsStatus.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| namespace Elsa.Workflows.Runtime; | ||
|
|
||
| public enum RefreshWorkflowDefinitionsStatus | ||
| { | ||
| Completed, | ||
| AlreadyInProgress | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.