From 3b1f38fe237418ef43d3435321652590da00cd9d Mon Sep 17 00:00:00 2001 From: reshke Date: Mon, 20 Jul 2026 18:25:39 +0300 Subject: [PATCH v6 2/2] Add `primary_last_archived` column to pg_stat_wal_receiver view. Comes in-handy for monitoring shared archive feature. TAP tests for shared archive feature were extended to check for this column value. Bumps catversion. --- src/backend/catalog/system_views.sql | 1 + src/backend/replication/walreceiver.c | 24 +++++++++++++++-------- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.dat | 6 +++--- src/test/recovery/t/055_archive_shared.pl | 11 +++++++++++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 090281a03dd..5bd037aa59b 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1025,6 +1025,7 @@ CREATE VIEW pg_stat_wal_receiver AS s.last_msg_receipt_time, s.latest_end_lsn, s.latest_end_time, + s.primary_last_archived, s.slot_name, s.sender_host, s.sender_port, diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index f226ea422e1..b115703f0da 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -1712,6 +1712,7 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) int sender_port = 0; char slotname[NAMEDATALEN]; char conninfo[MAXCONNINFO]; + char primary_last_archived[MAX_XFN_CHARS + 1]; /* Take a lock to ensure value consistency */ SpinLockAcquire(&WalRcv->mutex); @@ -1732,6 +1733,9 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) strlcpy(conninfo, WalRcv->conninfo, sizeof(conninfo)); SpinLockRelease(&WalRcv->mutex); + SpinLockAcquire(&PgArch->lock); + strlcpy(primary_last_archived, PgArch->primary_last_archived, sizeof(primary_last_archived)); + SpinLockRelease(&PgArch->lock); /* * No WAL receiver (or not ready yet), just return a tuple with NULL * values @@ -1800,22 +1804,26 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) nulls[10] = true; else values[10] = TimestampTzGetDatum(latest_end_time); - if (*slotname == '\0') + if (*primary_last_archived == '\0') nulls[11] = true; else - values[11] = CStringGetTextDatum(slotname); - if (*sender_host == '\0') + values[11] = CStringGetTextDatum(primary_last_archived); + if (*slotname == '\0') nulls[12] = true; else - values[12] = CStringGetTextDatum(sender_host); - if (sender_port == 0) + values[12] = CStringGetTextDatum(slotname); + if (*sender_host == '\0') nulls[13] = true; else - values[13] = Int32GetDatum(sender_port); - if (*conninfo == '\0') + values[13] = CStringGetTextDatum(sender_host); + if (sender_port == 0) nulls[14] = true; else - values[14] = CStringGetTextDatum(conninfo); + values[14] = Int32GetDatum(sender_port); + if (*conninfo == '\0') + nulls[15] = true; + else + values[15] = CStringGetTextDatum(conninfo); } /* Returns the record as Datum */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f046605ccf9..d0399cc1cbe 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202607173 +#define CATALOG_VERSION_NO 202607201 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 1c55a4dea34..bf7ed03c0ae 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5718,9 +5718,9 @@ { oid => '3317', descr => 'statistics: information about WAL receiver', proname => 'pg_stat_get_wal_receiver', proisstrict => 'f', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => '', - proallargtypes => '{int4,text,pg_lsn,int4,pg_lsn,pg_lsn,int4,timestamptz,timestamptz,pg_lsn,timestamptz,text,text,int4,text}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{pid,status,receive_start_lsn,receive_start_tli,written_lsn,flushed_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,slot_name,sender_host,sender_port,conninfo}', + proallargtypes => '{int4,text,pg_lsn,int4,pg_lsn,pg_lsn,int4,timestamptz,timestamptz,pg_lsn,timestamptz,text,text,text,int4,text}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{pid,status,receive_start_lsn,receive_start_tli,written_lsn,flushed_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,primary_last_archived,slot_name,sender_host,sender_port,conninfo}', prosrc => 'pg_stat_get_wal_receiver' }, { oid => '6514', descr => 'statistics: information about WAL recovery', proname => 'pg_stat_get_recovery', proisstrict => 'f', provolatile => 's', diff --git a/src/test/recovery/t/055_archive_shared.pl b/src/test/recovery/t/055_archive_shared.pl index 2a94f98010f..f3f1e13c6de 100644 --- a/src/test/recovery/t/055_archive_shared.pl +++ b/src/test/recovery/t/055_archive_shared.pl @@ -85,6 +85,9 @@ cmp_ok($status_count, '>', 0, "standby creates archive status files for received # Generate more WAL and wait for archiving on primary my $initial_archived = $primary->safe_psql('postgres', 'SELECT archived_count FROM pg_stat_archiver'); +my $primary_last_archived = $primary->safe_psql('postgres', + q{SELECT pg_walfile_name(pg_current_wal_lsn())}); + $primary->safe_psql('postgres', "SELECT txid_current();SELECT pg_switch_wal();"); # Wait for primary to archive the new segments @@ -109,9 +112,17 @@ for (my $i = 0; $i < $PostgreSQL::Test::Utils::timeout_default; $i++) last if $done_count > 0; sleep(1); } + ok($done_count > 0, "standby marked segments as .done after primary's archival report"); note("Standby has $done_count .done files"); +# The primary_last_archived done status for WAL file itself must also be present. +ok(-f "$standby_archive_status/$primary_last_archived.done", + "WAL segment $primary_last_archived done file exists in standby pg_wal/archive_status"); + +is($primary_last_archived, $standby->safe_psql('postgres', + q{SELECT primary_last_archived from pg_stat_wal_receiver; }), "standby wal receiver stat view updated with primary last archived wal"); + ############################################################################### # Test 2: Cascading replication ############################################################################### -- 2.43.0