Feature: failover priority (#2780)

The priority is configured with `failover_priority` tag. Possible values are from `0` till infinity, where `0` means that the node will never become the leader, which is the same as `nofailover` tag set to `true`. As a result, in the configuration file one should set only one of `failover_priority` or `nofailover` tags.

The failover priority kicks in only when there are more than one node have the same receive/replay LSN and are ahead of other nodes in the cluster. In this case the node with higher value of `failover_priority` is preferred. If there is a node with higher values of receive/replay LSN, it will become the new leader even if it has lower value of `failover_priority` (except when priority is set to 0).

Close https://github.com/zalando/patroni/issues/2759
This commit is contained in:
Mark Pekala
2023-10-24 12:22:48 +02:00
committed by GitHub
parent 65030c56ee
commit f5ee67fa1c
12 changed files with 278 additions and 24 deletions
+32
View File
@@ -325,3 +325,35 @@ class TestValidator(unittest.TestCase):
output = "\n".join(errors)
self.assertEqual(['postgresql.bin_dir', 'postgresql.bin_name.postgres', 'raft.bind_addr', 'raft.self_addr'],
parse_output(output))
def test_one_of(self, _, __):
c = copy.deepcopy(config)
# Providing neither is fine
del c["tags"]["nofailover"]
errors = schema(c)
self.assertNotIn("tags Multiple of ('nofailover', 'failover_priority') provided", errors)
# Just nofailover is fine
c["tags"]["nofailover"] = False
errors = schema(c)
self.assertNotIn("tags Multiple of ('nofailover', 'failover_priority') provided", errors)
# Just failover_priority is fine
del c["tags"]["nofailover"]
c["tags"]["failover_priority"] = 1
errors = schema(c)
self.assertNotIn("tags Multiple of ('nofailover', 'failover_priority') provided", errors)
# Providing both is not fine
c["tags"]["nofailover"] = False
errors = schema(c)
self.assertIn("tags Multiple of ('nofailover', 'failover_priority') provided", errors)
def test_failover_priority_int(self, *args):
c = copy.deepcopy(config)
del c["tags"]["nofailover"]
c["tags"]["failover_priority"] = 'a string'
errors = schema(c)
self.assertIn('tags.failover_priority a string is not an integer', errors)
c = copy.deepcopy(config)
del c["tags"]["nofailover"]
c["tags"]["failover_priority"] = -6
errors = schema(c)
self.assertIn('tags.failover_priority -6 didn\'t pass validation: Wrong value', errors)