- Add `publish_key()` default method to `Query` trait (returns `None`)
- Add `mutation_exec!` macro for SQLite INSERT/UPDATE/DELETE ops; overrides
`publish_key()` so the mutation carries its own invalidation key
- Add `Store::exec()` which runs a mutation and auto-publishes its key —
action handlers no longer need a separate `store.publish()` call
- Add `PgQuery` trait + `pg_query_one!` / `pg_query_all!` macros
(feature-gated on `pg_replication`) mirroring the SQLite Query API
- Add `cx.run_pg(pool, query)` to `RenderContext` which executes a PgQuery
and auto-subscribes its cache key — no more manual `cx.subscribe()` calls
- Update todo example: replace plain mutation fns with `mutation_exec!` structs
and `store.exec()` calls; remove `action_then_publish` helper
- Update pg_replication example: add `ListMessages` via `pg_query_all!` and
replace manual subscribe + raw query with `cx.run_pg()`
https://claude.ai/code/session_01HXe8rAZPweU9j2piBo9MdG
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
Two bugs that caused signals to not work on the frontend:
1. data-on-signal-change → data-on-signal-patch
The data-on-signal-change attribute was removed in RC8.
The replacement is data-on-signal-patch.
2. data-bind-newTodo="" → data-bind="newTodo"
HTML normalises attribute names to lowercase at parse time, so
data-bind-newTodo becomes data-bind-newtodo in the DOM. DataStar
would then bind to signal $newtodo instead of $newTodo, breaking
the two-way binding. The value syntax data-bind="newTodo" preserves
the camelCase name correctly.
https://claude.ai/code/session_01JThiQbp3Bn9J1VhBpRuz4u