State Machine Requests
Sagas can also send requests, and then react to the responses.
Declaring Requests
public record ValidateOrder(Guid OrderId);
public record OrderValidated(Guid OrderId);
public class OrderStateMachine :
MassTransitStateMachine<OrderState>
{
// Generic Types
// 1. Saga State
// 2. Request Message
// 3. Response Message
public Request<OrderState, ValidateOrder, OrderValidated> ValidateOrder { get; private set; } = null!;
}
Configuring Requests
public class OrderStateMachine :
MassTransitStateMachine<OrderState>
{
public Request<OrderState, ValidateOrder, OrderValidated> ValidateOrder { get; private set; } = null!;
public OrderStateMachine()
{
Request(() => ValidateOrder, o =>
{
o.Timeout = TimeSpan.FromDays(1);
});
}
}
Sending Requests
public class OrderStateMachine :
MassTransitStateMachine<OrderState>
{
public Request<OrderState, ValidateOrder, OrderValidated> ValidateOrder { get; private set; } = null!;
public OrderStateMachine()
{
Initially(When(OnRequest)
.Request(ValidateOrder, sendContext => {
var saga = sendContext.Saga;
var msg = sendContext.Message;
return new ValidateOrder();
})
.TransitionTo(Requested));
During(Requested,
// handle the consumer successfully responding
When(ValidateOrder.Completed)
.TransitionTo(Completed),
// handle the consumer throwing an exception
When(ValidateOrder.Faulted)
.TransitionTo(Failed)
);
}
}
Request Overrides
.Request(ValidateOrder, sendAddress, context => new ValidateOrder())
.Request(ValidateOrder, _ => sendAddress, context => new ValidateOrder())
.Request(ValidateOrder, sendAddress, async context =>
{
await Task.Delay(1);
return new ValidateOrder();
});
.Request(ValidateOrder, _ => sendAddress, async context =>
{
await Task.Delay(1);
new ValidateOrder();
})
.Request(ValidateOrder, _ => sendAddress, context => Task.FromResult(new ValidateOrder())
Handling Responses
The defined Request ValidateOrder
exposes a few handy properties for use when connecting the saga back to the response.
public class OrderStateMachine :
MassTransitStateMachine<OrderState>
{
public Request<OrderState, ValidateOrder, OrderValidated> ValidateOrder { get; private set; } = null!;
public OrderStateMachine()
{
// elided
During(Requested,
// handle the consumer successfully responding
When(ValidateOrder.Completed)
.TransitionTo(Completed),
// handle the consumer throwing an exception
When(ValidateOrder.Faulted)
.TransitionTo(Failed)
);
}
}
Event Property | Comment |
---|---|
Completed | Traps a successful response |
Completed2 | Traps an alternate response type |
Completed3 | Traps an alternate response type |
Faulted | Traps the Faulted<T> from the consumer throwing an exception |
TimeoutExpired | Traps the request timing out |
State Property | Comment |
---|---|
Pending | A convenience state you can transition to |