Routing Slip Builder
Instead of directly implementing the RoutingSlip message type, developers are encouraged to use a RoutingSlipBuilder to construct the routing slip. The RoutingSlipBuilder simplifies the process by providing methods to add activities (and their arguments), activity logs, and variables to the routing slip. For example, to create a routing slip with two activities and an additional variable, a developer might write:
var builder = new RoutingSlipBuilder(NewId.NextGuid());
var routingSlip = builder.Build();Add routing slip activities
Section titled “Add routing slip activities”var builder = new RoutingSlipBuilder(NewId.NextGuid());
builder.AddActivity("DownloadImage", new Uri("rabbitmq://localhost/execute_downloadimage"), new { ImageUri = new Uri("https://images.google.com/someImage.jpg") });
builder.AddActivity("FilterImage", new Uri("rabbitmq://localhost/execute_filterimage"));
builder.AddVariable("WorkPath", @"\dfs\work");
var routingSlip = builder.Build();Each activity requires a name for display purposes and a URI specifying the execution address. The execution address is where the routing slip should be sent to execute the activity. For each activity, arguments can be specified that are stored and presented to the activity via the activity arguments interface type specified by the first argument of the IActivity interface. The activities added to the routing slip are combined into an Itinerary, which is the list of activities to be executed and stored in the routing slip.
Managing the inventory of available activities, as well as their names and execution addresses, is the responsibility of the application and is not part of the MassTransit Courier. Since activities are application-specific, and the business logic to determine which activities to execute and in what order is part of the application domain, the details are left to the application developer.
Specify activity arguments
Section titled “Specify activity arguments”Each activity declares an activity argument type, which must be an interface. When the routing slip is received by an activity host, the argument type is used to read data from the routing slip and deliver it to the activity.
The argument properties are mapped, by name, to the argument type from the routing slip using:
- Explicitly declared arguments, added to the itinerary with the activity
- Implicitly mapped arguments, added as variables to the routing slip
To specify an explicit activity argument, specify the argument value while adding the activity using the routing slip builder.
var builder = new RoutingSlipBuilder(NewId.NextGuid());builder.AddActivity("DownloadImage", new Uri("rabbitmq://localhost/execute_downloadimage"), new { ImageUri = new Uri("https://images.google.com/someImage.jpg") });| Parameter | Notes |
|---|---|
| name | This is a human readable label for the activity |
| address | The address of the endpoint where the activity is listening. Short Addresses are also supported. |
| args | values to be bound to the Args type defined in this activity, not shared |
Add routing slip variables
Section titled “Add routing slip variables”To specify an implicit activity argument, add a variable to the routing slip with the same name/type as the activity argument.
var builder = new RoutingSlipBuilder(NewId.NextGuid());builder.AddActivity("DownloadImage", new Uri("rabbitmq://localhost/execute_downloadimage"));builder.AddVariable("ImageUri", "https://images.google.com/someImage.jpg");These values are shared across activities. This is a great way to pass data from one activity to the next.
| Parameter | Notes |
|---|---|
| key | The key to retrieve it from later |
| value | The value |
If an activity argument is not specified when the routing slip is created, it may be added by an activity that executes prior to the activity that requires the argument. For instance, if the DownloadImage activity stored the image in a local cache, that address could be added and used by another activity to access the cached image.
First, the routing slip would be built without the argument value.
var builder = new RoutingSlipBuilder(NewId.NextGuid());builder.AddActivity("DownloadImage", new Uri("rabbitmq://localhost/execute_downloadimage"));builder.AddActivity("ProcessImage", new Uri("rabbitmq://localhost/execute_processimage"));builder.AddVariable("ImageUri", "https://images.google.com/someImage.jpg");Then, the first activity would add the variable to the routing slip on completion.
async Task<ExecutionResult> Execute(ExecuteContext<DownloadImageArguments> context){ ... return context.CompletedWithVariables(new { ImagePath = ...});}The process image activity would then use that variable as an argument value.
async Task<ExecutionResult> Execute(ExecuteContext<ProcessImageArguments> context){ var path = context.Arguments.ImagePath;}Add an event subscription
Section titled “Add an event subscription”By default, routing slip events are published — which means that any subscribed consumers will receive the events. While this is useful getting started, it can quickly get out of control as applications grow and multiple unrelated routing slips are used. To handle this, subscriptions can be used to change the way routing slip events are produced.
Subscriptions are added to the routing slip at the time it is built using the RoutingSlipBuilder.
builder.AddSubscription(new Uri("rabbitmq://localhost/log-events"), RoutingSlipEvents.All);| Parameter | Notes |
|---|---|
| address | Where should routing slip events be sent |
| events | RoutingSlipEvents is a flag enum for selecting desired events |
This subscription would send all routing slip events to the specified endpoint. If the application only wants specific events, those events can be selected by
specifying their enumeration values. For example, to only get the RoutingSlipCompleted and RoutingSlipFaulted events, the following code
would be used.
builder.AddSubscription(new Uri("rabbitmq://localhost/log-events"), RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);It is also possible to tweak the content of the events to cut down on message size. For instance, by default, the RoutingSlipCompleted event includes the
variables from the routing slip. If the variables contained a large document, that document would be copied to the event. Eliminating the variables from the
event would reduce the message size, thereby reducing the traffic on the message broker. To specify the contents of a routing slip event subscription, an
additional argument is specified.
builder.AddSubscription(new Uri("rabbitmq://localhost/log-events"), RoutingSlipEvents.Completed, RoutingSlipEventContents.None);This would send the RoutingSlipCompleted event to the endpoint, without any of the variables be included (only the main properties of the event would be
present).
Once a subscription is added to a routing slip, events are no longer published — they are only sent to the addresses specified in the subscriptions. However, multiple subscriptions can be specified— the endpoints just need to be known at the time the routing slip is built.
Create a custom event subscription
Section titled “Create a custom event subscription”It is also possible to specify a subscription with a custom event, a message that is created by the application developer. This makes it possible to create your
own event types and publish them in response to routing slip events occurring. And this includes having the full context of a regular endpoint Send so that
any headers or context settings can be applied.
To create a custom event subscription, use the overload shown below.
// first, define the event type in your assemblypublic record OrderProcessingCompleted{ public Guid TrackingNumber { get; init; } public DateTime Timestamp { get; init; }
public string OrderId { get; init; } public string OrderApproval { get; init; }}
// then, add the subscription with the custom propertiesbuilder.AddSubscription(new Uri("rabbitmq://localhost/order-events"), RoutingSlipEvents.Completed, x => x.Send<OrderProcessingCompleted>(new { OrderId = "BFG-9000", OrderApproval = "ComeGetSome" }));In the message contract above, there are four properties, but only two of them are specified. By default, the base RoutingSlipCompleted event is created, and
then the content of that event is merged into the message created in the subscription. This ensures that the dynamic values, such as the TrackingNumber and
the Timestamp, which are present in the default event, are available in the custom event.
Custom events can also select with contents are merged with the custom event, using an additional method overload.