fix(chat-headers): cache internal marker lookups to prevent N+1 API calls

- BUG-4: Add in-memory cache for hasInternalMarker() results with 1000-entry limit
- Eliminates redundant session.message API calls for copilot marker detection
This commit is contained in:
YeonGyu-Kim 2026-02-21 02:16:03 +09:00
parent 21850face7
commit cd5e071eda

View File

@ -14,6 +14,9 @@ type ChatHeadersOutput = {
headers: Record<string, string> headers: Record<string, string>
} }
const INTERNAL_MARKER_CACHE_LIMIT = 1000
const internalMarkerCache = new Map<string, boolean>()
function isRecord(value: unknown): value is Record<string, unknown> { function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null return typeof value === "object" && value !== null
} }
@ -56,22 +59,45 @@ async function hasInternalMarker(
sessionID: string, sessionID: string,
messageID: string, messageID: string,
): Promise<boolean> { ): Promise<boolean> {
const cacheKey = `${sessionID}:${messageID}`
const cached = internalMarkerCache.get(cacheKey)
if (cached !== undefined) {
return cached
}
try { try {
const response = await client.session.message({ const response = await client.session.message({
path: { id: sessionID, messageID }, path: { id: sessionID, messageID },
}) })
const data = response.data const data = response.data
if (!isRecord(data) || !Array.isArray(data.parts)) return false if (!isRecord(data) || !Array.isArray(data.parts)) {
internalMarkerCache.set(cacheKey, false)
if (internalMarkerCache.size > INTERNAL_MARKER_CACHE_LIMIT) {
internalMarkerCache.clear()
}
return false
}
return data.parts.some((part) => { const hasMarker = data.parts.some((part) => {
if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string") { if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string") {
return false return false
} }
return part.text.includes(OMO_INTERNAL_INITIATOR_MARKER) return part.text.includes(OMO_INTERNAL_INITIATOR_MARKER)
}) })
internalMarkerCache.set(cacheKey, hasMarker)
if (internalMarkerCache.size > INTERNAL_MARKER_CACHE_LIMIT) {
internalMarkerCache.clear()
}
return hasMarker
} catch { } catch {
internalMarkerCache.set(cacheKey, false)
if (internalMarkerCache.size > INTERNAL_MARKER_CACHE_LIMIT) {
internalMarkerCache.clear()
}
return false return false
} }
} }