Issue CHEKPOINT explicitely after promote happened (#1498)

It is safe to call pg_rewind on the replica only when pg_control on the primary contains information about the latest timeline. Postgres is usually doing immediate checkpoint right after promote and in most cases it works just fine. Unfortunately we regularly receive complaints that it takes to long (minutes) until the checkpoint is done and replicas can't perform rewind. At the same time doing the checkpoint manually immediately helped. So Patroni starts doing the same. When the promotion happened and postgres is not running in recovery, we explicitly issue the checkpoint.

We are intentionally not using the AsyncExecutor here, because we want the HA loop continues doing its normal flow.
This commit is contained in:
Alexander Kukushkin
2020-04-20 11:55:05 +02:00
committed by GitHub
parent 5fa912f8fa
commit 80fbe90056
4 changed files with 65 additions and 11 deletions
+28 -3
View File
@@ -7,6 +7,16 @@ from patroni.postgresql.rewind import Rewind
from . import BaseTestPostgresql, MockCursor, psycopg2_connect
class MockThread(object):
def __init__(self, target, args):
self._target = target
self._args = args
def start(self):
self._target(*self._args)
@patch('subprocess.call', Mock(return_value=0))
@patch('psycopg2.connect', psycopg2_connect)
class TestRewind(BaseTestPostgresql):
@@ -102,6 +112,21 @@ class TestRewind(BaseTestPostgresql):
self.r.check_leader_is_not_in_recovery()
self.r.check_leader_is_not_in_recovery()
@patch.object(Postgresql, 'controldata', Mock(return_value={"Latest checkpoint's TimeLineID": 1}))
def test_check_for_checkpoint_after_promote(self):
self.r.check_for_checkpoint_after_promote()
@patch('patroni.postgresql.rewind.Thread', MockThread)
@patch.object(Postgresql, 'controldata')
@patch.object(Postgresql, 'checkpoint')
def test_ensure_checkpoint_after_promote(self, mock_checkpoint, mock_controldata):
mock_checkpoint.return_value = None
self.r.ensure_checkpoint_after_promote()
self.r.ensure_checkpoint_after_promote()
self.r.reset_state()
mock_controldata.return_value = {"Latest checkpoint's TimeLineID": 1}
mock_checkpoint.side_effect = Exception
self.r.ensure_checkpoint_after_promote()
self.r.ensure_checkpoint_after_promote()
self.r.reset_state()
mock_controldata.side_effect = TypeError
self.r.ensure_checkpoint_after_promote()
self.r.ensure_checkpoint_after_promote()