Postgres engine: streams — StreamHandle (auto-commit publishes + best-effort pg_notify wake, ASC reads with the extent guard, monotone offsets, pool-connection trim) and the durable subscribe receiver (async bridge, wake-driven re-drains, reconnect gap-heal, shutdown-only terminal close, stateless idle wake runtime for the sync save) (task pg-engine-streams)

This commit is contained in:
glm-5.3-flash committed 2026-10-09 08:05:34 +00:00
1 parent 8f5c2add5e
commit cb067bb4be
7 files changed
+2254 -45

No files matched your search

+5 -24
View File
@@ -79,6 +79,7 @@ use crate::resolution::{
};
use crate::schema::{QualifiedTable, tables};
use crate::seam::{pg_error, pool_error};
use crate::stream::stream_events_from_rows;
/// The notification payload boundary (the contract's pinned limit —
/// client-side checked, typed before any round trip; the predicate
@@ -637,27 +638,7 @@ fn job_from_row(row: &tokio_postgres::Row) -> Result<Job> {
))
}
/// Decode a read page into the contract's [`StreamEvent`] values (the
/// core constructor's `from_row`). Malformed rows map to `Error::Codec`.
fn stream_events_from_rows(
rows: &[tokio_postgres::Row],
stream: String,
) -> Result<Vec<StreamEvent>> {
let mut out = Vec::with_capacity(rows.len());
for row in rows {
let key: Option<String> = row
.try_get(1)
.map_err(|e| Error::Codec(format!("stream row key must be text: {e}")))?;
let payload: Option<Vec<u8>> = row
.try_get(2)
.map_err(|e| Error::Codec(format!("stream row payload must be bytea: {e}")))?;
out.push(StreamEvent::from_row(
row.get(0),
stream.clone(),
key,
payload.unwrap_or_default(),
row.get(3),
));
}
Ok(out)
}
// The stream-page decode (`stream_events_from_rows`) lives in
// `stream.rs` — the one decode owner the tx reads and the auto-commit
// reads share (the `stream` field mapping and the `Codec` posture
// guard live once; ADR-012 §2's one-owner rule).