Contents
Plain-language companion: v0.32.0.md
v0.32.0 — Citus: Stable Naming & Per-Source Frontier Foundation
Status: Planned. Derived from plans/ecosystem/PLAN_CITUS.md §6 Phase 1 and Phase 2.
Release Theme v0.32.0 is the first of two releases delivering world-class Citus support. It ships two additive, non-breaking layers: (1) a
src/citus.rsmodule with Citus detection and placement helpers; and (2) a stable-hash naming scheme that replaces OID-keyed internal objects (changes_{oid},pg_trickle_cdc_fn_{oid}, slot names, frontier keys) with names derived fromstable_hash(database_oid || '/' || schema || '.' || table). Both layers produce immediate quality benefits for all users — stable names survivepg_dump/restore and major-version upgrades — and they are mandatory prerequisites for v0.35.0’s per-worker slot CDC. There is zero behaviour change on a single-node deployment.
Correctness
| ID | Title | Effort | Priority |
|---|---|---|---|
| CITUS-1 | src/citus.rs: detection helpers and placement query |
M | P0 |
| CITUS-2 | SourceIdentifier struct carrying (oid, stable_name) |
S | P0 |
| CITUS-3 | Catalog migration: add source_stable_name, source_placement, st_placement columns |
S | P0 |
| CITUS-4 | Rename all OID-keyed objects to stable_name form |
M | P0 |
| CITUS-5 | Frontier rekey: Frontier.sources from OID string to stable_name |
S | P1 |
| CITUS-6 | Audit and remove cross-source global LSN comparisons | M | P1 |
| CITUS-7 | Add frontier_per_node JSONB column for distributed sources |
S | P1 |
| CITUS-8 | SQL migration: rename existing changes_{oid} tables and trigger functions in a single transaction |
M | P0 |
CITUS-1 — New module src/citus.rs. Detection helpers:
- is_citus_loaded() — SELECT 1 FROM pg_extension WHERE extname='citus'
- placement(oid) → Local | Reference | Distributed { dist_column } via
pg_dist_partition
- worker_nodes() → Vec<NodeAddr> from pg_dist_node
- shard_placements(table_oid) — which workers host shards
None of these panic if Citus is absent; all return sensible defaults
(Local, empty vecs). Citus-specific code paths are always guarded by
is_citus_loaded().
CITUS-2 — SourceIdentifier { oid: pg_sys::Oid, stable_name: String }.
stable_name = lower_hex(FNV-1a-64(database_oid || "/" || schema || "." || table))[..16].
Deterministic, short, URL-safe, identical on every Citus node. Serialised
in pgt_change_tracking.source_stable_name and used for all object names.
CITUS-3 — Schema changes (nullable, backward-compatible):
sql
ALTER TABLE pgtrickle.pgt_change_tracking
ADD COLUMN source_stable_name TEXT,
ADD COLUMN source_placement TEXT NOT NULL DEFAULT 'local';
ALTER TABLE pgtrickle.pgt_dependencies
ADD COLUMN source_stable_name TEXT,
ADD COLUMN source_placement TEXT NOT NULL DEFAULT 'local';
ALTER TABLE pgtrickle.pgt_stream_tables
ADD COLUMN st_placement TEXT NOT NULL DEFAULT 'local';
Old rows receive a synthetic stable name (hash of existing OID-based
name) and continue to function unchanged.
CITUS-4 — Replace changes_{oid}, pg_trickle_cdc_ins_{oid},
pg_trickle_cdc_fn_{oid}, idx_changes_{oid}_*, WAL slot names
(pgtrickle_{oid}), and the __PGS_PREV_LSN_{oid}__ placeholder tokens
in src/dvm/diff.rs with {stable_name} forms. Affected files:
src/cdc.rs, src/wal_decoder.rs, src/dvm/diff.rs,
src/refresh/codegen.rs, src/dvm/operators/*.
CITUS-5 / CITUS-6 — Frontier.sources is already a HashMap; rekey
from OID string to stable_name. Audit src/refresh/codegen.rs and
src/scheduler.rs for reads of pg_current_wal_lsn() used in cross-source
comparisons; replace with per-source watermark logic from
src/wal_decoder.rs.
CITUS-7 — Add frontier_per_node JSONB to pgt_change_tracking for
distributed sources. When the source is Local this column is NULL; for
Distributed sources it records { "worker_id": lsn, ... } tuples.
CITUS-8 — sql/pg_trickle--<prev>--<next>.sql performs column adds
then backfills source_stable_name from pg_class + pg_namespace,
renames existing buffer tables and trigger functions to the stable-hash
form, updates the WAL slot name in pg_replication_slots (via
pg_rename_logical_replication_slot where available), and updates
pgt_change_tracking. Provides a downgrade path in the same file.
Stability
| ID | Title | Effort | Priority |
|---|---|---|---|
| STAB-1 | Keep OID-based lookup as fallback for rows without source_stable_name |
S | P0 |
| STAB-2 | Detect and surface a clear error if stable hash collides (astronomically unlikely; check at create time) | S | P1 |
Test Coverage
| ID | Title | Effort | Priority |
|---|---|---|---|
| TEST-1 | Unit tests for stable_hash() — known vectors, cross-platform determinism |
S | P0 |
| TEST-2 | Unit tests for SourceIdentifier round-trip serialisation |
S | P0 |
| TEST-3 | Integration: pg_dump / pg_restore cycle preserves stream table with stable-named objects |
M | P0 |
| TEST-4 | Integration: major-version upgrade simulation — OID changes, stable name unchanged | M | P1 |
| TEST-5 | Integration: frontier rekey — multi-source ST with different write rates converges correctly | M | P0 |
| TEST-6 | Integration: existing installation upgrade (v0.31.0 → v0.32.0) renames objects correctly | M | P0 |
Documentation
| ID | Title | Effort | Priority |
|---|---|---|---|
| DOCS-1 | Changelog entry explaining stable naming motivation | S | P0 |
| DOCS-2 | Upgrade guide: what changes, what to expect, rollback instructions | S | P0 |
Exit Criteria
- [ ] CITUS-1:
is_citus_loaded(),placement(),worker_nodes()compile and return sensible defaults when Citus is absent - [ ] CITUS-2:
stable_hash("public.orders")produces identical output on two fresh PG instances with different OIDs - [ ] CITUS-4: no
{oid}tokens remain in object names created bysetup_cdc_for_source() - [ ] CITUS-8: migration script renames all existing objects;
just test-upgrade-allpasses - [ ] TEST-3:
pg_dump/pg_restoreround-trip test passes - [ ] TEST-6: v0.31.0 → v0.32.0 upgrade integration test passes
- [ ] Zero performance regression on the single-node benchmark suite (Citus detection check adds ≤ 1 µs per
create_stream_table()call when Citus is absent) - [ ]
just check-version-syncpasses - [ ]
just lintpasses (zero warnings)