From 43a87d3267e89a0bc231373dc69aaa73398b9aca Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Tue, 4 Nov 2025 14:28:54 +0100 Subject: [PATCH] Add RecoveryStopsHook for extensions to handle custom WAL records --- src/backend/access/transam/xlogrecovery.c | 24 ++++++++++++++++++++++- src/include/access/xlogrecovery.h | 10 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index 12bf6eb22c8..f38c48208a7 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -2567,8 +2567,28 @@ recoveryStopsBefore(XLogReaderState *record) return true; } + /* Check RecoveryStopsHook for custom records */ + if (RmgrIdIsCustom(XLogRecGetRmid(record)) && (RecoveryStopsBeforeHook != NULL)) + { + stopsHere = RecoveryStopsBeforeHook(record, &recordXid, &recordXtime); + + if (stopsHere) + { + recoveryStopAfter = false; + recoveryStopXid = recordXid; + recoveryStopLSN = InvalidXLogRecPtr; + recoveryStopTime = recordXtime; + recoveryStopName[0] = '\0'; + + ereport(LOG, + (errmsg("recovery stopping by hook before transaction %u, time %s", + recoveryStopXid, + timestamptz_to_str(recoveryStopTime)))); + return true; + } + } /* Otherwise we only consider stopping before COMMIT or ABORT records. */ - if (XLogRecGetRmid(record) != RM_XACT_ID) + else if (XLogRecGetRmid(record) != RM_XACT_ID) return false; xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK; @@ -4506,6 +4526,8 @@ GetXLogReplayRecPtr(TimeLineID *replayTLI) GetReplayXlogPtrHookType GetReplayXlogPtrHook = NULL; +RecoveryStopsBeforeHookType RecoveryStopsBeforeHook = NULL; + /* * Get effective latest redo apply position. * diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h index cec67fb9c89..8ab6e99f86d 100644 --- a/src/include/access/xlogrecovery.h +++ b/src/include/access/xlogrecovery.h @@ -50,6 +50,10 @@ typedef enum RecoveryPauseState typedef XLogRecPtr (*GetReplayXlogPtrHookType) (void); +typedef bool (*RecoveryStopsBeforeHookType) (XLogReaderState *record, + TransactionId *recordXid, + TimestampTz *recordXtime); + /* User-settable GUC parameters */ extern PGDLLIMPORT bool recoveryTargetInclusive; extern PGDLLIMPORT int recoveryTargetAction; @@ -81,6 +85,12 @@ extern PGDLLIMPORT bool StandbyMode; /* Hook for extensions to tune replay xlog pointer */ extern PGDLLIMPORT GetReplayXlogPtrHookType GetReplayXlogPtrHook; +/* + * Hook for extensions to be able to decides to stop applying the WAL files + * based on custom WAL records. + */ +extern PGDLLIMPORT RecoveryStopsBeforeHookType RecoveryStopsBeforeHook; + extern Size XLogRecoveryShmemSize(void); extern void XLogRecoveryShmemInit(void);