Skip to content
Tutorial4/4

4. Route between Components

Add a web shop loader that receives placed orders and never sees cancellations.

From the distribution-workspace root (cd .. if you are still in order-notifications/), the same command as chapter 1 with the new names:

Terminal window
intropy int create loader -n WebLoader -o web-loader \
--subscribes order-placed -s topic=orders -s organization=Fluxia -s empty=false
using cached integrio-intropy/intropy-templates@v2.0.0
created web-loader from integrio-intropy/intropy-templates@v2.0.0 (template loader)
dependency Contracts already scaffolded from shared-contracts — skipped

The loader has one pipeline, for order-placed. Which messages reach it is decided in the System.

Edit three host files. First add the web shop Port (doc comments omitted here):

order-notifications/Ports.cs
public static class Ports
{
public static readonly PortRef ErpExtractorSource = PortRef.Define("erp-extractor-source");
public static readonly PortRef WebLoaderDestination = PortRef.Define("web-loader-destination");
public static readonly PortRef WmsLoaderDestination = PortRef.Define("wms-loader-destination");
}

Then add the Component. The AddLoader name must match the web-loader directory:

order-notifications/OrderNotificationsSystem.cs: Define
public void Define(SystemBuilder builder)
{
builder.AddExtractor("erp-extractor")
.From(Ports.ErpExtractorSource)
.Publishes(Messages.OrderPlaced)
.Publishes(Messages.OrderCancelled)
.Calls(Services.Idempotency)
.Calls(Services.BusinessIncidents);
builder.AddLoader("web-loader")
.Subscribes(Messages.OrderPlaced,
configure: sub => sub
.IgnoreOthers())
.To(Ports.WebLoaderDestination)
.Calls(Services.Idempotency)
.Calls(Services.BusinessIncidents);
// Rendered as a declarative Dapr Subscription: one routing rule per route, in order,
// and a default route for the rest of the topic. The subscription's first message
// anchors it; the rest are also handled on the same channel.
builder.AddLoader("wms-loader")
.Subscribes(Messages.OrderPlaced,
configure: sub => sub
.AlsoHandles(Messages.OrderCancelled)
.IgnoreOthers())
.To(Ports.WmsLoaderDestination)
.Calls(Services.Idempotency)
.Calls(Services.BusinessIncidents);
}

Every loader on the topic receives its own copy of every message, so web-loader also receives order-cancelled. Its subscription does not handle that message, so the sidecar delivers it on the default route. IgnoreOthers() acknowledges and drops it. Without IgnoreOthers(), the message stays unacknowledged and the broker dead-letters it.

Last, resolve the new Port to a local folder:

order-notifications/OrderNotificationsDevelopment.cs: Define
public void Define(DevelopmentBuilder development)
{
development.Mock(Services.Idempotency).FromOpenApi("mocks/idempotency-service.openapi.yaml");
development.Mock(Services.BusinessIncidents).FromOpenApi("mocks/business-incident-service.openapi.yaml");
development.Files(Ports.ErpExtractorSource).RootPath("./test/erp-extractor-source");
development.Files(Ports.WebLoaderDestination).RootPath("./test/web-loader-destination");
development.Files(Ports.WmsLoaderDestination).RootPath("./test/wms-loader-destination");
development.Rerun("erp-extractor").AfterEachRun(TimeSpan.FromSeconds(30));
}

No other host files change.

Terminal window
cd order-notifications
task check
task generate
cat out/components/web-loader-subscription.yaml

task check ends with:

ok: 'order-notifications' is valid (3 components).
out/components/web-loader-subscription.yaml
apiVersion: dapr.io/v2alpha1
kind: Subscription
metadata:
name: "web-loader-subscription"
spec:
pubsubname: "order-notifications-pubsub"
topic: "orders"
routes:
rules:
- match: "event.type == 'order-placed'"
path: "/order-placed"
default: "/unhandled"
scopes:
- "web-loader"

Subscribes and AlsoHandles also take a when: argument: a Dapr CEL expression over the event, such as event.data.status == '0', that the sidecar appends to the type match.

Terminal window
task seed
task run

In a second terminal, from order-notifications/:

Terminal window
ls test/wms-loader-destination test/web-loader-destination
test/web-loader-destination:
ORD-1001.order-placed.json
test/wms-loader-destination:
ORD-1001.order-placed.json
ORD-1002.order-cancelled.json

wms-loader received both messages. web-loader received only the placed order. The cancellation arrived on its default route and was acknowledged without reaching a pipeline.

Stop the host with Ctrl+C.

Continue with the transactional integration tutorial to write a Component pipeline step by step. Use Build, connect, deploy when the System is ready to move toward real environments.