Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/base/cachingResourceFetcher.ts
13389 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import { ICache, SQLiteCache } from './cache';
6
import { CacheMode, CacheScope, CurrentTestRunInfo, ICachingResourceFetcher } from './simulationContext';
7
8
export const usedResourceCaches = new Set<string>();
9
10
class Request<T> {
11
12
constructor(
13
readonly input: T,
14
readonly cacheScope: CacheScope,
15
readonly cacheSalt: string,
16
readonly inputCacheKey: string
17
) {
18
}
19
20
get hash() {
21
return `${this.cacheScope}:${this.cacheSalt}:${this.inputCacheKey}`;
22
}
23
24
toJSON() {
25
return this.input;
26
}
27
}
28
29
class ResourceFetcherSQLiteCache<I, R> extends SQLiteCache<Request<I>, R> {
30
constructor(currentTestRunInfo: CurrentTestRunInfo) {
31
super('resource', undefined, currentTestRunInfo);
32
}
33
}
34
35
export class CachingResourceFetcher implements ICachingResourceFetcher {
36
37
declare readonly _serviceBrand: undefined;
38
39
private cache: ICache<Request<any>, any> | undefined;
40
41
// needs to be static, otherwise concurrent writes will happen, since
42
// many instances of this will be created
43
private static Queues = new Map</* cache key */string, Promise<unknown>>();
44
45
constructor(
46
currentTestRunInfo: CurrentTestRunInfo,
47
cacheMode: CacheMode
48
) {
49
this.cache = cacheMode !== CacheMode.Disable
50
? new ResourceFetcherSQLiteCache(currentTestRunInfo)
51
: undefined;
52
}
53
54
public async invokeWithCache<I, R>(cacheScope: CacheScope, input: I, cacheSalt: string, inputCacheKey: string, fn: (input: I) => Promise<R>): Promise<R> {
55
if (!this.cache) {
56
return await fn(input);
57
}
58
59
// serialize accesses to the same cache key
60
const promise = Promise.resolve(CachingResourceFetcher.Queues.get(inputCacheKey)).then(async (): Promise<R> => {
61
const request = new Request(input, cacheScope, cacheSalt, inputCacheKey);
62
let result: R | undefined = await this.cache!.get(request);
63
64
if (result === undefined) {
65
result = await fn(input);
66
await this.cache!.set(request, result);
67
}
68
69
return result;
70
});
71
72
CachingResourceFetcher.Queues.set(inputCacheKey, promise.catch(() => { }));
73
74
return promise;
75
}
76
}
77
78