Rebasely Beta: data may be purged

examples/storefront Public

Markdown · 1.8 KiB · at 48ffd57

id: fulfilment
type: concept
owner: justin
component: fulfilment
describes:
  - workers/fulfilment/src/**
  - migrations/0004_shipments.sql
reviewed: 2026-10-07

Fulfilment

The storefront-fulfilment Worker turns paid orders into shipments. It consumes the order-events queue ([[order-events]]) and talks to two things: storefront-api's OrdersService over the ORDERS service binding, and the warehouse's HTTP API at WAREHOUSE_URL.

Handling an event

For each order.paid message:

  1. OrdersService.forFulfilment(order) returns the current order. If it is not paid any more (already fulfilled, which means this message is a repeat, or cancelled), the message is acked and nothing else happens.
  2. POST {WAREHOUSE_URL}/v1/shipments with the address and the lines, and Idempotency-Key: order-<id>.
  3. OrdersService.recordShipment(order, shipment_id) moves the order to fulfilled and stores the shipment id.

Every other event type is acked and ignored. The steps are drawn in the order fulfilment flow on the Architecture tab.

Failures

Each message in a batch is acked or retried on its own, so one bad order does not hold back the rest. Any error (the warehouse answering 4xx or 5xx, a timeout, OrdersService failing) retries the message after backoff(attempts): 30 seconds, doubling, at most an hour. After six retries the queue moves the message to order-events-dlq. Messages there are orders a person has to look at; the logged error says why each one failed.

Why repeating step 2 is safe is in [[0007-at-least-once-with-idempotency-keys]].

Running it locally

npx wrangler dev -c workers/fulfilment/wrangler.jsonc with WAREHOUSE_URL and WAREHOUSE_TOKEN in .dev.vars next to that config. With storefront-api running in another terminal, wrangler connects the service binding and the local queue.