| | | 1 | | using Elsa.Expressions.Helpers; |
| | | 2 | | using Elsa.Expressions.Models; |
| | | 3 | | using Elsa.Extensions; |
| | | 4 | | using Elsa.Workflows.Memory; |
| | | 5 | | using Microsoft.Extensions.Logging; |
| | | 6 | | |
| | | 7 | | namespace Elsa.Workflows; |
| | | 8 | | |
| | | 9 | | /// <inheritdoc /> |
| | 421 | 10 | | public class VariablePersistenceManager(IStorageDriverManager storageDriverManager, ILogger<VariablePersistenceManager> |
| | | 11 | | { |
| | | 12 | | /// <inheritdoc /> |
| | | 13 | | public async Task LoadVariablesAsync(WorkflowExecutionContext workflowExecutionContext, IEnumerable<string>? exclude |
| | | 14 | | { |
| | 442 | 15 | | var cancellationToken = workflowExecutionContext.CancellationToken; |
| | 442 | 16 | | var contexts = workflowExecutionContext.ActivityExecutionContexts.ToList(); |
| | 442 | 17 | | var excludeTagsList = excludeTags?.ToList(); |
| | | 18 | | |
| | 1152 | 19 | | foreach (var context in contexts) |
| | | 20 | | { |
| | 134 | 21 | | var variables = GetLocalVariables(context).ToList(); |
| | | 22 | | |
| | 310 | 23 | | foreach (var variable in variables) |
| | | 24 | | { |
| | 21 | 25 | | context.ExpressionExecutionContext.Memory.Declare(variable); |
| | 21 | 26 | | var storageDriverContext = new StorageDriverContext(context, variable, cancellationToken); |
| | 21 | 27 | | var register = context.ExpressionExecutionContext.Memory; |
| | 21 | 28 | | var block = EnsureBlock(register, variable); |
| | 21 | 29 | | var metadata = (VariableBlockMetadata)block.Metadata!; |
| | 21 | 30 | | var driver = storageDriverManager.Get(metadata.StorageDriverType!); |
| | | 31 | | |
| | 21 | 32 | | block.Metadata = metadata with |
| | 21 | 33 | | { |
| | 21 | 34 | | IsInitialized = true |
| | 21 | 35 | | }; |
| | | 36 | | |
| | 21 | 37 | | if (driver == null) |
| | | 38 | | continue; |
| | | 39 | | |
| | 15 | 40 | | if (excludeTagsList != null && driver.Tags.Any(excludeTagsList.Contains)) |
| | | 41 | | continue; |
| | | 42 | | |
| | 15 | 43 | | var id = GetStateId(variable); |
| | | 44 | | |
| | | 45 | | try |
| | | 46 | | { |
| | 15 | 47 | | var value = await driver.ReadAsync(id, storageDriverContext); |
| | 15 | 48 | | if (value == null) continue; |
| | | 49 | | |
| | 15 | 50 | | register.Declare(variable); |
| | | 51 | | |
| | 15 | 52 | | if (!variable.TryParseValue(value, out var parsedValue)) |
| | | 53 | | { |
| | 0 | 54 | | logger.LogWarning("Failed to parse value for variable {VariableId} of type {VariableType} with v |
| | | 55 | | |
| | 0 | 56 | | if (!ObjectConverter.StrictMode) |
| | 0 | 57 | | variable.Set(register, value); |
| | 0 | 58 | | continue; |
| | | 59 | | } |
| | | 60 | | |
| | 15 | 61 | | variable.Set(register, parsedValue); |
| | 15 | 62 | | } |
| | 0 | 63 | | catch (Exception e) |
| | | 64 | | { |
| | 0 | 65 | | logger.LogError(e, "Failed to read variable {VariableId} from storage driver {StorageDriverType}", v |
| | 0 | 66 | | } |
| | 15 | 67 | | } |
| | 134 | 68 | | } |
| | 442 | 69 | | } |
| | | 70 | | |
| | | 71 | | /// <inheritdoc /> |
| | | 72 | | public async Task SaveVariablesAsync(WorkflowExecutionContext workflowExecutionContext) |
| | | 73 | | { |
| | 436 | 74 | | var cancellationToken = workflowExecutionContext.CancellationToken; |
| | 436 | 75 | | var contexts = workflowExecutionContext.ActivityExecutionContexts.ToList(); |
| | | 76 | | |
| | 7078 | 77 | | foreach (var context in contexts) |
| | | 78 | | { |
| | 3103 | 79 | | var variables = GetLocalVariables(context).ToList(); |
| | | 80 | | |
| | 6454 | 81 | | foreach (var variable in variables) |
| | | 82 | | { |
| | 124 | 83 | | var block = variable.GetBlock(context.ExpressionExecutionContext); |
| | 124 | 84 | | var metadata = (VariableBlockMetadata)block.Metadata!; |
| | 124 | 85 | | var driver = storageDriverManager.Get(metadata.StorageDriverType!); |
| | | 86 | | |
| | 124 | 87 | | if (driver == null) |
| | | 88 | | continue; |
| | | 89 | | |
| | 89 | 90 | | var id = GetStateId(variable); |
| | 89 | 91 | | var value = block.Value; |
| | 89 | 92 | | var storageDriverContext = new StorageDriverContext(context, variable, cancellationToken); |
| | | 93 | | |
| | 89 | 94 | | if (value == null) |
| | 2 | 95 | | await driver.DeleteAsync(id, storageDriverContext); |
| | | 96 | | else |
| | 87 | 97 | | await driver.WriteAsync(id, value, storageDriverContext); |
| | | 98 | | } |
| | 3103 | 99 | | } |
| | 436 | 100 | | } |
| | | 101 | | |
| | | 102 | | /// <inheritdoc /> |
| | | 103 | | public async Task DeleteVariablesAsync(ActivityExecutionContext context, IEnumerable<string>? includeTags = default) |
| | | 104 | | { |
| | 2541 | 105 | | var register = context.ExpressionExecutionContext.Memory; |
| | 2541 | 106 | | var variableList = GetLocalVariables(context).ToList(); |
| | 2541 | 107 | | var cancellationToken = context.CancellationToken; |
| | 2541 | 108 | | var includeTagsList = includeTags?.ToList(); |
| | | 109 | | |
| | 5260 | 110 | | foreach (var variable in variableList) |
| | | 111 | | { |
| | 89 | 112 | | if (!register.TryGetBlock(variable.Id, out var block)) |
| | | 113 | | continue; |
| | | 114 | | |
| | 41 | 115 | | var metadata = (VariableBlockMetadata)block.Metadata!; |
| | 41 | 116 | | var driver = storageDriverManager.Get(metadata.StorageDriverType!); |
| | | 117 | | |
| | 41 | 118 | | if (driver == null) |
| | | 119 | | continue; |
| | | 120 | | |
| | 30 | 121 | | if (includeTagsList != null && !driver.Tags.Any(includeTagsList.Contains)) |
| | | 122 | | continue; |
| | | 123 | | |
| | 30 | 124 | | var id = GetStateId(variable); |
| | 30 | 125 | | var storageDriverContext = new StorageDriverContext(context, variable, cancellationToken); |
| | 30 | 126 | | await driver.DeleteAsync(id, storageDriverContext); |
| | 30 | 127 | | register.Blocks.Remove(variable.Id); |
| | 30 | 128 | | } |
| | 2541 | 129 | | } |
| | | 130 | | |
| | | 131 | | /// <inheritdoc /> |
| | | 132 | | public async Task DeleteVariablesAsync(WorkflowExecutionContext context, IEnumerable<string>? includeTags = default) |
| | | 133 | | { |
| | 0 | 134 | | var activityContexts = context.ActivityExecutionContexts.ToList(); |
| | 0 | 135 | | var includeTagsList = includeTags?.ToList(); |
| | | 136 | | |
| | 0 | 137 | | foreach (var activityContext in activityContexts) |
| | | 138 | | { |
| | 0 | 139 | | await DeleteVariablesAsync(activityContext, includeTagsList); |
| | | 140 | | } |
| | 0 | 141 | | } |
| | | 142 | | |
| | 5778 | 143 | | private IEnumerable<Variable> GetLocalVariables(IExecutionContext context) => context.Variables; |
| | | 144 | | |
| | | 145 | | private MemoryBlock EnsureBlock(MemoryRegister register, Variable variable) |
| | | 146 | | { |
| | 21 | 147 | | if (!register.TryGetBlock(variable.Id, out var block)) |
| | 0 | 148 | | block = register.Declare(variable); |
| | 21 | 149 | | return block; |
| | | 150 | | } |
| | | 151 | | |
| | 134 | 152 | | private string GetStateId(Variable variable) => variable.Id; |
| | | 153 | | } |