Repository: zalando/patroni
Pull request #2896 (2023-10-06 05:13:51)

Ignore synchronous_mode setting in a standby cluster
is_synchronous_mode() should always return False in standby clusters

coveralls: ## Pull Request Test Coverage Report for [Build 6427753899](https://coveralls.io/builds/63127010)

* **1** of **1**   **(100.0%)**  changed or added relevant line in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **99.863%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/63127010/badge)](https://coveralls.io/builds/63127010) |
| :-- | --: |
| Change from base [Build 6404304255](https://coveralls.io/builds/63075492): |  0.0% |
| Covered Lines: | 13144 |
| Relevant Lines: | 13162 |

---
##### 💛  - [Coveralls](https://coveralls.io)

CyberDem0n: :+1:
hughcapet: 👍 

Patch:
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 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 postgres1 is replicating from postgres2 after 32 seconds
+
   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
+    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:8010/standby_leader
+    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 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 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:


Test patch:
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)