diff --git a/news/1 Enhancements/17474.md b/news/1 Enhancements/17474.md new file mode 100644 index 000000000000..4c60fd858a39 --- /dev/null +++ b/news/1 Enhancements/17474.md @@ -0,0 +1 @@ +Resolve environments using cache if cache has complete env info. diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts index c6d116792ea1..94d4a7ad151e 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts @@ -36,10 +36,10 @@ export interface IEnvsCollectionCache { addEnv(env: PythonEnvInfo): void; /** - * Return cached environment information for a given interpreter path if it exists, - * otherwise return `undefined`. + * Return cached environment information for a given interpreter path if it exists and + * has complete info, otherwise return `undefined`. */ - getEnv(path: string): PythonEnvInfo | undefined; + getCompleteInfo(path: string): PythonEnvInfo | undefined; /** * Writes the content of the in-memory cache to persistent storage. @@ -53,6 +53,8 @@ export interface IEnvsCollectionCache { validateCache(): Promise; } +type PythonEnvCompleteInfo = { hasCompleteInfo?: boolean } & PythonEnvInfo; + interface IPersistentStorage { load(): Promise; store(envs: PythonEnvInfo[]): Promise; @@ -63,7 +65,7 @@ interface IPersistentStorage { */ export class PythonEnvInfoCache extends PythonEnvsWatcher implements IEnvsCollectionCache { - private envs: PythonEnvInfo[] = []; + private envs: PythonEnvCompleteInfo[] = []; constructor(private readonly persistentStorage: IPersistentStorage) { super(); @@ -103,8 +105,9 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher areSameEnv(e, executablePath)); + public getCompleteInfo(executablePath: string): PythonEnvInfo | undefined { + const env = this.envs.find((e) => areSameEnv(e, executablePath)); + return env?.hasCompleteInfo ? env : undefined; } public async clearAndReloadFromStorage(): Promise { @@ -114,6 +117,9 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher { if (this.envs.length) { traceInfo('Environments added to cache', JSON.stringify(this.envs)); + this.envs.forEach((e) => { + e.hasCompleteInfo = true; + }); await this.persistentStorage.store(this.envs); } } diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts index 71f76b6e9ee3..1c014d293177 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts @@ -54,10 +54,11 @@ export class EnvsCollectionService extends PythonEnvsWatcher { - const cachedEnv = this.cache.getEnv(executablePath); - // Envs in cache may have incomplete info when a refresh is happening, so - // do not rely on cache in those cases. - if (cachedEnv && this.refreshPromises.size === 0) { + // Note cache may have incomplete info when a refresh is happening. + // This API is supposed to return complete info by definition, so + // only use cache if it has complete info on an environment. + const cachedEnv = this.cache.getCompleteInfo(executablePath); + if (cachedEnv) { return cachedEnv; } const resolved = await this.locator.resolveEnv(executablePath);