Rindle docs and package mapSkip to main content

Module session

Module session 

Expand description

The shared interactive-mutation-session engine (REPLICATOR-INTERACTIVE-TXN-DESIGN.md §4).

One server-agnostic home for the session state machine both write masters serve: the single-session invariant, the parked FIFO and its drain ordering, the daemon-owned deadline with RAII rollback, session-id minting/matching, absorbed replay and 410 Gone, and the wire (de)serializers. rindled (rindle-server) and the replicator write-master (rindle-replicator) each implement SessionBackend over their own transaction representation and SessionResponder over their own deferred responder; the subtle scheduling logic is written and tested once, and the api-server receives byte-identical replies from either master (the §7 “indistinguishable masters” invariant — which is why the serializers live here too, not per-server).

This module is transport-free by design: no HTTP types, only serde_json bodies plus a status code. It is the extraction of rindle-server/src/net.rs’s session handlers (DAEMON-INTERACTIVE-TXN-DESIGN.md §4.2), ported branch-for-branch; rindled’s wire tests (rindle-replicator/tests/session_wire.rs and rindle-server/tests/standalone_wire.rs) gate the two hosts.

The ONE-SHOT write types live here too (SqlTxn/SqlTxnOutput + parse_sql_txn/ sql_txn_output_json, REPLICATOR-INTERACTIVE-TXN-DESIGN.md §11.3): a one-shot is a session compressed into a single call, and both masters answering the same /execute-sql-txn shapes through the same types is how the one-shot and session paths stay unable to drift.

Structs§

CommitTail
The commit-time bookkeeping the backend writes co-transactionally: a client session’s lmid upsert, a foreign session’s producer watermark. Folded into ONE backend call — not engine-driven steps — because the replicator’s divergence guard must measure the user statements’ captures BEFORE the lmid row lands in the capture buffer; only the backend can order that (REPLICATOR-INTERACTIVE-TXN-DESIGN.md §4.2).
LmidAdvance
The client watermark after a write/rejection: lmid is the stored high-water mark.
ProducerWrite
A foreign (non-client) writer’s durable identity: a stable, low-cardinality id plus that producer’s own gapless sequence (design 306 §4). The same (producer, sequence) model Kafka uses — dedup AND ordering, bounded by producer count rather than by write volume.
ReadRows
A session read’s {cols, rows} result.
SessionCommit
What a backend’s commit reports: applied: false is the zero-capture no-op (a foreign session whose statements changed nothing durable — the backend rolled back instead of committing, mirroring the one-shot path).
SessionEngine
The shared session engine: owns session metadata + the parked queue + id minting + the deadline; drives a SessionBackend for everything that touches the transaction. Generic over the server’s parked one-shot command C and its deferred responder R.
SessionReply
A rendered session reply: status + JSON body, shaped ON the engine thread (replies have several shapes — begin’s session-or-absorbed, query’s {cols, rows} — so the engine shapes them and the server’s completion path only writes the socket).
SqlStatement
One {sql, params} statement off the wire — the shape shared by a session begin’s accumulated prefix, exec statements, query reads, and a one-shot SqlTxn’s statements.
SqlTxn
One approved SQL write transaction — the one-shot (/execute-sql-txn) flavor, i.e. a mutation session compressed into a single call. A client_id + mid carries the optimistic-client discipline (≤ lmid absorbed, lmid+1 applies + the co-transactional lmid upsert, a gap rejects); a foreign write may instead carry a producer watermark, which runs the SAME rule against its own namespace. The two are mutually exclusive on the wire. How a txn runs stays per-server (group-commit fold, capture, broadcast) — only the accepted shape is shared.
SqlTxnOutput
The outcome of a one-shot SqlTxn (or a mutation rejection) — and the exact shape a session commit answers, from either master. applied: false is an absorbed replay (mid ≤ lmid, seq ≤ last_seq) or a zero-effect no-op: nothing committed, no txn identity.

Enums§

ParkedNext
What the drain pump hands back: a parked one-shot for the server to run, or “stop” (queue empty, or a parked begin just opened the next session).
SessionError
The engine’s error type — only the variants the state machine distinguishes and the wire renders. Each backend maps its native error in at the boundary (SessionBackend methods return these), keeping the engine monomorphic; MutationGap’s Display is byte-identical to rindle-server’s ServerError::MutationGap so the extraction changes no response body.
SessionOp
One /mutate-session/* request, parsed on the intake thread. Begin optionally carries the accumulated write prefix and the first read, so a lazy-upgrading mutator’s first interactive read costs ONE round trip over the batch path (DAEMON-INTERACTIVE-TXN-DESIGN.md §4.1).
TxnWireId
The backend’s opaque transaction identity on the wire. The two masters already differ here for one-shots — rindled reports the cluster commit (cv + txId), the replicator its change-log cursor (cursor) — and the JS client reads neither; carrying the split as an explicit variant keeps the shared serializer honest instead of papering over it (REPLICATOR-INTERACTIVE-TXN-DESIGN.md §7).

Constants§

DEFAULT_SESSION_DEADLINE
The default daemon-owned session lease (DAEMON-INTERACTIVE-TXN-DESIGN.md §4.3): a wedged or dead api-server costs the write head at most this long. Shared so both masters enforce the same bound by default; each server’s config can override it.

Traits§

SessionBackend
A single serialized write backend that can host ONE interactive mutation session at a time, with the open transaction held as backend state (rindled’s ClusterWriteTxn is an owned handle; the replicator’s txn is inseparable from WriteMaster’s connection + capture ctx + broadcast — a stateful trait fits both).
SessionResponder
The server’s deferred-respond handle: consumes itself answering the client exactly once, off the engine thread (each server wraps its own responder + completion channel).

Functions§

absorbed_reply
A begin absorbed by mid dedup: the /execute-sql-txn replay shape plus absorbed: true, so the caller both skips the mutator and treats the reply as the authoritative outcome.
check_read_js_safe
The strict-i64 guard for the LEGACY bare-cell read wire (design 226 §8): an unguarded session’s reply goes through session_read_json, whose bare cells ride owned_to_json — an Int outside ±(2^53−1) would flatten to a rounded f64. The contract is a typed error, never a rounded number, so the read fails like any other statement error (the tagged /v1/sql wire carries such cells exactly; guarded sessions therefore skip this). Mirrors the napi/wasm mandatory strict_i64 walk — the daemon HTTP JSON wire is a JS boundary too.
error_reply
Render an error as the {error} body + shared status (http_error parity).
execute_one_shot
Execute one mutation transaction through the shared admission and commit-tail discipline. Hosts provide only their storage operations through SessionBackend; absorbed replay, gap rejection, rollback-on-statement-error, LMID advancement, and the foreign-write producer watermark stay identical to interactive sessions by construction.
parse_session_op
Parse one /mutate-session/<op> body (DAEMON-INTERACTIVE-TXN-DESIGN.md §4.1). begin may carry the accumulated statement prefix and the first read (query: {sql, params}); query is flat {sessionId, sql, params} like /execute-sql-read.
parse_sql_txn
Parse a /execute-sql-txn body — { statements, clientID?, mid?, producer? } — the one-shot flavor of the session wire, shared so both masters accept identical bytes.
parse_statement_obj
Parse one {sql, params?} object.
parse_statements
Parse a body’s statements array ([{sql, params?}, …]).
public_cancel_reply
Idempotent cancellation acknowledgement. The replicator router fills cancelled from its out-of-band interrupt registry; a backend without an active operation returns false without changing transaction state.
public_commit_outcome_reply
Render a durable public-transaction commit lookup. None means the lookup has no terminal record, so a caller that can still reach a live connection-affine session should continue routing the commit there. A found outcome or lookup failure is already terminal and can be answered without occupying a writer connection.
public_operation_sequence
Parse the frozen public transaction operation identity without consulting session state. Route intake uses this too, so rollback/cancel and missing-handle terminal paths cannot bypass the canonical positive-decimal contract merely because they do not reach a live session.
public_session_gone
reject_one_shot
Process a client mutation as an explicit no-op: apply no user statements, but advance its LMID in the same captured commit. Replays absorb and gaps reject through the same admission function as execute_one_shot and interactive session begin.
session_gone
The 410 Gone every op against a non-open session id answers: committed, rolled back, expired, or the daemon restarted — the caller cannot distinguish and does not need to (its redelivery re-enters at begin, where mid dedup absorbs any committed outcome).
session_op_id
The session id an op resolves against, or None for the two begin flavors (which mint one). Shared because every pooled/planed dispatcher routes ops by this id — the replicator’s connection-affine shards and the standalone daemon’s reader-backed read-only plane must extract it identically or an op could reach a session engine that never minted its id.
session_read_json
A session read serialized as the /execute-sql-read shape — cols in order, each row a bare cell array — so the JS client zips them identically on both paths.
session_read_tagged_json
A session read for a public mutation-facade session: identical {cols, rows} shape, but each cell uses the tagged value wire (encode_wire_value) so an integer outside ±(2^53−1) survives exactly instead of being flattened to an f64 by owned_to_json. A NaN REAL cannot be stored by SQLite and so cannot reach a read; the defensive fallback maps it to null.
sql_txn_output_json
The /execute-sql-txn output shape — the one-shot AND session-commit reply, from either master: applied, the backend’s opaque txn identity (rindled: cv + txId; replicator: cursor; OMITTED when nothing committed), and the client watermark (lmidAdvances + flat lmid).