Documents › FlowsGuide · version 1 ·
tags
#shop #guide

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

  1. Someone creates a Cart (in the data, through the API, or from another flow's page).

  2. d2 raises diesel.entity.on.created (category = "Cart", key = "<the cart's id>") in this project.

  3. 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)
    }
    
  4. That sends shop.cartCreated, the shop's own message, handled in shop-carts: it finds the cart and its customer (dom.find) and sends shop.notify.

  5. shop.notify (shop-notify) is the one place every message goes through; here it keeps the message in the shop's outbox (Message objects).

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.reserve asks 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

  1. Model what you track (a Spec: topic with $class lines).
  2. Write the flow as your own message ($when myapp.somethingHappened (id: String) { … }) in a Spec: topic, with a sentence above it saying what it's for.
  3. Try it by hand in the fiddle with a Story: topic ($send, then $expect what it should give).
  4. 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.