How the shop's flows work, and how to write your own¶✎ edit
A flow is what d2 does when something happens: a message comes in, the rules that handle it run, one statement after another, and each can send more messages. The shop's flows start from changes to its data: when an object is created or updated, d2 raises an event (diesel.entity.on.created, diesel.entity.on.updated), and a project's rules can handle it.
1. A new cart, end to end¶✎ edit
Someone creates a
Cart(in the data, through the API, or from another flow's page).d2 raises
diesel.entity.on.created (category = "Cart", key = "<the cart's id>")in this project.Init has a rule for it, with a guard so it only takes carts:
$when diesel.entity.on.created (category, key) if (category is "Cart") { shop.cartCreated(id = key) }That sends
shop.cartCreated, the shop's own message, handled in shop-carts: it finds the cart and its customer (dom.find) and sendsshop.notify.shop.notify(shop-notify) is the one place every message goes through; here it keeps the message in the shop's outbox (Messageobjects).
Why two steps (the trigger, then the shop's message)? The trigger only decides when; the flow says what. You can run the flow by hand in the fiddle (shop-flows) without making a cart, and another flow can call it too.
2. An order placed¶✎ edit
shop-orders does three things for a new Order: an Invoice, a stock reservation for each line (shop.reserve, from the first warehouse with enough), and a thank-you. Two things to notice:
o.lines map (l => shop.reserve(sku = l.sku, qty = l.qty)): a message sent for each line, the results collected in a list.- A flow's own changes to objects don't set off more flows, so a busy flow can't start a chain. That's why
shop.reserveasks for the stock check (shop.checkStock) itself instead of relying on the trigger for stock updates.
3. Abandoned carts, on a schedule¶✎ edit
Some flows start from the clock. Init declares a cron every time the project starts:
$when diesel.project.on.init {
diesel.cron(name = "abandoned-carts", schedule = "daily 03:00", msg = "shop.abandonedCarts", args = {hours: 48})
}
Every day at 03:00 it sends shop.abandonedCarts (hours = 48): carts open for more than 48 hours are marked abandoned and their customers nudged. See the project's crons on Crons.
Writing your own¶✎ edit
- Model what you track (a
Spec:topic with$classlines). - Write the flow as your own message (
$when myapp.somethingHappened (id: String) { … }) in aSpec:topic, with a sentence above it saying what it's for. - Try it by hand in the fiddle with a
Story:topic ($send, then$expectwhat it should give). - Connect it to the data with a trigger in
Settings:Init($when diesel.entity.on.created (category, key) if (category is "…")), or to the clock with a cron.