Skip to content

state buckets

Buckets are declared at the top of the config file and referred to by the pipelines that use them — deliberately the shape connections already have, and global for the same reason: one pipeline remembers the current recipe per machine, and six unrelated ones stamp it onto their output.

the rule that isn't enforced

Two pipelines sharing a bucket are two run loops with no ordering between them. Ordering-sensitive correlation has to live in one pipeline; sharing is for state that doesn't change on the timescale of a message. Nothing prevents this — it is a property of what you are computing, not of the config.

Every bucket is bounded and there is no unbounded spelling, expiry is applied when a bucket is touched rather than by a sweeper, and contents survive a config reload unless that bucket's own declaration changed. The narrative, and what remember / recall do with all this, is in state.

state bucket

state.<name>

One named bucket, and the bounds on it.

Both bounds have defaults and neither can be turned off. A keyed store with no limit is not a feature, it is a memory leak that takes a week to show up — so the question is only ever what the limits are.

fieldtypedescription
idle_timeout_secsintegeroptionalforget a key this many seconds after it was last written. Without it a machine that is decommissioned holds its slot until the bucket fills. Measured from the last write rather than the last read: a value nothing has written for an hour is stale whether or not something is still asking for it.
max_keysintegeroptionalmost keys to hold at once. Past this the least recently written key is dropped to make room, so a bucket is a cache of the active keys rather than a record of every key ever seen. Defaults to 10000.

pipeline state

pipelines[].state

A pipeline's binding to a bucket: which one, and what its messages are keyed by.

The key lives here rather than on the bucket because it is a property of this stream — the same machine id arrives as _meta.machine_id from a nats subscription and as machine_id after a reducer has flattened it, and both are correct. The cost is that two pipelines sharing a bucket can key it differently with nothing to catch them, which is the sharp edge of sharing and is documented rather than prevented.

fieldtypedescription
bucketstringrequiredname of the bucket this pipeline reads and writes — one of the ones declared under state at the top of the config. A pipeline naming a bucket that isn't declared fails to build.
keystringoptionalthe field whose value identifies the thing being remembered, e.g. _meta.machine_id. A dotted path like anywhere else. Leave it out for one bucket-wide value — which is the right answer for something there is only ever one of, and the wrong one for anything per-device.

reference tables generated from the config schemas — just docs