diff --git a/patroni/__init__.py b/patroni/__init__.py index fb0c296a..c689d5f2 100644 --- a/patroni/__init__.py +++ b/patroni/__init__.py @@ -103,6 +103,8 @@ class Patroni(object): if self.config.reload_local_configuration(): self.reload_config() + reap_children() + logger.info(self.ha.run_cycle()) cluster = self.dcs.cluster diff --git a/patroni/ha.py b/patroni/ha.py index 68d9d1a3..2080e1ed 100644 --- a/patroni/ha.py +++ b/patroni/ha.py @@ -40,9 +40,9 @@ class Ha(object): def acquire_lock(self): return self.dcs.attempt_to_acquire_leader() - def update_lock(self): + def update_lock(self, write_leader_optime=False): ret = self.dcs.update_leader() - if ret and not self._async_executor.busy: + if ret and write_leader_optime: try: self.dcs.write_leader_optime(self.state_handler.last_operation()) except: @@ -67,7 +67,7 @@ class Ha(object): data['pending_restart'] = True if not self._async_executor.busy and data['state'] in ['running', 'restarting', 'starting']: try: - data['xlog_location'] = self.state_handler.xlog_position() + data['xlog_location'] = self.state_handler.xlog_position(retry=False) except: pass if self.patroni.scheduled_restart: @@ -428,7 +428,7 @@ class Ha(object): self.dcs.reset_cluster() return 'removed leader lock because postgres is not running as master' - if self.update_lock(): + if self.update_lock(True): return self.enforce_master_role('no action. i am the leader with the lock', 'promoted self to leader because i had the session lock') else: diff --git a/patroni/postgresql.py b/patroni/postgresql.py index 3edd654a..53c82e98 100644 --- a/patroni/postgresql.py +++ b/patroni/postgresql.py @@ -318,9 +318,10 @@ class Postgresql(object): return self._cursor_holder def close_connection(self): - if self._cursor_holder and self._cursor_holder.connection and self._cursor_holder.connection.closed == 0: - self._cursor_holder.connection.close() + if self._connection and self._connection.closed == 0: + self._connection.close() logger.info("closed patroni connection to the postgresql cluster") + self._cursor_holder = self._connection = None def _query(self, sql, *params): cursor = None @@ -888,11 +889,12 @@ BEGIN END; $$""".format(name, ' '.join(options)), name, password, password) - def xlog_position(self): - return self.query("""SELECT pg_xlog_location_diff(CASE WHEN pg_is_in_recovery() - THEN pg_last_xlog_replay_location() - ELSE pg_current_xlog_location() - END, '0/0')::bigint""").fetchone()[0] + def xlog_position(self, retry=True): + stmt = """SELECT pg_xlog_location_diff(CASE WHEN pg_is_in_recovery() + THEN pg_last_xlog_replay_location() + ELSE pg_current_xlog_location() + END, '0/0')::bigint""" + return (self.query(stmt) if retry else self._query(stmt)).fetchone()[0] def load_replication_slots(self): if self.use_slots and self._schedule_load_slots: diff --git a/tests/test_ha.py b/tests/test_ha.py index 3cf29d9f..da58eec4 100644 --- a/tests/test_ha.py +++ b/tests/test_ha.py @@ -139,7 +139,7 @@ class TestHa(unittest.TestCase): def test_update_lock(self): self.p.last_operation = Mock(side_effect=PostgresException('')) - self.assertTrue(self.ha.update_lock()) + self.assertTrue(self.ha.update_lock(True)) def test_touch_member(self): self.p.xlog_position = Mock(side_effect=Exception)