perf: keep positive transcript team-affinity cached as files grow

fileBelongsToTeam streams a transcript's head lines to decide if it belongs to a
team, cached by (mtime,size). During launch the team's own session transcripts
grow on every poll, invalidating the cache and forcing a re-stream + head re-parse
each time (profiled at ~7-8% main-thread JS after the earlier fixes).

A positive affinity is decided by early head lines that persist as an append-only
transcript grows, so a true result stays valid while the file only grows. Reuse a
cached true when size has not shrunk; a false result is still re-checked on any
change (a short file may grow head lines mentioning the team) and a shrink forces a
re-scan. Existing resolver tests still pass.
This commit is contained in:
777genius 2026-05-30 10:15:07 +03:00
parent 1b4838d422
commit a4b9512c7c

View file

@ -1021,8 +1021,19 @@ export class TeamTranscriptProjectResolver {
const cacheKey = this.buildTeamAffinityFileCacheKey(filePath, normalizedTeam);
const cached = this.teamAffinityFileCache.get(cacheKey);
if (cached && cached.mtimeMs === fileStat.mtimeMs && cached.size === fileStat.size) {
return cached.belongsToTeam;
if (cached) {
// A positive affinity is decided by early "head" lines that persist as an
// append-only transcript grows, so a `true` result stays valid while the file
// only grows (size >= cached). This avoids re-streaming the team's own
// continuously-growing transcripts on every bootstrap poll. A `false` result
// is still re-checked on any change, since a short file may later grow head
// lines that mention the team; a shrink (rewrite/truncate) also forces a re-scan.
if (cached.belongsToTeam && fileStat.size >= cached.size) {
return true;
}
if (cached.mtimeMs === fileStat.mtimeMs && cached.size === fileStat.size) {
return cached.belongsToTeam;
}
}
const stream = createReadStream(filePath, { encoding: 'utf8' });