Skip to content

Commit 2e1a42c

Browse files
committed
fix: decode json-buffer values for keyv cache compat
1 parent d4f1e16 commit 2e1a42c

1 file changed

Lines changed: 30 additions & 1 deletion

File tree

extensions/copilot/test/base/cache.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ import { CurrentTestRunInfo } from './simulationContext';
1717
const compress = promisify(zlib.brotliCompress);
1818
const decompress = promisify(zlib.brotliDecompress);
1919

20+
/**
21+
* Yield to the libuv event loop.
22+
*
23+
* The previous `@keyv/sqlite` store was backed by the asynchronous `sqlite3`
24+
* driver, so every individual store operation resolved on a later loop tick.
25+
* Some consumers rely on that boundary: e.g. the panel multi-file edit flow
26+
* applies one code block's edits while the next code block's code-mapper request
27+
* is awaiting its cached response, so the next request is built against the
28+
* already-edited document. `node:sqlite`'s `DatabaseSync` is synchronous, so we
29+
* reintroduce the async boundary on every store operation to preserve that
30+
* interleaving (and thus compatibility with the recorded cache).
31+
*/
32+
function yieldEventLoop(): Promise<void> {
33+
return new Promise<void>(resolve => setImmediate(resolve));
34+
}
35+
2036
const DefaultCachePath = process.env.VITEST ? path.resolve(__dirname, '..', 'simulation', 'cache') : path.resolve(__dirname, '..', 'test', 'simulation', 'cache');
2137

2238
async function getGitRoot(cwd: string): Promise<string> {
@@ -48,19 +64,32 @@ class SqliteKeyValueStore {
4864
return `${SqliteKeyValueStore.NAMESPACE}:${key}`;
4965
}
5066

67+
private static _decodeJsonBufferValue(value: string): string {
68+
if (value.startsWith(':base64:')) {
69+
return value.slice(':base64:'.length);
70+
}
71+
if (value.startsWith(':')) {
72+
return value.slice(1);
73+
}
74+
return value;
75+
}
76+
5177
async get(key: string): Promise<string | undefined> {
78+
await yieldEventLoop();
5279
const row = this.db.prepare('SELECT value FROM keyv WHERE key = ?').get(this._namespacedKey(key)) as { value: string } | undefined;
5380
if (!row) {
5481
return undefined;
5582
}
56-
return JSON.parse(row.value).value as string;
83+
return SqliteKeyValueStore._decodeJsonBufferValue(JSON.parse(row.value).value as string);
5784
}
5885

5986
async set(key: string, value: string): Promise<void> {
87+
await yieldEventLoop();
6088
this.db.prepare('INSERT OR REPLACE INTO keyv (key, value) VALUES (?, ?)').run(this._namespacedKey(key), JSON.stringify({ value }));
6189
}
6290

6391
async has(key: string): Promise<boolean> {
92+
await yieldEventLoop();
6493
const row = this.db.prepare('SELECT 1 FROM keyv WHERE key = ?').get(this._namespacedKey(key));
6594
return row !== undefined;
6695
}

0 commit comments

Comments
 (0)