Junction
The base class of a junction: one unit of work in a train's chain, taking a TIn and producing a TOut. You implement Run; the base class handles the railway. When an earlier junction has failed, Run is not called and the failure passes through.
In a ServiceTrain, derive from EffectJunction instead when the junction should be visible to the junction logger and junction progress.
Signature
namespace Trax.Core.Junction;
public interface IJunction<TIn, TOut>
{
Task<TOut> Run(TIn input);
}
public abstract class Junction<TIn, TOut> : IJunction<TIn, TOut>
{
protected Junction();
public CancellationToken CancellationToken { get; protected set; }
public abstract Task<TOut> Run(TIn input);
}IJunction<TIn, TOut> and Junction<TIn, TOut> also carry a public RailwayJunction method, and Junction a public Result property. Both are hidden from completion: the train calls them, you do not.
Type Parameters
| Type Parameter | Description |
|---|---|
TIn | The junction's input. The train takes it from Memory by type. A tuple input is assembled from several Memory values. |
TOut | The junction's output. The train stores it in Memory by type for later junctions and for Resolve(). Use Unit for a junction that produces nothing. |
Members
| Member | Description |
|---|---|
Run(TIn input) | Your implementation. Return the output, or throw to fail the train. |
CancellationToken | The running train's token, set before Run is called. Pass it to anything you await. |
Behavior
- A failed predecessor skips
Run. The earlier failure is returned unchanged. - Cancellation is checked first. If the train's token is already cancelled,
Runis not called and the run ends cancelled. - An exception becomes the failure. Whatever
Runthrows is caught and returned as the train'sLeft, with aTrainExceptionData(train name, runExternalId, junction name, exception type, message, stack trace) attached inexception.Data["TrainExceptionData"]. The exception's own message is not changed. AnOperationCanceledExceptionthrown while the train's token is cancelled propagates as cancellation instead, with no data attached. See TrainException.
Example
using Trax.Core.Junction;
public class ChargePayment(IPaymentGateway gateway) : Junction<ValidatedOrder, PaymentReceipt>
{
public override async Task<PaymentReceipt> Run(ValidatedOrder order) =>
await gateway.Charge(order.CustomerId, order.Total, CancellationToken);
}The train builds the junction itself, taking IPaymentGateway for its constructor from Memory or, in a ServiceTrain, from the container. Use constructor injection; do not put [Inject] on a junction's properties (see Inject).
Remarks
- A junction instance is created for each chain step. Keep per-run state in locals, not fields.
Junctiondoes not record anything.EffectJunctionadds the per-junction metadata the junction effects read.
See Junctions for the concepts.
Package
dotnet add package Trax.Core