From efacc6c16b8c0af6e258ee353b8913c120157b68 Mon Sep 17 00:00:00 2001 From: Polina Bungina <27892524+hughcapet@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:21:37 +0200 Subject: [PATCH] Ignore synchronous_mode setting in a standby cluster (#2896) is_synchronous_mode() should always return False in standby clusters --- features/standby_cluster.feature | 27 +++++++++++++++++---------- features/steps/standby_cluster.py | 1 + patroni/config.py | 4 ++-- tests/test_config.py | 7 ++++++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/features/standby_cluster.feature b/features/standby_cluster.feature index 7ff07679..ac6bbb85 100644 --- a/features/standby_cluster.feature +++ b/features/standby_cluster.feature @@ -53,15 +53,22 @@ Feature: standby cluster And I receive a response replication_state streaming And postgres1 does not have a logical replication slot named test_logical - Scenario: check failover - When I kill postgres1 - And I kill postmaster on postgres1 - Then postgres2 is replicating from postgres0 after 32 seconds - When I issue a GET request to http://127.0.0.1:8010/primary - Then I receive a response code 503 - And I sleep for 3 seconds - When I issue a GET request to http://127.0.0.1:8010/standby_leader + Scenario: check switchover + When I run patronictl.py switchover batman1 --force + And I issue a GET request to http://127.0.0.1:8010/standby_leader Then I receive a response code 200 And I receive a response role standby_leader - And replication works from postgres0 to postgres2 after 15 seconds - And there is a postgres2_cb.log with "on_start replica batman1\non_role_change standby_leader batman1" in postgres2 data directory + And postgres1 is replicating from postgres2 after 32 seconds + + Scenario: check failover + When I kill postgres2 + And I kill postmaster on postgres2 + Then postgres1 is replicating from postgres0 after 32 seconds + When I issue a GET request to http://127.0.0.1:8009/primary + Then I receive a response code 503 + And I sleep for 3 seconds + When I issue a GET request to http://127.0.0.1:8009/standby_leader + Then I receive a response code 200 + And I receive a response role standby_leader + And replication works from postgres0 to postgres1 after 15 seconds + And there is a postgres1_cb.log with "on_start replica batman1\non_role_change standby_leader batman1" in postgres1 data directory diff --git a/features/steps/standby_cluster.py b/features/steps/standby_cluster.py index 17d635b8..a428130c 100644 --- a/features/steps/standby_cluster.py +++ b/features/steps/standby_cluster.py @@ -34,6 +34,7 @@ def start_patroni_standby_cluster(context, name, cluster_name, name2): "ttl": 20, "loop_wait": 2, "retry_timeout": 5, + "synchronous_mode": True, # should be completely ignored "standby_cluster": { "host": "localhost", "port": port, diff --git a/patroni/config.py b/patroni/config.py index a0384504..5779aaac 100644 --- a/patroni/config.py +++ b/patroni/config.py @@ -96,8 +96,8 @@ class GlobalConfig(object): @property def is_synchronous_mode(self) -> bool: - """``True`` if synchronous replication is requested.""" - return self.check_mode('synchronous_mode') + """``True`` if synchronous replication is requested and it is not a standby cluster config.""" + return self.check_mode('synchronous_mode') and not self.is_standby_cluster @property def is_synchronous_mode_strict(self) -> bool: diff --git a/tests/test_config.py b/tests/test_config.py index 8515476a..2b21f589 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -5,7 +5,7 @@ import io from copy import deepcopy from mock import MagicMock, Mock, patch -from patroni.config import Config, ConfigParseError +from patroni.config import Config, ConfigParseError, GlobalConfig class TestConfig(unittest.TestCase): @@ -197,3 +197,8 @@ class TestConfig(unittest.TestCase): self.assertEqual(mock_logger.call_args_list[0][0], ('Violated the rule "loop_wait + 2*retry_timeout <= ttl", where ttl=%d. Adjusting' ' loop_wait from %d to %d and retry_timeout from %d to %d', 20, 10, 1, 10, 9)) + + def test_global_config_is_synchronous_mode(self): + # we should ignore synchronous_mode setting in a standby cluster + config = {'standby_cluster': {'host': 'some_host'}, 'synchronous_mode': True} + self.assertFalse(GlobalConfig(config).is_synchronous_mode)