| | | 1 | | namespace Elsa.Workflows.Management.Models; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Represents a single directed edge in the workflow reference graph. |
| | | 5 | | /// The edge points from a consumer workflow (Source) to the workflow it references (Target). |
| | | 6 | | /// </summary> |
| | | 7 | | /// <param name="Source">The workflow definition ID of the consumer (the workflow that contains the reference).</param> |
| | | 8 | | /// <param name="Target">The workflow definition ID being referenced (the dependency).</param> |
| | 309 | 9 | | public record WorkflowReferenceEdge(string Source, string Target); |
| | | 10 | | |
| | | 11 | | /// <summary> |
| | | 12 | | /// Represents a complete graph of workflow references, built by recursively traversing all consumers |
| | | 13 | | /// of a given workflow definition. |
| | | 14 | | /// </summary> |
| | | 15 | | public class WorkflowReferenceGraph |
| | | 16 | | { |
| | | 17 | | /// <summary> |
| | | 18 | | /// Creates a new instance of the <see cref="WorkflowReferenceGraph"/> class. |
| | | 19 | | /// </summary> |
| | | 20 | | /// <param name="rootDefinitionIds">The IDs of the root workflow definitions from which the graph was built.</param> |
| | | 21 | | /// <param name="edges">The collection of edges representing all reference relationships in the graph.</param> |
| | | 22 | | public WorkflowReferenceGraph(IReadOnlyCollection<string> rootDefinitionIds, IReadOnlyCollection<WorkflowReferenceEd |
| | | 23 | | { |
| | | 24 | | RootDefinitionIds = rootDefinitionIds; |
| | | 25 | | Edges = edges; |
| | | 26 | | |
| | | 27 | | // Pre-compute useful lookups |
| | | 28 | | AllDefinitionIds = ComputeAllDefinitionIds(edges, rootDefinitionIds); |
| | | 29 | | ConsumerDefinitionIds = AllDefinitionIds.Except(rootDefinitionIds).ToHashSet(); |
| | | 30 | | |
| | | 31 | | // Outbound: Source → Targets (what does this workflow depend on?) |
| | | 32 | | OutboundEdges = edges.ToLookup(e => e.Source, e => e.Target); |
| | | 33 | | |
| | | 34 | | // Inbound: Target → Sources (what workflows consume this one?) |
| | | 35 | | InboundEdges = edges.ToLookup(e => e.Target, e => e.Source); |
| | | 36 | | } |
| | | 37 | | |
| | | 38 | | /// <summary> |
| | | 39 | | /// The IDs of the root workflow definitions from which the graph was built. |
| | | 40 | | /// </summary> |
| | | 41 | | public IReadOnlyCollection<string> RootDefinitionIds { get; } |
| | | 42 | | |
| | | 43 | | /// <summary> |
| | | 44 | | /// The collection of edges representing all reference relationships in the graph. |
| | | 45 | | /// Each edge represents a single Source → Target relationship. |
| | | 46 | | /// </summary> |
| | | 47 | | public IReadOnlyCollection<WorkflowReferenceEdge> Edges { get; } |
| | | 48 | | |
| | | 49 | | /// <summary> |
| | | 50 | | /// All workflow definition IDs in the graph, including the roots and all consumers. |
| | | 51 | | /// </summary> |
| | | 52 | | public IReadOnlySet<string> AllDefinitionIds { get; } |
| | | 53 | | |
| | | 54 | | /// <summary> |
| | | 55 | | /// All workflow definition IDs that consume (directly or indirectly) the root workflow definitions. |
| | | 56 | | /// Does not include the roots themselves. |
| | | 57 | | /// </summary> |
| | | 58 | | public IReadOnlySet<string> ConsumerDefinitionIds { get; } |
| | | 59 | | |
| | | 60 | | /// <summary> |
| | | 61 | | /// A lookup that maps each workflow definition ID to the IDs of workflows it depends on (references). |
| | | 62 | | /// Use this to find: "What workflows does X reference?" |
| | | 63 | | /// </summary> |
| | | 64 | | public ILookup<string, string> OutboundEdges { get; } |
| | | 65 | | |
| | | 66 | | /// <summary> |
| | | 67 | | /// A lookup that maps each workflow definition ID to the IDs of workflows that reference it. |
| | | 68 | | /// Use this to find: "What workflows consume X?" |
| | | 69 | | /// </summary> |
| | | 70 | | public ILookup<string, string> InboundEdges { get; } |
| | | 71 | | |
| | | 72 | | /// <summary> |
| | | 73 | | /// Gets all workflow definition IDs that the specified workflow depends on (references). |
| | | 74 | | /// </summary> |
| | | 75 | | public IEnumerable<string> GetDependencies(string definitionId) => OutboundEdges[definitionId]; |
| | | 76 | | |
| | | 77 | | /// <summary> |
| | | 78 | | /// Gets all workflow definition IDs that reference (consume) the specified workflow. |
| | | 79 | | /// </summary> |
| | | 80 | | public IEnumerable<string> GetConsumers(string definitionId) => InboundEdges[definitionId]; |
| | | 81 | | |
| | | 82 | | private static HashSet<string> ComputeAllDefinitionIds(IReadOnlyCollection<WorkflowReferenceEdge> edges, IReadOnlyCo |
| | | 83 | | { |
| | | 84 | | var ids = new HashSet<string>(rootDefinitionIds); |
| | | 85 | | |
| | | 86 | | foreach (var edge in edges) |
| | | 87 | | { |
| | | 88 | | ids.Add(edge.Source); |
| | | 89 | | ids.Add(edge.Target); |
| | | 90 | | } |
| | | 91 | | |
| | | 92 | | return ids; |
| | | 93 | | } |
| | | 94 | | } |
| | | 95 | | |