Trait OneShotBackend
pub trait OneShotBackend {
// Required methods
fn begin_public_operation(&mut self) -> Result<(), WritePlaneError>;
fn public_batch_statement(
&mut self,
statement: &SqlStatementRequest,
remaining_result_bytes: usize,
) -> Result<StatementResult, WritePlaneError>;
fn rollback_public_operation(&mut self);
fn commit_public_operation(
&mut self,
outcome_key: &str,
request_identity: &str,
) -> Result<PublicOperationCommit, WritePlaneError>;
fn stored_public_outcome(
&mut self,
outcome_key: &str,
) -> Result<Option<StoredPublicOutcome>, WritePlaneError>;
fn public_operation_floor_ms(&mut self) -> Result<i64, WritePlaneError>;
fn resolve_public_run_id_cursor(
&mut self,
run_id: &str,
) -> Result<Option<String>, WritePlaneError>;
fn apply_public_ddl(
&mut self,
statement: &SqlStatementRequest,
outcome_key: &str,
request_identity: &str,
result_byte_limit: usize,
) -> Result<PublicOperationCommit, WritePlaneError>;
fn with_migration_barrier(
&mut self,
f: &mut dyn FnMut(&mut dyn MigrationSection) -> Result<PublicMigrateAck, WritePlaneError>,
) -> Result<PublicMigrateAck, WritePlaneError>;
}Expand description
The backend contract of the one-shot public SQL surface. The master implements it over its
session-transaction primitives; a standalone daemon implements it over its own store (303
S5). Every method returns pre-classified WritePlaneError — classification happens once,
host-side, and there is no conversion back out (decision C3).
The result-buffer invariant (extraction plan §2): the backend accumulates each
successful statement’s result from begin_public_operation on; an OCC retry inside
commit_public_operation re-runs the recorded statements and replaces the buffer
wholesale; commit returns that final buffer and stores exactly it in the outcome row.
rollback_public_operation clears the buffer; begin starts it empty. The per-statement
results returned to the coordinator feed byte accounting and error surfacing only — they
are never the response payload.
Required Methods§
fn begin_public_operation(&mut self) -> Result<(), WritePlaneError>
fn begin_public_operation(&mut self) -> Result<(), WritePlaneError>
Open the one-shot write transaction: serializable isolation, no raw-exec guard (every
statement installs the public authorizer itself). NOT the interactive begin_public —
that path’s error currency is lossy for a failed BEGIN, and a one-shot BEGIN failure
must keep its SQLITE_ERROR/sqlite_code bytes. On Err there is nothing to roll
back: the coordinator does NOT call rollback_public_operation after a failed begin.
fn public_batch_statement(
&mut self,
statement: &SqlStatementRequest,
remaining_result_bytes: usize,
) -> Result<StatementResult, WritePlaneError>
fn public_batch_statement( &mut self, statement: &SqlStatementRequest, remaining_result_bytes: usize, ) -> Result<StatementResult, WritePlaneError>
Run one statement inside the open one-shot transaction. Two flags distinguish this from
the interactive public statement, invisible at the call site and load-bearing: the
statement takes no per-statement savepoint (the whole transaction rolls back on any
error), and it records the SQL replay so a busy-snapshot commit retry can re-run
silently while no result has been observed. remaining_result_bytes bounds this
statement’s encoded result within the operation-wide cap.
fn rollback_public_operation(&mut self)
fn rollback_public_operation(&mut self)
Roll back the open one-shot transaction and clear the result buffer. Infallible and
idempotent — a no-op when nothing is open (best-effort ROLLBACK; a failure
poisons the connection for the next write and surfaces there). The coordinator calls
this exactly once on any statement or accounting error.
fn commit_public_operation(
&mut self,
outcome_key: &str,
request_identity: &str,
) -> Result<PublicOperationCommit, WritePlaneError>
fn commit_public_operation( &mut self, outcome_key: &str, request_identity: &str, ) -> Result<PublicOperationCommit, WritePlaneError>
Commit the open one-shot transaction, writing the outcome row — keyed outcome_key,
carrying request_identity and the buffered result set — co-transactionally with
the effects. Returns commit’s buffered results (the invariant above). On Err the
backend has rolled back; the coordinator then re-reads the stored outcome, because a
concurrent same-key winner’s co-transactional row is authoritative.
fn stored_public_outcome(
&mut self,
outcome_key: &str,
) -> Result<Option<StoredPublicOutcome>, WritePlaneError>
fn stored_public_outcome( &mut self, outcome_key: &str, ) -> Result<Option<StoredPublicOutcome>, WritePlaneError>
Read one stored outcome row — a record read only, no decisions (those are
stored_public_operation’s).
fn public_operation_floor_ms(&mut self) -> Result<i64, WritePlaneError>
fn public_operation_floor_ms(&mut self) -> Result<i64, WritePlaneError>
The operation-namespace retention floor, computed against the host’s own clock (the coordinator reads no clock). A replayed key minted at or below this floor fails closed.
fn resolve_public_run_id_cursor(
&mut self,
run_id: &str,
) -> Result<Option<String>, WritePlaneError>
fn resolve_public_run_id_cursor( &mut self, run_id: &str, ) -> Result<Option<String>, WritePlaneError>
The ONLY host leg of outcome-cursor resolution (decision C4): resolve a legacy
run_id-only outcome row to its commit cursor (the master’s journal scan). Stored-cursor
short-circuit and the GC-race re-read live in the coordinator’s spine, so a store whose
outcome rows always carry their cursor may simply return Ok(None) — a stored cursor
returns before this is ever called.
fn apply_public_ddl(
&mut self,
statement: &SqlStatementRequest,
outcome_key: &str,
request_identity: &str,
result_byte_limit: usize,
) -> Result<PublicOperationCommit, WritePlaneError>
fn apply_public_ddl( &mut self, statement: &SqlStatementRequest, outcome_key: &str, request_identity: &str, result_byte_limit: usize, ) -> Result<PublicOperationCommit, WritePlaneError>
Apply one fresh public DDL statement as its own atomic autocommit unit (decision C5).
The host owns the critical section — the master takes its maintenance lock and
refuses while interactive writers hold the pool open (Conflict) — and runs the
budget-wrapped DDL inside it. Contract: every validation runs INSIDE the
transaction, before the outcome row is inserted co-transactionally and the unit
commits — the zero-capture refusal (MIGRATION_DDL_ONLY), the destructive-DDL
(227) guards, schema-registry validation, the broken-foreign-keys refusal, and the
result_byte_limit cap on the encoded result. A store whose DDL API cannot run a
final in-transaction validation cannot implement this method yet (303 S4’s written
obligation).
The coordinator’s replay check runs OUTSIDE this critical section, so a concurrent
same-key DDL may win between the miss and this apply: the winner’s unique
co-transactional outcome insert makes this attempt fail, and the coordinator re-reads
the stored outcome on every Err. On Err the backend has rolled back — there is no
open unit for the coordinator to clean up.
fn with_migration_barrier(
&mut self,
f: &mut dyn FnMut(&mut dyn MigrationSection) -> Result<PublicMigrateAck, WritePlaneError>,
) -> Result<PublicMigrateAck, WritePlaneError>
fn with_migration_barrier( &mut self, f: &mut dyn FnMut(&mut dyn MigrationSection) -> Result<PublicMigrateAck, WritePlaneError>, ) -> Result<PublicMigrateAck, WritePlaneError>
Run the public migration critical section (extraction plan C6): the host owns WHERE
the section is — it takes its migration exclusion and refuses Conflict while the
writer pool cannot quiesce, BEFORE invoking f — and the coordinator closure owns
everything inside it, over the MigrationSection view. Because the quiesce gate
precedes the closure, this surface refuses-before-replaying by construction (the DDL
one-shot’s opposite replays-before-refusing order lives in C5’s optimistic flow).
The exclusion domain is ALL migrations, deploy included: on the master the maintenance lock already serializes both modes over the one shared tag namespace, and any host that runs a separately-implemented deploy migration path MUST route it through this same barrier, or a deploy migration could interleave with a public section (303 S4’s written obligation). Not reentrant — one section at a time.