fix(slack): cap _user_name_cache to prevent unbounded growth

_resolve_user_name() caches every resolved (team_id, user_id) → display
name but never evicts entries. On a long-running bot in a large
workspace every unique user the bot encounters adds a permanent entry.
Sibling structures _bot_message_ts (BOT_TS_MAX=5000) and
_assistant_threads (ASSISTANT_THREADS_MAX=5000) already have caps;
_user_name_cache had none.

Fix: add _USER_NAME_CACHE_MAX = 5000 and evict the oldest half on
overflow after each write, matching the existing sibling pattern.
Consolidates the two cache-write branches (success + API error) into a
single write so eviction runs once per resolution.

Reapplied from #23676 onto the current adapter (cache moved to
plugins/platforms/slack/adapter.py and is now keyed by
(team_id, user_id) tuples for multi-workspace safety).
This commit is contained in:
EloquentBrush 2026-07-22 08:03:36 -07:00 committed by Teknium
parent 7ce8f3fb1f
commit 9d5d8ce0b2
No known key found for this signature in database

View file

@ -675,6 +675,7 @@ class SlackAdapter(BasePlatformAdapter):
# so a multi-workspace Socket Mode process never reuses another
# tenant's display name.
self._user_name_cache: Dict[Tuple[str, str], str] = {}
self._USER_NAME_CACHE_MAX = 5000
self._socket_mode_task: Optional[asyncio.Task] = None
# Multi-workspace support
self._team_clients: Dict[str, Any] = {} # team_id → WebClient
@ -2763,12 +2764,16 @@ class SlackAdapter(BasePlatformAdapter):
or user.get("name")
or user_id
)
self._user_name_cache[cache_key] = name
return name
except Exception as e:
logger.debug("[Slack] users.info failed for %s: %s", user_id, e)
self._user_name_cache[cache_key] = user_id
return user_id
name = user_id
self._user_name_cache[cache_key] = name
if len(self._user_name_cache) > self._USER_NAME_CACHE_MAX:
excess = len(self._user_name_cache) - self._USER_NAME_CACHE_MAX // 2
for old_key in list(self._user_name_cache)[:excess]:
del self._user_name_cache[old_key]
return name
async def _humanize_user_mentions(
self, text: str, chat_id: str = "", team_id: str = ""