Skip to content

Report durable advances to the source without waiting - #267

Open
serprex wants to merge 1 commit into
mainfrom
split/durable-replies
Open

serprex wants to merge 1 commit into
mainfrom
split/durable-replies

Conversation

@serprex

@serprex serprex commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Durable apply and flush advances wait for periodic standby status replies. Report advances sooner, matching logic in postgres.

Extracted from original #228 and based directly on main. Contains no changes from #226 or other extracted PRs.

Validation: cargo fmt --all -- --check, cargo clippy --workspace --all-targets --locked -- -D warnings, and cargo test --locked --lib source::source_feed (8 passed). Rebuild crate for each isolated diff.

Measured impact (2026-10-22)

Compared a9b85994dc01d67d08c0a061180b097ca5c5723a against shared parent 151fd47cbd75ec7b9bc63ffe7040f049e702ecd0, with each PR built separately.

Workload Base (ms) PR (ms) Median change
First durable status reply 508.48 [506.51, 510.26] 63.51 [63.38, 63.74] -87.5%
Mean gap between replies within trial 508.00 [505.25, 509.28] 63.41 [63.27, 63.55] -87.5%
Workload Base (replies) PR (replies) Median change
Replies during 60 polling steps 2.00 [2.00, 2.00] 19.00 [19.00, 19.00] +850.0%

Workload: real SourceFeed against loopback PostgreSQL protocol fixture, 500 ms status interval, advancing write/flush/apply positions across 60 polls, each cancelled after 20 ms. Read complete status frames on server side. Uses real elapsed time; 50 ms receive wake floor and poll cadence affect measured latency. Measures feedback scheduling, without WAL throughput or source WAL recycling measurements.

AMD Ryzen 7 7840U; rustc 1.99.1; locked dependencies; optimized release builds; mimalloc 0.1.52. Seven trials per revision, alternating base/PR order, pinned to CPUs 2,4,6 (three physical cores). Values show median [min, max]; negative time changes mean less work or waiting. Local component measurements, without PostgreSQL or ClickHouse services.

Standby replies went out only every status interval (10 s by default)
or when a keepalive asked. Apply and flush, bounded as before by shadow
replay, the ClickHouse-acknowledged resume-safe position and the
persisted floor, could therefore sit a whole interval behind what the
daemon had made durable: the source kept that WAL longer, and on the
write-heavy repro (interval 1 s) it was most of a second of the drain's
acknowledgement tail.

Reply as soon as apply or flush advances past what the source was last
told, as PostgreSQL's walreceiver does after each flush, but at most ten
times per interval. The values sent are unchanged, so nothing is
acknowledged earlier than it is durable; only the delay shrinks.

A zero --status-interval is now refused: PostgreSQL reads a zero
wal_receiver_status_interval as no replies, and the source keeps WAL
until a reply releases it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@serprex
serprex force-pushed the split/durable-replies branch from 1fabf4e to 661a913 Compare October 23, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants