Matrix: revalidate cached direct targets

This commit is contained in:
Gustavo Madeira Santana
2026-03-12 08:22:00 +00:00
parent b900cedcd4
commit e50f182035
2 changed files with 39 additions and 2 deletions

View File

@@ -166,6 +166,40 @@ describe("resolveMatrixRoomId", () => {
await expect(resolveMatrixRoomId(client, userId)).resolves.toBe("!dm-room:example.org");
});
it("revalidates cached direct rooms before reuse when membership changes", async () => {
const userId = "@shared:example.org";
const directRooms = ["!dm-room-1:example.org"];
const membersByRoom = new Map<string, string[]>([
["!dm-room-1:example.org", ["@bot:example.org", userId]],
["!dm-room-2:example.org", ["@bot:example.org", userId]],
]);
const client = {
getAccountData: vi.fn().mockImplementation(async () => ({
[userId]: [...directRooms],
})),
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
getJoinedRooms: vi
.fn()
.mockResolvedValue(["!dm-room-1:example.org", "!dm-room-2:example.org"]),
getJoinedRoomMembers: vi
.fn()
.mockImplementation(async (roomId: string) => membersByRoom.get(roomId) ?? []),
setAccountData: vi.fn(),
resolveRoom: vi.fn(),
} as unknown as MatrixClient;
await expect(resolveMatrixRoomId(client, userId)).resolves.toBe("!dm-room-1:example.org");
directRooms.splice(0, directRooms.length, "!dm-room-1:example.org", "!dm-room-2:example.org");
membersByRoom.set("!dm-room-1:example.org", [
"@bot:example.org",
userId,
"@mallory:example.org",
]);
await expect(resolveMatrixRoomId(client, userId)).resolves.toBe("!dm-room-2:example.org");
});
});
describe("normalizeThreadId", () => {

View File

@@ -97,13 +97,16 @@ async function resolveDirectRoomId(client: MatrixClient, userId: string): Promis
if (!isMatrixQualifiedUserId(trimmed)) {
throw new Error(`Matrix user IDs must be fully qualified (got "${trimmed}")`);
}
const selfUserId = (await client.getUserId().catch(() => null))?.trim() || null;
const directRoomCache = resolveDirectRoomCache(client);
const cached = directRoomCache.get(trimmed);
if (cached) {
if (cached && (await isStrictDirectRoom(client, cached, trimmed, selfUserId))) {
return cached;
}
const selfUserId = (await client.getUserId().catch(() => null))?.trim() || null;
if (cached) {
directRoomCache.delete(trimmed);
}
// 1) Fast path: use account data (m.direct) for *this* logged-in user (the bot).
try {