From 18da3f673a5c46888e705dd5a8fe154b99775cec Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Fri, 11 Sep 2026 11:02:38 +0530 Subject: [PATCH] refactor(gateway): release turn leases by token identity only Every `TurnLeaseToken` is now constructed by `SessionTurnLeaseRegistry.acquire` with its concrete `_SessionLease`, so `release()` no longer needs the `getattr(token, "lease", None) or self._leases.get(...)` fallback that #107013 left in place. Make `lease` a required constructor argument and resolve the lease from the token alone; the mapping lookup could only ever return the same object (or a stale alias after rotation, which is exactly the case identity release exists to avoid). --- gateway/turn_lease.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gateway/turn_lease.py b/gateway/turn_lease.py index dc69e1d43a..e04355dba0 100644 --- a/gateway/turn_lease.py +++ b/gateway/turn_lease.py @@ -45,9 +45,11 @@ class TurnLeaseToken: __slots__ = ("session_id", "owner_key", "generation", "released", "lease") - def __init__(self, session_id: str, owner_key: str, generation: int, lease: Optional["_SessionLease"] = None) -> None: + def __init__(self, session_id: str, owner_key: str, generation: int, lease: "_SessionLease") -> None: self.session_id, self.owner_key, self.generation = session_id, owner_key, generation self.released = False + # The concrete lease, so release resolves by identity even after a rotation re-aliases + # ``session_id`` (both ids map to this same lease). self.lease = lease def __repr__(self) -> str: # pragma: no cover - debug aid @@ -166,9 +168,7 @@ class SessionTurnLeaseRegistry: if token is None or token.released: return False token.released = True - lease = getattr(token, "lease", None) or self._leases.get(token.session_id) - if lease is None: - return False + lease = token.lease if lease.holder is not token: logger.debug("turn lease release skipped on session %s: token (key %s gen %s) is not " "the current holder", token.session_id, token.owner_key, token.generation)