Skip to content

Commit ec1ddc4

Browse files
committed
Serialize cleanup with association loading
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
1 parent 2965bfa commit ec1ddc4

2 files changed

Lines changed: 65 additions & 8 deletions

File tree

src/managers/builtin/inlineScript/envManager.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ export class InlineScriptEnvManager implements EnvironmentManager, Disposable {
197197
private discoveryRetryTimer: ReturnType<typeof setTimeout> | undefined;
198198
private readonly subscriptions: Disposable[] = [];
199199
private persistenceQueue: Promise<void> = Promise.resolve();
200+
private readonly persistedAssociationsLoaded: Promise<void>;
200201
private selectionQueue: Promise<void> = Promise.resolve();
201202
private cacheMaintenanceQueue: Promise<void> = Promise.resolve();
202203
private cacheMaintenanceBarrier: Deferred<void> | undefined;
@@ -246,12 +247,11 @@ export class InlineScriptEnvManager implements EnvironmentManager, Disposable {
246247
});
247248
}),
248249
);
249-
queueMicrotask(() => {
250-
void this.initializePersistedAssociations().catch((error) => {
251-
this.log.warn(
252-
`Failed to prime inline-script environment associations: ${getErrorMessage(error)}`,
253-
);
254-
});
250+
this.persistedAssociationsLoaded = this.loadPersistedAssociations();
251+
void this.initializePersistedAssociations().catch((error) => {
252+
this.log.warn(
253+
`Failed to prime inline-script environment associations: ${getErrorMessage(error)}`,
254+
);
255255
});
256256
}
257257

@@ -1812,12 +1812,16 @@ export class InlineScriptEnvManager implements EnvironmentManager, Disposable {
18121812
this.lastValidatedMetadataIdentityProofs.delete(scriptPath);
18131813
}
18141814

1815-
private initializePersistedAssociations(): Promise<void> {
1815+
private loadPersistedAssociations(): Promise<void> {
18161816
return this.enqueuePersistence(async (state) => {
18171817
const rawAssociations = await state.get<unknown>(INLINE_SCRIPT_ENVS_KEY);
18181818
const parsed = this.parsePersistedAssociations(rawAssociations);
18191819
this.applyPersistedAssociations(parsed?.records ?? {});
1820-
}).then(async () => {
1820+
});
1821+
}
1822+
1823+
private initializePersistedAssociations(): Promise<void> {
1824+
return this.persistedAssociationsLoaded.then(async () => {
18211825
await Promise.all(
18221826
[...this.fsPathToPersistedAssociation.keys()].map(async (scriptPath) => {
18231827
const uri = this.routingRegistry.getUri(scriptPath);
@@ -2164,6 +2168,7 @@ export class InlineScriptEnvManager implements EnvironmentManager, Disposable {
21642168

21652169
private clearAssociationsForScripts(scripts: readonly Uri[]): Promise<void> {
21662170
return this.enqueueSelection(async () => {
2171+
await this.persistedAssociationsLoaded;
21672172
const changes = scripts
21682173
.filter((uri) => uri.scheme === 'file')
21692174
.map((uri) => ({

src/test/managers/builtin/inlineScript/envManager.unit.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4946,6 +4946,58 @@ suite('InlineScriptEnvManager', () => {
49464946
assert.strictEqual(routingRegistry.hasValidatedAssociation(uri), false);
49474947
});
49484948

4949+
test('waits for persisted association initialization before handling a script deletion', async () => {
4950+
await nextTurn();
4951+
manager.dispose();
4952+
const uri = scriptUri();
4953+
const scriptPath = normalizePath(uri.fsPath);
4954+
persistedAssociations = {
4955+
[scriptPath]: matchedAssociationRecord(path.join(tempRoot, 'cached-python')),
4956+
};
4957+
let signalInitialRead!: () => void;
4958+
let releaseInitialRead!: () => void;
4959+
const initialReadStarted = new Promise<void>((resolve) => {
4960+
signalInitialRead = resolve;
4961+
});
4962+
const initialReadBarrier = new Promise<void>((resolve) => {
4963+
releaseInitialRead = resolve;
4964+
});
4965+
let associationReads = 0;
4966+
workspaceState.get.callsFake(async (key: string) => {
4967+
if (key !== INLINE_SCRIPT_ENVS_KEY) {
4968+
return undefined;
4969+
}
4970+
associationReads += 1;
4971+
if (associationReads === 1) {
4972+
signalInitialRead();
4973+
await initialReadBarrier;
4974+
}
4975+
return persistedAssociations;
4976+
});
4977+
workspaceState.set.resetHistory();
4978+
manager = new InlineScriptEnvManager(
4979+
nativeFinder,
4980+
api,
4981+
baseManager,
4982+
globalStorageUri,
4983+
makeFakeLog(),
4984+
routingRegistry,
4985+
);
4986+
await initialReadStarted;
4987+
4988+
fireDelete(uri);
4989+
await nextTurn();
4990+
releaseInitialRead();
4991+
await waitForCondition(
4992+
() => workspaceStateSetCalls(INLINE_SCRIPT_ENVS_KEY).length === 1,
4993+
'deleted association should be persisted after initialization completes',
4994+
);
4995+
4996+
assert.deepStrictEqual(persistedAssociations, {});
4997+
assert.strictEqual(await manager.get(uri), undefined);
4998+
assert.strictEqual(routingRegistry.hasValidatedAssociation(uri), false);
4999+
});
5000+
49495001
test('clears persisted association state for the old path when a script is renamed', async () => {
49505002
const oldUri = scriptUri('old.py');
49515003
const newUri = scriptUri('new.py');

0 commit comments

Comments
 (0)