Implements a PostgreSQL logical replication module that streams WAL changes, buffers them per XID for transaction atomicity, and publishes CacheKey invalidation events to the existing framework broadcast channel. Key design choices: - Transaction atomicity: changes are buffered until COMMIT so the fanout always receives a consistent view. A 1000-row bulk-insert emits one table-level CacheKey, not 1000 row events. - Native protocol: uses a self-contained raw TCP + postgres-protocol implementation for the replication connection (tokio-postgres 0.7 does not expose copy_both_simple publicly). - Corrected pgoutput v1 parser: original maybe_sql_integration code incorrectly read XID from DML messages; DML messages carry no XID in proto v1 — only Begin does. - Clean integration: publishes CacheKey::Channel events to store.events so the existing fanout task picks them up with zero changes to the fanout loop. - New cx.subscribe(key) API on RenderContext for manually registering subscription keys (needed when queries go through PgPool, not cx.run). New files: src/pg_replication/mod.rs — PgReplicationListener, key helpers src/pg_replication/wal_parser.rs — pgoutput v1 binary protocol parser src/pg_replication/emitter.rs — WalEmitter (tx-buffering + CacheKey emit) src/pg_replication/proto.rs — raw TCP PG wire-protocol connection examples/pg_replication/main.rs — live message board example docker-compose.yml — PG 16 container with wal_level=logical Run the example: docker compose up -d cargo run --example pg_replication --features pg_replication https://claude.ai/code/session_01SLGgXeqKV2o7KTmCaQZZPg
40 lines
1.3 KiB
TOML
40 lines
1.3 KiB
TOML
[package]
|
|
name = "livevue-rs"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
# Run the todo example with: cargo run --example todo
|
|
# Run the pg_replication example with: cargo run --example pg_replication --features pg_replication
|
|
|
|
[features]
|
|
# Opt-in feature: PostgreSQL logical replication for reactive cache invalidation.
|
|
# Adds tokio-postgres and bytes as dependencies.
|
|
pg_replication = ["dep:tokio-postgres", "dep:postgres-protocol", "dep:bytes"]
|
|
|
|
[dependencies]
|
|
axum = { version = "0.7", features = ["macros"] }
|
|
tokio = { version = "1", features = ["full"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "postgres"] }
|
|
maud = { version = "0.26", features = ["axum"] }
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
dashmap = "6"
|
|
anyhow = "1"
|
|
tokio-stream = "0.1"
|
|
tracing = "0.1.44"
|
|
futures = "0.3.32"
|
|
|
|
# Optional: PostgreSQL logical replication
|
|
tokio-postgres = { version = "0.7", optional = true }
|
|
postgres-protocol = { version = "0.6", optional = true }
|
|
bytes = { version = "1", optional = true }
|
|
|
|
[dev-dependencies]
|
|
chrono = { version = "0.4", features = ["clock"] }
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
|
|
[[example]]
|
|
name = "pg_replication"
|
|
path = "examples/pg_replication/main.rs"
|
|
required-features = ["pg_replication"] |