Why plugs are stateless first
Why plugs derive what they need from the session id, and when stored state is the better tool.
Plugs should work out what they need again on every run, from their inputs and the session id. A worktree is at a path that comes from the session id. A container is named after the session. A run that resumes finds both without asking anyone.
What this buys
- Nothing to lose. A plug that stores nothing cannot leave a record behind, cannot read a stale one, and cannot have two runners disagree about it.
- Configuration changes apply. If
blaise.ymlchanges while a session is paused, a stateless plug uses the new inputs on the next run. Plugs may be reordered, added or removed without any migration. - Any instance of a runner can resume. Blaise sends a resume back to the runner that paused, and the instances that share its token are interchangeable. A stateless plug finds the environment by name, wherever the instance is, as long as it can reach it.
- Less to test. The harness needs no store, and a plug has no schema to evolve.
Every plug we ship is stateless.
When state is the right tool
Some things cannot be derived. A database provider chooses the id of a branch it creates; the plug
cannot compute it again. For those, a plug declares a persisted schema, and Blaise keeps a small
JSON value for the session and the plug. Because Blaise has to match the value to the plug, the
entry in blaise.yml needs an id.
The costs are real:
- A crash between creating the resource and recording its id leaves a resource nobody knows about. A plug records the id right after it creates the resource, and waits for the write.
- The value outlives the plug's code. When the plug changes its schema, stored values no longer
validate, and
onMigratehas to convert them. - The value outlives the configuration. A plug whose
idis removed, or replaced by another plug, leaves a record with no owner. Blaise reports it as orphaned instead of handing it to the wrong plug.
A rule of thumb
If you can write the name of the resource from the session id and your inputs, derive it. If the name comes from somewhere else, store it, keep the value small, and never store a secret in it: the value is encrypted at rest and hidden in the dashboard, but credentials are re-derived on every run.
How to write each kind: Write a stateless plug and Store state and migrate it. The rules and limits of stored state are in Persisted state.