using MessageFlow; namespace MessageFlow.Samples; /// /// Glues two independently authored chain fragments into a single chain. /// public static class MergedChainsSample { /// /// Builds the fragment owned by the billing team. /// /// The billing fragment. public static ChainBuilder BuildBillingFragment() => Chain.Create() .Use(new RefundHandler()); /// /// Builds the fragment owned by the accounts team. /// /// The accounts fragment. public static ChainBuilder BuildAccountsFragment() => Chain.Create() .Use(new PasswordResetHandler()); /// /// Merges both fragments into one chain. Tickets neither fragment accepts fall through to the /// fallback of the merged chain. /// /// The composed chain. public static IChain BuildChain() => Chain.Create() .Use(BuildBillingFragment()) .Use(BuildAccountsFragment()) .WithFallback((request, _) => new ValueTask($"escalated ticket {request.Id} to a human")) .Build(); /// /// Runs the sample against one ticket of every kind. /// /// The writer receiving the sample output. /// A token used to cancel the operation. /// The triage decisions, in ticket order. public static async Task> RunAsync( TextWriter output, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(output); var chain = BuildChain(); var tickets = new[] { new Ticket(11, TicketKind.Refund), new Ticket(12, TicketKind.PasswordReset), new Ticket(13, TicketKind.Other), }; var results = new List(); foreach (var ticket in tickets) { var response = await chain.ExecuteAsync(ticket, cancellationToken).ConfigureAwait(false); results.Add(response); await output.WriteLineAsync($"ticket {ticket.Id} ({ticket.Kind}) => {response}").ConfigureAwait(false); } return results; } }