using MessageFlow;
namespace MessageFlow.Samples;
///
/// Shows how the cancellation token flows from
/// down to every handler.
///
public static class CancellationSample
{
///
/// Builds a chain whose handler observes the cancellation token before doing any work.
///
/// The composed chain.
public static IChain BuildChain()
=> Chain.Create()
.Use(async (request, next, cancellationToken) =>
{
cancellationToken.ThrowIfCancellationRequested();
return await next(request, cancellationToken).ConfigureAwait(false);
})
.WithFallback(async (request, _) =>
{
await Task.Yield();
return $"processed:{request}";
})
.Build();
///
/// Executes a request and turns cancellation into a readable description.
///
/// The chain to execute.
/// The request to send.
/// A token used to cancel the operation.
/// The response, or the name of the cancellation exception.
public static async Task DescribeAsync(
IChain chain,
string request,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(chain);
try
{
return await chain.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
return nameof(OperationCanceledException);
}
}
///
/// Runs the sample once with a live token and once with an already cancelled token.
///
/// The writer receiving the sample output.
/// A token used to cancel the operation.
/// The successful response followed by the name of the cancellation exception.
public static async Task> RunAsync(
TextWriter output,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(output);
var chain = BuildChain();
using var cancelled = new CancellationTokenSource();
await cancelled.CancelAsync().ConfigureAwait(false);
var results = new List();
foreach (var token in new[] { cancellationToken, cancelled.Token })
{
var description = await DescribeAsync(chain, "job", token).ConfigureAwait(false);
results.Add(description);
await output.WriteLineAsync($"job => {description}").ConfigureAwait(false);
}
return results;
}
}