Repository navigation
Conversation
A walsender reports what it will withhold from the stream as a warning, and filters it through client_min_messages like any backend. A role, database, or server set to send only errors kept that warning from the stream, so from PostgreSQL 18 a publication dropped under the stream was skipped silently and a keepalive confirmed past the change. The replication connection now sets client_min_messages = warning as a startup parameter, which outranks every one of those settings. Also pins the unlocalized severity in the stream's warning check with a localized warning.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Follow-up to #151. The stream stops fail-closed on a
WARNINGfrom the walsender — from PostgreSQL 18 that is how a publication skipped at load time is reported (55000), and without the stop a keepalive would moveDelivered, and the caller'sConfirmthe slot, past a change the slot will never resend. That stop only works if the warning reaches the connection. A walsender filters its messages throughclient_min_messageslike any backend, andConnectReplicationinherited whatever the role, the database, or the server set. A database set toerrorto quiet noisy clients silenced the warning, and on 18 the silent skip came back: the change never arrived,Deliveredmoved past its commit, andConfirmmoved the slot past it too. Before 18 the server sends anERRORfor the missing publication, which no setting filters, so 14 through 17 already failed closed.Before / after
What
pkg/dbconn/replication.go—ConnectReplicationsetsclient_min_messages = warningas a startup parameter alongsidereplication = database. A startup parameter outranks the role's, the database's, and the server's setting, so none of them can keep the walsender's warning from the connection.pkg/dbconn/replication_integration_test.go—TestConnectReplicationAsksForWarningsOverTheDatabaseSetting: with the database set toerror,SHOW client_min_messageson the replication connection readswarning.pkg/decode/stream_refusal_integration_test.go—TestStreamStopsOnTheWarningWhenTheDatabaseSendsOnlyErrors:ALTER DATABASE … SET client_min_messages = errorbefore the stream opens, then the dropped-publication scenario; the stream must still end with the server's SQLSTATE on every major. The dropped-publication steps and the per-major expectation move into two fixture helpers shared withTestStreamReturnsTheDecodersError.pkg/decode/stream_test.go—TestStreamStopsOnALocalizedWarning: a notice withSeverity: "WARNUNG"andSeverityUnlocalized: "WARNING"stops the stream, pinning the check to the unlocalized field.SAFETY.mddecode row, design decode row, and the ST-4 Enforced line record that the replication connection asks for warnings itself; the ST-4 test list names the two new tests.Decisions to veto
SETafter connect: a walsender accepts only the simple query protocol andConnectReplicationruns no session preparation, and the startup parameter is also what outranks the role and database settings. It overrides a value in the connection URL as well, since it is assigned after parsing.warning, notnoticeor lower: the walsender says what it will withhold atWARNING; everything below stays informational and the stream ignores it, as before.Verification
TestStreamStopsOnTheWarningWhenTheDatabaseSendsOnlyErrorstimes out at the stream deadline (17.1 s,the stream did not fail before the stream deadline) andTestConnectReplicationAsksForWarningsOverTheDatabaseSettingreadserror; with it both pass (5.5 s / 1.8 s). Reading the localizedSeverityinstead ofSeverityUnlocalizedfailsTestStreamStopsOnALocalizedWarning.go test -race -count=1 ./pkg/decode/ ./pkg/dbconn/green on PostgreSQL 16 (decode 152 s, dbconn 95 s) and withPG_VERSION=18on 18 (decode 138 s, dbconn 80 s).make lint0 issues;SKIP_INTEGRATION=1 go test ./pkg/decode/ ./pkg/dbconn/ ./internal/safety/ ./pkg/schemachange/green (docs guards included).🤖 Created by Kiran's coding agent (Amp, Claude Opus 4.6).