blob: cf0c2b4b12cbbd8bf0b85db0fa6e18ae3459d228 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Implements an in-memory cache for file search results.
* This cache optimizes subsequent searches by leveraging previously computed results.
*/
export class ResultCache {
private readonly cache: Map<string, string[]>;
private hits = 0;
private misses = 0;
constructor(private readonly allFiles: string[]) {
this.cache = new Map();
}
/**
* Retrieves cached search results for a given query, or provides a base set
* of files to search from.
* @param query The search query pattern.
* @returns An object containing the files to search and a boolean indicating
* if the result is an exact cache hit.
*/
async get(
query: string,
): Promise<{ files: string[]; isExactMatch: boolean }> {
const isCacheHit = this.cache.has(query);
if (isCacheHit) {
this.hits++;
return { files: this.cache.get(query)!, isExactMatch: true };
}
this.misses++;
// This is the core optimization of the memory cache.
// If a user first searches for "foo", and then for "foobar",
// we don't need to search through all files again. We can start
// from the results of the "foo" search.
// This finds the most specific, already-cached query that is a prefix
// of the current query.
let bestBaseQuery = '';
for (const key of this.cache?.keys?.() ?? []) {
if (query.startsWith(key) && key.length > bestBaseQuery.length) {
bestBaseQuery = key;
}
}
const filesToSearch = bestBaseQuery
? this.cache.get(bestBaseQuery)!
: this.allFiles;
return { files: filesToSearch, isExactMatch: false };
}
/**
* Stores search results in the cache.
* @param query The search query pattern.
* @param results The matching file paths to cache.
*/
set(query: string, results: string[]): void {
this.cache.set(query, results);
}
}
|