From 9bde7f4fde9e59bf2ed2f56f7b57f19a3be32bc3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 2 Mar 2026 21:58:28 +0000 Subject: [PATCH] perf: cache allowlist and account-id normalization --- src/channels/allowlist-match.ts | 59 ++++++++++++++++++++++++++++----- src/routing/account-id.ts | 30 +++++++++++++++-- src/slack/monitor/allow-list.ts | 18 +++++++++- 3 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/channels/allowlist-match.ts b/src/channels/allowlist-match.ts index 23063878a49..b30ef119c84 100644 --- a/src/channels/allowlist-match.ts +++ b/src/channels/allowlist-match.ts @@ -16,6 +16,17 @@ export type AllowlistMatch = { matchSource?: TSource; }; +type CachedAllowListSet = { + size: number; + set: Set; +}; + +const ALLOWLIST_SET_CACHE = new WeakMap(); +const SIMPLE_ALLOWLIST_CACHE = new WeakMap< + Array, + { normalized: string[]; size: number; wildcard: boolean; set: Set } +>(); + export function formatAllowlistMatchMeta( match?: { matchKey?: string; matchSource?: string } | null, ): string { @@ -26,11 +37,12 @@ export function resolveAllowlistMatchByCandidates(params allowList: string[]; candidates: Array<{ value?: string; source: TSource }>; }): AllowlistMatch { + const allowSet = resolveAllowListSet(params.allowList); for (const candidate of params.candidates) { if (!candidate.value) { continue; } - if (params.allowList.includes(candidate.value)) { + if (allowSet.has(candidate.value)) { return { allowed: true, matchKey: candidate.value, @@ -47,26 +59,57 @@ export function resolveAllowlistMatchSimple(params: { senderName?: string | null; allowNameMatching?: boolean; }): AllowlistMatch<"wildcard" | "id" | "name"> { - const allowFrom = params.allowFrom - .map((entry) => String(entry).trim().toLowerCase()) - .filter(Boolean); + const allowFrom = resolveSimpleAllowFrom(params.allowFrom); - if (allowFrom.length === 0) { + if (allowFrom.size === 0) { return { allowed: false }; } - if (allowFrom.includes("*")) { + if (allowFrom.wildcard) { return { allowed: true, matchKey: "*", matchSource: "wildcard" }; } const senderId = params.senderId.toLowerCase(); - if (allowFrom.includes(senderId)) { + if (allowFrom.set.has(senderId)) { return { allowed: true, matchKey: senderId, matchSource: "id" }; } const senderName = params.senderName?.toLowerCase(); - if (params.allowNameMatching === true && senderName && allowFrom.includes(senderName)) { + if (params.allowNameMatching === true && senderName && allowFrom.set.has(senderName)) { return { allowed: true, matchKey: senderName, matchSource: "name" }; } return { allowed: false }; } + +function resolveAllowListSet(allowList: string[]): Set { + const cached = ALLOWLIST_SET_CACHE.get(allowList); + if (cached && cached.size === allowList.length) { + return cached.set; + } + const set = new Set(allowList); + ALLOWLIST_SET_CACHE.set(allowList, { size: allowList.length, set }); + return set; +} + +function resolveSimpleAllowFrom(allowFrom: Array): { + normalized: string[]; + size: number; + wildcard: boolean; + set: Set; +} { + const cached = SIMPLE_ALLOWLIST_CACHE.get(allowFrom); + if (cached && cached.size === allowFrom.length) { + return cached; + } + + const normalized = allowFrom.map((entry) => String(entry).trim().toLowerCase()).filter(Boolean); + const set = new Set(normalized); + const built = { + normalized, + size: allowFrom.length, + wildcard: set.has("*"), + set, + }; + SIMPLE_ALLOWLIST_CACHE.set(allowFrom, built); + return built; +} diff --git a/src/routing/account-id.ts b/src/routing/account-id.ts index aa561c0bbca..4d7db31fc9f 100644 --- a/src/routing/account-id.ts +++ b/src/routing/account-id.ts @@ -6,6 +6,10 @@ const VALID_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i; const INVALID_CHARS_RE = /[^a-z0-9_-]+/g; const LEADING_DASH_RE = /^-+/; const TRAILING_DASH_RE = /-+$/; +const ACCOUNT_ID_CACHE_MAX = 512; + +const normalizeAccountIdCache = new Map(); +const normalizeOptionalAccountIdCache = new Map(); function canonicalizeAccountId(value: string): string { if (VALID_ID_RE.test(value)) { @@ -32,7 +36,13 @@ export function normalizeAccountId(value: string | undefined | null): string { if (!trimmed) { return DEFAULT_ACCOUNT_ID; } - return normalizeCanonicalAccountId(trimmed) || DEFAULT_ACCOUNT_ID; + const cached = normalizeAccountIdCache.get(trimmed); + if (cached) { + return cached; + } + const normalized = normalizeCanonicalAccountId(trimmed) || DEFAULT_ACCOUNT_ID; + setNormalizeCache(normalizeAccountIdCache, trimmed, normalized); + return normalized; } export function normalizeOptionalAccountId(value: string | undefined | null): string | undefined { @@ -40,5 +50,21 @@ export function normalizeOptionalAccountId(value: string | undefined | null): st if (!trimmed) { return undefined; } - return normalizeCanonicalAccountId(trimmed) || undefined; + if (normalizeOptionalAccountIdCache.has(trimmed)) { + return normalizeOptionalAccountIdCache.get(trimmed); + } + const normalized = normalizeCanonicalAccountId(trimmed) || undefined; + setNormalizeCache(normalizeOptionalAccountIdCache, trimmed, normalized); + return normalized; +} + +function setNormalizeCache(cache: Map, key: string, value: T): void { + cache.set(key, value); + if (cache.size <= ACCOUNT_ID_CACHE_MAX) { + return; + } + const oldest = cache.keys().next(); + if (!oldest.done) { + cache.delete(oldest.value); + } } diff --git a/src/slack/monitor/allow-list.ts b/src/slack/monitor/allow-list.ts index c8b1bfe6586..bc552c02cf4 100644 --- a/src/slack/monitor/allow-list.ts +++ b/src/slack/monitor/allow-list.ts @@ -8,8 +8,24 @@ import { normalizeStringEntriesLower, } from "../../shared/string-normalization.js"; +const SLACK_SLUG_CACHE_MAX = 512; +const slackSlugCache = new Map(); + export function normalizeSlackSlug(raw?: string) { - return normalizeHyphenSlug(raw); + const key = raw ?? ""; + const cached = slackSlugCache.get(key); + if (cached !== undefined) { + return cached; + } + const normalized = normalizeHyphenSlug(raw); + slackSlugCache.set(key, normalized); + if (slackSlugCache.size > SLACK_SLUG_CACHE_MAX) { + const oldest = slackSlugCache.keys().next(); + if (!oldest.done) { + slackSlugCache.delete(oldest.value); + } + } + return normalized; } export function normalizeAllowList(list?: Array) {