using System; using System.Collections.Generic; using System.Linq; namespace Tapeti.Flow.Default { /// <summary> /// Represents the state stored for active flows. /// </summary> public class FlowState { private FlowMetadata? metadata; private Dictionary<Guid, ContinuationMetadata>? continuations; /// <summary> /// Contains metadata about the flow. /// </summary> public FlowMetadata Metadata { get => metadata ??= new FlowMetadata(null); set => metadata = value; } /// <summary> /// Contains the serialized state which is restored when a flow continues. /// </summary> public string? Data { get; set; } /// <summary> /// Contains metadata about continuations awaiting a response. /// </summary> public Dictionary<Guid, ContinuationMetadata> Continuations { get => continuations ??= new Dictionary<Guid, ContinuationMetadata>(); set => continuations = value; } /// <summary> /// Creates a deep clone of this FlowState. /// </summary> public FlowState Clone() { return new FlowState { metadata = metadata?.Clone(), Data = Data, continuations = continuations?.ToDictionary(kv => kv.Key, kv => kv.Value.Clone()) }; } } /// <summary> /// Contains metadata about the flow. /// </summary> public class FlowMetadata { /// <summary> /// Contains information about the expected response for this flow. /// </summary> public ReplyMetadata? Reply { get; } /// <inheritdoc cref="FlowMetadata"/> public FlowMetadata(ReplyMetadata? reply) { Reply = reply; } /// <summary> /// Creates a deep clone of this FlowMetadata. /// </summary> public FlowMetadata Clone() { return new FlowMetadata(Reply); } } /// <summary> /// Contains information about the expected response for this flow. /// </summary> public class ReplyMetadata { /// <summary> /// The queue to which the response should be sent. /// </summary> public string? ReplyTo { get; set; } /// <summary> /// The correlation ID included in the original request. /// </summary> public string? CorrelationId { get; set; } /// <summary> /// The expected response message class. /// </summary> public string? ResponseTypeName { get; set; } /// <summary> /// Indicates whether the response should be sent a mandatory. /// False for requests originating from a dynamic queue. /// </summary> public bool Mandatory { get; set; } /// <summary> /// Creates a deep clone of this ReplyMetadata. /// </summary> public ReplyMetadata Clone() { return new ReplyMetadata { ReplyTo = ReplyTo, CorrelationId = CorrelationId, ResponseTypeName = ResponseTypeName, Mandatory = Mandatory }; } } /// <summary> /// Contains metadata about a continuation awaiting a response. /// </summary> public class ContinuationMetadata { /// <summary> /// The name of the method which will handle the response. /// </summary> public string? MethodName { get; set; } /// <summary> /// The name of the method which is called when all responses have been processed. /// </summary> public string? ConvergeMethodName { get; set; } /// <summary> /// Determines if the converge method is synchronous or asynchronous. /// </summary> public bool ConvergeMethodSync { get; set; } /// <summary> /// Creates a deep clone of this ContinuationMetadata. /// </summary> public ContinuationMetadata Clone() { return new ContinuationMetadata { MethodName = MethodName, ConvergeMethodName = ConvergeMethodName, ConvergeMethodSync = ConvergeMethodSync }; } } }