Fix race condition with logical slot advance and copy (#3098)

The `SlotsAdvanceThread` is asynchronously calling
pg_replication_slot_advance() and providing feedback about logical
replication slots that must be reinitialized by copying from the
primary. That is, the parent thread will learn about slots to be copied
only when scheduling the next pg_replication_slot_advance() call.
As a result it was possible situation when logical slot was copied with
PostgreSQL restart more than once.

To improve it we implement following measures:
1. do not schedule slot sync if it is in the list to be copied
2. remove to be copued slots from the `self._scheduled` structure
3. clean state of `SlotsAdvanceThread` when slot files are copied.
This commit is contained in:
Alexander Kukushkin
2024-07-10 17:40:17 +02:00
committed by GitHub
parent 622d41c83c
commit c687838074
2 changed files with 14 additions and 5 deletions
+4
View File
@@ -274,6 +274,10 @@ class TestSlotsHandler(BaseTestPostgresql):
self.s.schedule_advance_slots({'foo': {'bar': 100}})
self.s._advance.sync_slots()
self.assertEqual(self.s._advance._copy_slots, ["bar"])
# we don't want to make attempts to advance slots that are to be copied
self.s.schedule_advance_slots({'foo': {'bar': 101}})
self.assertEqual(self.s._advance._scheduled, {})
self.s._advance.clean()
with patch.object(SlotsAdvanceThread, 'sync_slots', Mock(side_effect=Exception)):
self.s._advance._condition.wait = Mock()