From 6e750b6921c42f3c2ffed2e135be4d9c65e96f36 Mon Sep 17 00:00:00 2001 From: Nick Maludy Date: Thu, 13 Feb 2020 11:11:35 -0500 Subject: [PATCH] Adds heartbeating to the consul driver. Change-Id: Ie22e944e270dfd37988724f76823f6fd38d19b21 Closes-Bug: #1752225 --- .../consul-heartbeat-support-3ec69e2ace537dc1.yaml | 9 +++++++++ tooz/drivers/consul.py | 13 +++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 releasenotes/notes/consul-heartbeat-support-3ec69e2ace537dc1.yaml diff --git a/releasenotes/notes/consul-heartbeat-support-3ec69e2ace537dc1.yaml b/releasenotes/notes/consul-heartbeat-support-3ec69e2ace537dc1.yaml new file mode 100644 index 00000000..7aa8dd4f --- /dev/null +++ b/releasenotes/notes/consul-heartbeat-support-3ec69e2ace537dc1.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Added heartbeat supported to the Consul driver so that locks would remain locked + instead of timing out on the first TTL. This can be considered both a feature and + a bug fix because previously the Consul driver would only hold the lock for the + first TTL and behind the scenes Consul would release it due to the lack of session + updates. In order for the Consul driver to perform distributed locking properly + you MUST utilize heartbeats! diff --git a/tooz/drivers/consul.py b/tooz/drivers/consul.py index f5cfd9bd..26a72e0f 100644 --- a/tooz/drivers/consul.py +++ b/tooz/drivers/consul.py @@ -158,6 +158,19 @@ class ConsulDriver(coordination.CoordinationDriver): self._session_id = None self._client = None + def heartbeat(self): + # THIS IS A REQUIREMENT FOR CONSUL TO WORK PROPERLY. + # Consul maintains a "session" token that is used to as the basis + # for all operations in the service. The session must be refreshed + # periodically or else it assumes that the agent maintaining the + # session has died or is unreachable. When a session expires all locks + # are released and any services that were registered with that session + # are marked as no longer active. + self._client.session.renew(self._session_id) + # renew the session every half-TTL or 1 second, whatever is larger + sleep_sec = max(self._ttl / 2, 1) + return sleep_sec + def get_lock(self, name): real_name = self._paths_join(self._namespace, u"locks", name) return ConsulLock(real_name, self._node, self._address,