@@ -73,6 +73,14 @@ typedef struct LogicalRepCtxStruct
7373
7474LogicalRepCtxStruct * LogicalRepCtx ;
7575
76+ typedef struct LogicalRepWorkerId
77+ {
78+ Oid subid ;
79+ Oid relid ;
80+ } LogicalRepWorkerId ;
81+
82+ static List * on_commit_stop_workers = NIL ;
83+
7684static void ApplyLauncherWakeup (void );
7785static void logicalrep_launcher_onexit (int code , Datum arg );
7886static void logicalrep_worker_onexit (int code , Datum arg );
@@ -249,6 +257,30 @@ logicalrep_worker_find(Oid subid, Oid relid, bool only_running)
249257 return res ;
250258}
251259
260+ /*
261+ * Similar to logicalrep_worker_find(), but returns list of all workers for
262+ * the subscription, instead just one.
263+ */
264+ List *
265+ logicalrep_workers_find (Oid subid , bool only_running )
266+ {
267+ int i ;
268+ List * res = NIL ;
269+
270+ Assert (LWLockHeldByMe (LogicalRepWorkerLock ));
271+
272+ /* Search for attached worker for a given subscription id. */
273+ for (i = 0 ; i < max_logical_replication_workers ; i ++ )
274+ {
275+ LogicalRepWorker * w = & LogicalRepCtx -> workers [i ];
276+
277+ if (w -> in_use && w -> subid == subid && (!only_running || w -> proc ))
278+ res = lappend (res , w );
279+ }
280+
281+ return res ;
282+ }
283+
252284/*
253285 * Start new apply background worker.
254286 */
@@ -513,6 +545,27 @@ logicalrep_worker_stop(Oid subid, Oid relid)
513545 LWLockRelease (LogicalRepWorkerLock );
514546}
515547
548+ /*
549+ * Request worker for specified sub/rel to be stopped on commit.
550+ */
551+ void
552+ logicalrep_worker_stop_at_commit (Oid subid , Oid relid )
553+ {
554+ LogicalRepWorkerId * wid ;
555+ MemoryContext oldctx ;
556+
557+ /* Make sure we store the info in context that survives until commit. */
558+ oldctx = MemoryContextSwitchTo (TopTransactionContext );
559+
560+ wid = palloc (sizeof (LogicalRepWorkerId ));
561+ wid -> subid = subid ;
562+ wid -> relid = relid ;
563+
564+ on_commit_stop_workers = lappend (on_commit_stop_workers , wid );
565+
566+ MemoryContextSwitchTo (oldctx );
567+ }
568+
516569/*
517570 * Wake up (using latch) any logical replication worker for specified sub/rel.
518571 */
@@ -753,15 +806,41 @@ ApplyLauncherShmemInit(void)
753806 }
754807}
755808
809+ /*
810+ * Check whether current transaction has manipulated logical replication
811+ * workers.
812+ */
813+ bool
814+ XactManipulatesLogicalReplicationWorkers (void )
815+ {
816+ return (on_commit_stop_workers != NIL );
817+ }
818+
756819/*
757820 * Wakeup the launcher on commit if requested.
758821 */
759822void
760823AtEOXact_ApplyLauncher (bool isCommit )
761824{
762- if (isCommit && on_commit_launcher_wakeup )
763- ApplyLauncherWakeup ();
825+ if (isCommit )
826+ {
827+ ListCell * lc ;
764828
829+ foreach (lc , on_commit_stop_workers )
830+ {
831+ LogicalRepWorkerId * wid = lfirst (lc );
832+ logicalrep_worker_stop (wid -> subid , wid -> relid );
833+ }
834+
835+ if (on_commit_launcher_wakeup )
836+ ApplyLauncherWakeup ();
837+ }
838+
839+ /*
840+ * No need to pfree on_commit_stop_workers. It was allocated in
841+ * transaction memory context, which is going to be cleaned soon.
842+ */
843+ on_commit_stop_workers = NIL ;
765844 on_commit_launcher_wakeup = false;
766845}
767846
0 commit comments