fix: harden _await_disconnect_step against outer cancellation + add claim keys

Follow-up to #80700:

1. _await_disconnect_step was missing the try/except CancelledError around
   asyncio.wait() that _await_adapter_cleanup_with_timeout already has.
   When the outer fatal-handler timeout cancels disconnect() mid-step,
   asyncio.wait does NOT cancel its inner task — the task was orphaned
   with no observer. Add the same cancel+detach+re-raise pattern.

2. _queue_retryable_fatal_platform omitted credential_claim/listener_claim
   keys that all 3 startup-path queue sites include. These are consumed by
   the multiplex reservation logic to prevent secondary profiles from
   taking the endpoint while a primary is queued. Pre-existing latent bug
   — now fixed since the extraction makes it trivial.
This commit is contained in:
kshitij 2026-08-07 18:28:18 +05:30
parent 95e78556f4
commit e5e96e8bb5
2 changed files with 19 additions and 4 deletions

View File

@ -7270,6 +7270,12 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
"config": platform_config,
"attempts": 0,
"next_retry": time.monotonic(),
"credential_claim": self._adapter_credential_claim(
adapter.platform, adapter
),
"listener_claim": self._adapter_listener_claim(
adapter.platform, adapter
),
}
logger.info(
"%s queued for background reconnection",

View File

@ -4318,10 +4318,19 @@ class TelegramAdapter(BasePlatformAdapter):
via ``_consume_abandoned_task``.
"""
task = asyncio.ensure_future(awaitable)
if timeout <= 0:
done, _pending = await asyncio.wait({task})
else:
done, _pending = await asyncio.wait({task}, timeout=timeout)
try:
if timeout <= 0:
done, _pending = await asyncio.wait({task})
else:
done, _pending = await asyncio.wait({task}, timeout=timeout)
except asyncio.CancelledError:
# Outer cancellation (e.g. the fatal handler's outer timeout) must
# not orphan the inner task — asyncio.wait does NOT cancel its
# futures when itself cancelled (#80598). Mirror the pattern used
# by GatewayRunner._await_adapter_cleanup_with_timeout.
task.cancel()
task.add_done_callback(_consume_abandoned_task)
raise
if task in done:
# Intentional cancels (heartbeat / identity / lifecycle) surface as
# CancelledError — swallow so disconnect keeps advancing.