fix: cover discord thread starter cache TTL (#5274) (thanks @webvijayi)

This commit is contained in:
Shadow
2026-02-12 16:31:05 -06:00
parent 4e6330e2ab
commit bf690507bf
2 changed files with 47 additions and 2 deletions

View File

@@ -64,6 +64,7 @@ Docs: https://docs.openclaw.ai
- Agents: prevent file descriptor leaks in child process cleanup. (#13565) Thanks @KyleChen26.
- Agents: prevent double compaction caused by cache TTL bypassing guard. (#13514) Thanks @taw0002.
- Agents: use last API call's cache tokens for context display instead of accumulated sum. (#13805) Thanks @akari-musubi.
- Discord: add TTL/LRU eviction to the thread starter cache to prevent unbounded growth. (#5274) Thanks @webvijayi.
- Discord tests: use a partial @buape/carbon mock in slash command coverage. (#13262) Thanks @arosstale.
- Tests: update thread ID handling in Slack message collection tests. (#14108) Thanks @swizzmagik.

View File

@@ -1,10 +1,12 @@
import type { Client } from "@buape/carbon";
import { describe, expect, it } from "vitest";
import { ChannelType, type Client } from "@buape/carbon";
import { afterEach, describe, expect, it, vi } from "vitest";
import { buildAgentSessionKey } from "../../routing/resolve-route.js";
import {
__resetDiscordThreadStarterCacheForTest,
resolveDiscordAutoThreadContext,
resolveDiscordAutoThreadReplyPlan,
resolveDiscordReplyDeliveryPlan,
resolveDiscordThreadStarter,
} from "./threading.js";
describe("resolveDiscordAutoThreadContext", () => {
@@ -142,3 +144,45 @@ describe("resolveDiscordAutoThreadReplyPlan", () => {
expect(plan.autoThreadContext).toBeNull();
});
});
describe("resolveDiscordThreadStarter cache", () => {
afterEach(() => {
vi.useRealTimers();
__resetDiscordThreadStarterCacheForTest();
});
it("expires cached entries after TTL", async () => {
vi.useFakeTimers();
const baseTime = new Date("2026-02-12T00:00:00Z").getTime();
vi.setSystemTime(baseTime);
const restGet = vi.fn(async () => ({
content: "starter",
author: { username: "starter", id: "user-1" },
timestamp: "2026-02-12T00:00:00Z",
}));
const client = { rest: { get: restGet } } as unknown as Client;
const params = {
channel: { id: "thread-1" },
client,
parentId: "parent-1",
parentType: ChannelType.GuildText,
resolveTimestampMs: () => baseTime,
};
const first = await resolveDiscordThreadStarter(params);
expect(first?.text).toBe("starter");
expect(restGet).toHaveBeenCalledTimes(1);
vi.setSystemTime(baseTime + 60_000);
const second = await resolveDiscordThreadStarter(params);
expect(second).toEqual(first);
expect(restGet).toHaveBeenCalledTimes(1);
vi.setSystemTime(baseTime + 60_000 + 5 * 60_000 + 1);
const third = await resolveDiscordThreadStarter(params);
expect(third).toEqual(first);
expect(restGet).toHaveBeenCalledTimes(2);
});
});