Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Weft The book

Starting and stopping things

Every verb for the three lifecycles, what it leaves behind, and what to run after you change something. For why they are three separate things, go and read the three lifecycles.

Infrastructure

A program has infrastructure when one of its steps needs a container of its own, which you can see in the source because the step says so:

pg = PostgresDatabase { database: "imagebot" }

Nothing starts it for you. Not weft run, not weft build, not activation.

CommandWhat it does
weft infra startBrings up whatever is down and leaves whatever is already up alone
weft infra stopScales to nothing and keeps the disk. Start it again and your rows are there
weft infra terminateDeletes it, disk included, unless the step asked for the disk to be kept
weft infra upgradeRebuilds against your current source. Leaves the project deactivated afterwards, so you choose when the new version takes traffic
weft infra statusWhere each piece stands, with its address
weft infra doorsThe addresses this project’s infra answers on
weft infra logs <node>What the containers actually printed
weft infra cancelStops waiting on work in flight
weft infra node-stop <node> / node-terminate <node>The same, for one piece

weft infra status prints one line per piece:

infra for imagebot (a1b2…):
  pg [running] -> postgres://…
StatusWhat it means
provisioningComing up
runningAt least one pod is ready
stoppedScaled to nothing, disk kept
flakyIt was healthy and has dropped below its readiness threshold
failedThe last apply failed. The message says at which stage

A project-wide partial is a real steady state rather than something in transit: some pieces are up and some are not.

When it hangs

weft puts no time limit on a container coming up, because a model server pulling weights can take a long time. So a bad image or a probe that never passes looks like waiting, not like an error.

Read weft infra logs <node> first, because that is where a service says what went wrong. Then weft infra cancel. Cancel halts between steps rather than undoing what it did, so the piece is left partly applied and marked failed; check weft infra status and either terminate it or run the verb again.

Infra you deleted from the source

Deleting the step does not delete the container. weft status warns you that live infrastructure exists whose node is gone from the source, and it keeps running, and costing, until you stop or terminate it. The verbs stay available for exactly that reason.

Triggers

weft activate runs each trigger’s setup once, then leaves the listeners running. Setup is not bookkeeping: it registers subscriptions with providers and dials sockets, and it fails loudly if it cannot, rather than minting a trigger that looks live and is dead.

What you wantRun
My program should answer the world nowweft activate
Stop it answeringweft deactivate
I edited something a trigger reads, and it is liveweft resync
Prepare a trigger without exposing it yetweft bake
Try one trigger with an event I made upweft run --fire <trigger>='<json>'
I clicked activate and want it backweft cancel-activate

Project status moves registered → activating → active → deactivating → inactive.

One trigger at a time

Each trigger is turned on separately, so weft activate --trigger inbound turns on one and leaves the rest alone; for the other flags, go and read the CLI. The project shows active while any of its shared triggers listens and none is part way through turning on or off, and weft status lists each trigger’s own state under triggers:.

A trigger that reads a member’s copy or a member’s value (@per_member, @member_filled) exists once per member, and its copies are turned on with --member <id>. For those, go and read programs with members.

Frozen inputs

Setup snapshots the trigger’s input values along with the registration, and a fire replays that snapshot. So a trigger’s inputs are whatever they were when you last ran setup. Change one and weft tells you the bake is stale:

the code changed since trigger 'inbound' was last prepared, so its bake is stale.
Prepare it again: `weft bake` does it without listening, `weft activate` does it and listens

Choosing what happens to work in flight

weft deactivate and weft resync both ask:

ModeWhat it does
wipeDrops every waiting signal and cancels suspended runs. A clean slate, and what you want while building
hibernateKeeps the signals, hides pending tasks from the browser extension, parks late answers
parkKeeps the signals visible and queues new answers until you reactivate

With no terminal attached, or with --json, the default is wipe. Running executions are cancelled unless you pass --running-policy wait, which lets them land first, capped at a minute (--drain-timeout), and weft cancel-running ends that wait early.

The infra verbs that take triggers down (weft infra stop, terminate, upgrade) ask you the same thing, and their answer means the same. They ask only when a trigger reading that infrastructure is on, the program’s own or a member’s. With no terminal, or with --json, they do not pick for you: they stop and name the flags, for example --mode park --running-policy wait, and if you passed those flags already they are used. When no trigger reading it is on, nothing is asked, but a run may still be using that infrastructure: --running-policy wait on its own lets it land before the containers go.

weft activate and weft bake make the same choice about a worker still up from an older build: by default what it runs is cancelled and it is replaced now; with --running-policy wait its executions land first. While it waits, nothing new is sent to that worker, and once its last execution lands the worker finishes writing down what it owes (a metered call’s cost) and leaves on its own, which takes a second or two; the cap covers both.

Reactivating a project that kept state asks you again: drain the parked work and keep the suspensions, keep the suspensions only, or wipe everything.

Infra has to be up first

A trigger that reads its address off one of your containers cannot be set up until that container answers:

these triggers' infra is not running: pg. Start it with `weft infra start`, then run this again.

Infrastructure that only a run touches does not hold activation back.

Executions

It starts fromCommand
Youweft run
One trigger, by handweft run --fire <trigger>='<json>'
A trigger firing for realNothing. It happens because you activated
A caller connectingNothing. The project has to be active
StatusWhat it means
runningWork is happening now
waiting_for_inputParked on a person or a service. No worker is up and nothing is being spent
completedFinished
failedA step failed, or the run could get no further
cancelledYou or another run stopped it

weft executions --status running lists both the ones working and the ones waiting, and the status column tells them apart.

Waiting, and stuck

Waiting means somebody still has to answer. Stuck means nobody can: steps are holding values that will never add up to enough to run them, and nothing is parked on a signal, so no answer exists that would move it along.

weft ends a stuck run as failed and names every step and what each is short of:

execution stuck: 2 firings hold pulses and can never fire: theirs has value,
still waiting on go; leaf has value, every wired input arrived

That is a bug in the shape of your graph rather than something to wait out.

Stopping one

weft stop <color> cancels it. If a worker is up, it stops within about fifty milliseconds. If the run was parked, the cancellation is written down and the listener forgets its signals, so a late answer finds nothing.

Work already done stays done, and weft cannot take back a message, an email or a payment your program already sent.

Cancelling a run that already ended is refused rather than silently ignored, so weft stop on yesterday’s run tells you it has already finished.

After you change something

weft status compares your source against what is running and names the verb:

drift:
  infra: source has changed; `weft infra upgrade` rebuilds it
  binary: worker code has changed; the next run or `weft build` rebuilds the image
  definition: project shape has changed; the next run picks it up
  activation: the listeners fire an older program; `weft resync` re-registers them
What you changedWhat to run
The shape of the graphNothing. The next run picks it up
A node’s Rust codeNothing. The next run rebuilds it
What an infra step asks forweft infra upgrade, then weft activate
Anything a trigger reads, on a live projectweft resync

Until you resync, the subscription sitting at the provider is still pointed at the program you had before.