Use case
Payments & stateful flows
Money paths have to be legible. bloccs lays the flow out as a typed graph: validate and dedupe before anything moves, branch on state, then capture and book the ledger as separate supervised sinks. Idempotency and the DB/HTTP boundaries are declared, so a retry can't double-charge and a stray effect can't compile.
The flow
Where this stands today
Where this stands today: idempotency, DB reads and writes, outbound capture, and supervised recovery are all shipped in 0.8 — the core of this flow runs on real adapters. As with any source, charge is fed by your web layer; bloccs doesn't serve HTTP itself.
Source of truth
The manifest
The whole network is one TOML file. Drop it in, run mix bloccs.compile, and bloccs emits a
Broadway supervision tree from it — the compiler checks every edge, schema, and
declared effect first.
- Edges match ports by schema, or it won't compile.
- Effects are declared per node — nothing touches the outside world undeclared.
- Supervision and concurrency are part of the file, not an afterthought.
[network]
id = "payments"
version = "0.1.0"
runtime = "beam"
[nodes]
charge = { use = "nodes/charge.bloccs" }
validate = { use = "nodes/validate.bloccs" }
dedupe = { use = "nodes/dedupe.bloccs" }
branch = { use = "nodes/branch.bloccs" }
capture = { use = "nodes/capture.bloccs" }
ledger = { use = "nodes/ledger.bloccs" }
[[edges]]
from = "charge.created"
to = "validate.charge"
[[edges]]
from = "validate.valid"
to = "dedupe.charge"
[[edges]]
from = "dedupe.fresh"
to = "branch.charge"
# Fan-out: capture at the provider and book the ledger entry.
[[edges]]
from = "branch.authorized"
to = ["capture.charge", "ledger.entry"]
[expose]
in = { charge = "charge.created" }
out = { captured = "capture.captured", booked = "ledger.booked" }
[supervision]
strategy = "rest_for_one"
max_restarts = 3
max_seconds = 60
[deploy]
concurrency = { capture = 1, ledger = 1 }
Anatomy
Node by node
Each node declares its kind and the capabilities it's allowed to use. Pure nodes touch nothing; effectful nodes carry a badge for exactly what they reach.
charge
Source +HTTPReceives the charge request as a typed Charge@1.
validate
NodeChecks amount, currency, and shape. Pure and deterministic.
dedupe
Node +DBLooks up the idempotency key so a retried request can't double-charge.
branch
SplitRoutes on charge state — only authorized charges proceed to capture.
capture
Sink +HTTPCaptures at the payment provider. The outbound call is a scoped capability.
ledger
Sink +DBWrites the double-entry ledger row. Runs alongside capture under supervision.