mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-28 21:01:43 +03:00
fix(discord): add TTL and LRU eviction to thread starter cache
Fixes #5260 The DISCORD_THREAD_STARTER_CACHE Map was growing unbounded during long-running gateway sessions, causing memory exhaustion. This fix adds: - 5-minute TTL expiry (thread starters rarely change) - Max 500 entries with LRU eviction - Same caching pattern used by Slack's thread resolver The implementation mirrors src/slack/monitor/thread-resolution.ts which already handles this correctly.
This commit is contained in:
@@ -29,12 +29,54 @@ type DiscordThreadParentInfo = {
|
|||||||
type?: ChannelType;
|
type?: ChannelType;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DISCORD_THREAD_STARTER_CACHE = new Map<string, DiscordThreadStarter>();
|
// Cache entry with timestamp for TTL-based eviction
|
||||||
|
type DiscordThreadStarterCacheEntry = {
|
||||||
|
value: DiscordThreadStarter;
|
||||||
|
updatedAt: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cache configuration: 5 minute TTL (thread starters rarely change), max 500 entries
|
||||||
|
const DISCORD_THREAD_STARTER_CACHE_TTL_MS = 5 * 60 * 1000;
|
||||||
|
const DISCORD_THREAD_STARTER_CACHE_MAX = 500;
|
||||||
|
|
||||||
|
const DISCORD_THREAD_STARTER_CACHE = new Map<string, DiscordThreadStarterCacheEntry>();
|
||||||
|
|
||||||
export function __resetDiscordThreadStarterCacheForTest() {
|
export function __resetDiscordThreadStarterCacheForTest() {
|
||||||
DISCORD_THREAD_STARTER_CACHE.clear();
|
DISCORD_THREAD_STARTER_CACHE.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get cached entry with TTL check, refresh LRU position on hit
|
||||||
|
function getCachedThreadStarter(key: string, now: number): DiscordThreadStarter | undefined {
|
||||||
|
const entry = DISCORD_THREAD_STARTER_CACHE.get(key);
|
||||||
|
if (!entry) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// Check TTL expiry
|
||||||
|
if (now - entry.updatedAt > DISCORD_THREAD_STARTER_CACHE_TTL_MS) {
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// Refresh LRU position by re-inserting (Map maintains insertion order)
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.set(key, { ...entry, updatedAt: now });
|
||||||
|
return entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cached entry with LRU eviction when max size exceeded
|
||||||
|
function setCachedThreadStarter(key: string, value: DiscordThreadStarter, now: number): void {
|
||||||
|
// Remove existing entry first (to update LRU position)
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.set(key, { value, updatedAt: now });
|
||||||
|
// Evict oldest entries (first in Map) when over max size
|
||||||
|
while (DISCORD_THREAD_STARTER_CACHE.size > DISCORD_THREAD_STARTER_CACHE_MAX) {
|
||||||
|
const oldestKey = DISCORD_THREAD_STARTER_CACHE.keys().next().value;
|
||||||
|
if (!oldestKey) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DISCORD_THREAD_STARTER_CACHE.delete(oldestKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isDiscordThreadType(type: ChannelType | undefined): boolean {
|
function isDiscordThreadType(type: ChannelType | undefined): boolean {
|
||||||
return (
|
return (
|
||||||
type === ChannelType.PublicThread ||
|
type === ChannelType.PublicThread ||
|
||||||
@@ -100,7 +142,8 @@ export async function resolveDiscordThreadStarter(params: {
|
|||||||
resolveTimestampMs: (value?: string | null) => number | undefined;
|
resolveTimestampMs: (value?: string | null) => number | undefined;
|
||||||
}): Promise<DiscordThreadStarter | null> {
|
}): Promise<DiscordThreadStarter | null> {
|
||||||
const cacheKey = params.channel.id;
|
const cacheKey = params.channel.id;
|
||||||
const cached = DISCORD_THREAD_STARTER_CACHE.get(cacheKey);
|
const now = Date.now();
|
||||||
|
const cached = getCachedThreadStarter(cacheKey, now);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
@@ -146,7 +189,7 @@ export async function resolveDiscordThreadStarter(params: {
|
|||||||
author,
|
author,
|
||||||
timestamp: timestamp ?? undefined,
|
timestamp: timestamp ?? undefined,
|
||||||
};
|
};
|
||||||
DISCORD_THREAD_STARTER_CACHE.set(cacheKey, payload);
|
setCachedThreadStarter(cacheKey, payload, Date.now());
|
||||||
return payload;
|
return payload;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user