Skip to content

Documentation / @etherfold/core / readOnlyStream

Function: readOnlyStream() ​

readOnlyStream<ABI>(reader): ExistingStream<ABI>

Defined in: packages/core/src/stream/readOnly.ts:71

A STREAM YOU CAN ONLY READ: an ExistingStream whose saveNewEvents and clear are no-ops.

Why this has to exist at all ​

READ and WRITE share ONE seam. A generation handed the stream to fold is handed the thing that also appends, and promiseToSave calls saveNewEvents UNCONDITIONALLY -- so "a generation that merely reads" is not something a caller can express by declining to write, and it is not something a CONFIGURATION could express either, because the save is driven by the indexing loop rather than by the caller's intent. It is expressed by handing over a stream whose writes go nowhere.

That is what makes the ONE-WRITER RULE structural: only the generation that INDEXES a stream is given the keeper, every other generation folding it is given one of these, and a second writer is therefore unreachable rather than merely discouraged.

Why the writes are NO-OPS and not refusals ​

A throw would wedge the engine, and correctly so: it does not process a batch it could not write (StreamWriteOutcome), so a refusing keeper would freeze the fold rather than leave it read-only. Silence is the honest answer here -- there is nothing to write, because somebody else already wrote it.

clear is a no-op for a sharper reason than symmetry: the load path clears the cached stream on every shape it cannot use (a stream that does not match the source, a stream that will not re-parse, a stream that does not reach back far enough), and a follower takes those branches over a stream ANOTHER generation is still indexing into. A view that passed clear through would delete the live generation's history from underneath it.

One view, over KEEPERS ​

What this wraps is always a keeper of the stream, so that there is ONE definition of what read-only means on this seam rather than several that can drift apart: a follower is handed one over the keeper the writing generation owns (container.ts), and storedEmissionStream (@etherfold/server) is one over the emission table read back.

NOT a caller: replayStream, a captured fixture. It was built out of this until the keeper seam narrowed to what the NODE said, which a fixture's deliberately DECODED events are not; it now has its own reader type with no write half at all (fixture.ts, ADR-0059). That is a fixture leaving this seam rather than a second read-only implementation of it -- the rule below is untouched.

The rule this serves, and the options weighed against it, are ADR-0044.

Type Parameters ​

ABI ​

ABI extends Abi

Parameters ​

reader ​

StreamReader<ABI>

Returns ​

ExistingStream<ABI>