LOW: Add eviction policy for conversation history to prevent memory leak #39

Open
opened 2026-02-20 14:48:55 +02:00 by Koko210 · 0 comments
Owner

Problem

bot/utils/conversation_history.py stores per-channel conversation history in a Python dict in globals (globals.conversation_histories). Each channel the bot interacts with gets an entry that grows over time.

While individual channel histories may be bounded (the ConversationHistory class likely has a max length), the number of CHANNELS tracked grows without bound. Over weeks/months of operation:

  • Channels that the bot was once active in but are now inactive still hold memory
  • DM channels accumulate (each user who DMs the bot creates a channel entry)
  • Temporary voice channels, threads, etc., create entries that are never cleaned up

This is a slow memory leak that compounds over long uptimes.

Current Behavior

  • New channel interaction -> allocate ConversationHistory object
  • Channel goes inactive -> object remains in dict forever
  • No cleanup, no eviction, no TTL

Proposed Solution

Add an LRU or time-based eviction policy:

Option A: LRU with max size

from collections import OrderedDict

MAX_TRACKED_CHANNELS = 100  # configurable

class ConversationHistoryStore:
    def __init__(self, max_channels=100):
        self._store = OrderedDict()
        self.max_channels = max_channels
    
    def get(self, channel_id):
        if channel_id in self._store:
            self._store.move_to_end(channel_id)
            return self._store[channel_id]
        history = ConversationHistory()
        self._store[channel_id] = history
        if len(self._store) > self.max_channels:
            self._store.popitem(last=False)  # evict oldest
        return history

Option B: Time-based TTL

Add a last_accessed timestamp to each ConversationHistory. Run a periodic cleanup (e.g., every hour via APScheduler) that evicts entries older than N hours.

Option C: Both (LRU + TTL)

Combine max size and time-based eviction for the most robust solution.

Impact

  • Risk: Very Low (evicted channels simply lose their conversation context, which naturally happens on restart anyway)
  • Effort: Low
  • Benefit: Prevents unbounded memory growth over long uptimes

Files Affected

  • bot/utils/conversation_history.py
  • bot/globals.py (conversation_histories dict type may change)
## Problem bot/utils/conversation_history.py stores per-channel conversation history in a Python dict in globals (globals.conversation_histories). Each channel the bot interacts with gets an entry that grows over time. While individual channel histories may be bounded (the ConversationHistory class likely has a max length), the number of CHANNELS tracked grows without bound. Over weeks/months of operation: - Channels that the bot was once active in but are now inactive still hold memory - DM channels accumulate (each user who DMs the bot creates a channel entry) - Temporary voice channels, threads, etc., create entries that are never cleaned up This is a slow memory leak that compounds over long uptimes. ## Current Behavior - New channel interaction -> allocate ConversationHistory object - Channel goes inactive -> object remains in dict forever - No cleanup, no eviction, no TTL ## Proposed Solution Add an LRU or time-based eviction policy: ### Option A: LRU with max size from collections import OrderedDict MAX_TRACKED_CHANNELS = 100 # configurable class ConversationHistoryStore: def __init__(self, max_channels=100): self._store = OrderedDict() self.max_channels = max_channels def get(self, channel_id): if channel_id in self._store: self._store.move_to_end(channel_id) return self._store[channel_id] history = ConversationHistory() self._store[channel_id] = history if len(self._store) > self.max_channels: self._store.popitem(last=False) # evict oldest return history ### Option B: Time-based TTL Add a last_accessed timestamp to each ConversationHistory. Run a periodic cleanup (e.g., every hour via APScheduler) that evicts entries older than N hours. ### Option C: Both (LRU + TTL) Combine max size and time-based eviction for the most robust solution. ## Impact - Risk: Very Low (evicted channels simply lose their conversation context, which naturally happens on restart anyway) - Effort: Low - Benefit: Prevents unbounded memory growth over long uptimes ## Files Affected - bot/utils/conversation_history.py - bot/globals.py (conversation_histories dict type may change)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Koko210/miku-discord#39