Skip to content

Commit 43a6ca8

Browse files
committed
Reworked fix to avoid test execution hanging
1 parent bdb9cba commit 43a6ca8

1 file changed

Lines changed: 19 additions & 9 deletions

File tree

mcpgateway/plugins/__init__.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import logging
2424
import random
2525
import time
26-
from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union
26+
from typing import Any, Callable, Literal, Optional, TYPE_CHECKING, Union
2727

2828
# Third-Party
2929
from cpex.framework import ObservabilityProvider, TenantPluginManager
@@ -102,9 +102,10 @@ class _TeamBindingChangeMsg(BaseModel):
102102

103103
def _get_invalidation_hmac_key() -> Optional[bytes]:
104104
"""Return the HMAC signing key for pub/sub messages, or None if unconfigured."""
105-
from mcpgateway.config import settings # pylint: disable=import-outside-toplevel
106105
from pydantic import SecretStr # pylint: disable=import-outside-toplevel
107106

107+
from mcpgateway.config import settings # pylint: disable=import-outside-toplevel
108+
108109
secret = settings.jwt_secret_key
109110
if not secret:
110111
return None
@@ -491,21 +492,22 @@ async def _plugin_invalidation_listener() -> None:
491492
consecutive_failures = 0
492493

493494
while True:
495+
pubsub = None
494496
try:
495497
client = await _redis()
496498
if not client:
497499
_logger.debug("Plugin invalidation listener: Redis unavailable, retrying in 10s")
498500
await asyncio.sleep(10)
499501
continue
500502

501-
async with client.pubsub() as pubsub:
502-
await pubsub.subscribe(_REDIS_INVALIDATION_CHANNEL)
503-
_logger.info("Plugin invalidation listener subscribed to %s", _REDIS_INVALIDATION_CHANNEL)
504-
backoff = 1.0
505-
consecutive_failures = 0
503+
pubsub = client.pubsub()
504+
await pubsub.subscribe(_REDIS_INVALIDATION_CHANNEL)
505+
_logger.info("Plugin invalidation listener subscribed to %s", _REDIS_INVALIDATION_CHANNEL)
506+
backoff = 1.0
507+
consecutive_failures = 0
506508

507-
async for message in pubsub.listen():
508-
await _handle_invalidation_message(message)
509+
async for message in pubsub.listen():
510+
await _handle_invalidation_message(message)
509511

510512
except asyncio.CancelledError:
511513
_logger.info("Plugin invalidation listener cancelled")
@@ -524,6 +526,14 @@ async def _plugin_invalidation_listener() -> None:
524526
)
525527
await asyncio.sleep(delay)
526528
backoff = min(max_backoff, backoff * 2)
529+
finally:
530+
# Always release the pubsub connection back to the pool.
531+
# Using wait_for shields aclose() from an in-flight CancelledError:
532+
if pubsub is not None:
533+
try:
534+
await asyncio.wait_for(pubsub.aclose(), timeout=2.0)
535+
except Exception:
536+
pass
527537

528538

529539
async def start_plugin_invalidation_listener() -> None:

0 commit comments

Comments
 (0)