refactor(matrix): share bounded cache insertion (#113636)

This commit is contained in:
Vincent Koc
2026-07-25 19:43:58 +08:00
committed by GitHub
parent 421e287c45
commit 618f910377
3 changed files with 31 additions and 51 deletions

View File

@@ -0,0 +1,12 @@
// Matrix plugin module implements bounded in-memory cache insertion.
export function setBoundedMap<K, V>(map: Map<K, V>, key: K, value: V, maxEntries: number): void {
map.set(key, value);
if (map.size <= maxEntries) {
return;
}
// Map insertion order keeps eviction FIFO without moving refreshed keys.
const oldest = map.keys().next();
if (!oldest.done) {
map.delete(oldest.value);
}
}

View File

@@ -6,6 +6,7 @@ import {
readJoinedMatrixMembers,
} from "../direct-room.js";
import type { MatrixClient } from "../sdk.js";
import { setBoundedMap } from "./bounded-cache.js";
type DirectMessageCheck = {
roomId: string;
@@ -25,23 +26,8 @@ type DirectRoomTrackerOptions = {
const DM_CACHE_TTL_MS = 30_000;
const RECENT_INVITE_TTL_MS = 30_000;
const MAX_TRACKED_DM_ROOMS = 1024;
const MAX_TRACKED_DM_MEMBER_FLAGS = 2048;
function rememberBounded<T>(
map: Map<string, T>,
key: string,
value: T,
maxSize = MAX_TRACKED_DM_ROOMS,
): void {
map.set(key, value);
if (map.size > maxSize) {
const oldest = map.keys().next().value;
if (typeof oldest === "string") {
map.delete(oldest);
}
}
}
const MAX_DM_ROOMS = 1024;
const MAX_DM_MEMBER_FLAGS = 2048;
export function createDirectRoomTracker(client: MatrixClient, opts: DirectRoomTrackerOptions = {}) {
const log = opts.log ?? (() => {});
@@ -87,7 +73,7 @@ export function createDirectRoomTracker(client: MatrixClient, opts: DirectRoomTr
if (!normalized) {
throw new Error("membership unavailable");
}
rememberBounded(joinedMembersCache, roomId, { members: normalized, ts: now });
setBoundedMap(joinedMembersCache, roomId, { members: normalized, ts: now }, MAX_DM_ROOMS);
return normalized;
} catch (err) {
log(`matrix: dm member lookup failed room=${roomId} (${String(err)})`);
@@ -110,12 +96,7 @@ export function createDirectRoomTracker(client: MatrixClient, opts: DirectRoomTr
return cached.isDirect;
}
const isDirect = await hasDirectMatrixMemberFlag(client, roomId, normalizedUserId);
rememberBounded(
directMemberFlagCache,
cacheKey,
{ isDirect, ts: now },
MAX_TRACKED_DM_MEMBER_FLAGS,
);
setBoundedMap(directMemberFlagCache, cacheKey, { isDirect, ts: now }, MAX_DM_MEMBER_FLAGS);
return isDirect;
};
@@ -186,9 +167,12 @@ export function createDirectRoomTracker(client: MatrixClient, opts: DirectRoomTr
if (!normalizedRemoteUserId) {
return;
}
rememberBounded(locallyPromotedDirectRooms, roomId, {
remoteUserId: normalizedRemoteUserId,
});
setBoundedMap(
locallyPromotedDirectRooms,
roomId,
{ remoteUserId: normalizedRemoteUserId },
MAX_DM_ROOMS,
);
};
return {
@@ -207,10 +191,8 @@ export function createDirectRoomTracker(client: MatrixClient, opts: DirectRoomTr
if (!normalizedRemoteUserId) {
return;
}
rememberBounded(recentInviteCandidates, roomId, {
remoteUserId: normalizedRemoteUserId,
ts: Date.now(),
});
const invite = { remoteUserId: normalizedRemoteUserId, ts: Date.now() };
setBoundedMap(recentInviteCandidates, roomId, invite, MAX_DM_ROOMS);
log(`matrix: remembered invite candidate room=${roomId} sender=${normalizedRemoteUserId}`);
},
isDirectMessage: async (params: DirectMessageCheck): Promise<boolean> => {

View File

@@ -1,6 +1,7 @@
// Matrix plugin module implements room info behavior.
import { isMatrixNotFoundError } from "../errors.js";
import type { MatrixClient } from "../sdk.js";
import { setBoundedMap } from "./bounded-cache.js";
export type MatrixRoomInfo = {
name?: string;
@@ -10,18 +11,8 @@ export type MatrixRoomInfo = {
aliasesResolved: boolean;
};
const MAX_TRACKED_ROOM_INFO = 1024;
const MAX_TRACKED_MEMBER_DISPLAY_NAMES = 4096;
function rememberBounded<T>(map: Map<string, T>, key: string, value: T, maxEntries: number): void {
map.set(key, value);
if (map.size > maxEntries) {
const oldest = map.keys().next().value;
if (typeof oldest === "string") {
map.delete(oldest);
}
}
}
const MAX_ROOM_INFO = 1024;
const MAX_MEMBER_DISPLAY_NAMES = 4096;
export function createMatrixRoomInfoResolver(client: MatrixClient) {
const roomNameCache = new Map<string, Pick<MatrixRoomInfo, "name" | "nameResolved">>();
@@ -52,7 +43,7 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
}
const info = { name, nameResolved };
if (nameResolved) {
rememberBounded(roomNameCache, roomId, info, MAX_TRACKED_ROOM_INFO);
setBoundedMap(roomNameCache, roomId, info, MAX_ROOM_INFO);
}
return info;
};
@@ -84,7 +75,7 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
}
const info = { canonicalAlias, altAliases, aliasesResolved };
if (aliasesResolved) {
rememberBounded(roomAliasCache, roomId, info, MAX_TRACKED_ROOM_INFO);
setBoundedMap(roomAliasCache, roomId, info, MAX_ROOM_INFO);
}
return info;
};
@@ -111,12 +102,7 @@ export function createMatrixRoomInfoResolver(client: MatrixClient) {
.catch(() => null);
const displayName =
memberState && typeof memberState.displayname === "string" ? memberState.displayname : userId;
rememberBounded(
memberDisplayNameCache,
cacheKey,
displayName,
MAX_TRACKED_MEMBER_DISPLAY_NAMES,
);
setBoundedMap(memberDisplayNameCache, cacheKey, displayName, MAX_MEMBER_DISPLAY_NAMES);
return displayName;
};