|
| 1 | +// Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | +// Licensed under the MIT License. |
| 3 | + |
| 4 | +import { EnvironmentPath, PythonExtension } from '../api/types'; |
| 5 | +import { Uri } from 'vscode'; |
| 6 | + |
| 7 | +const MAX_TRACKED_URIS = 100; // Maximum number of environments to track |
| 8 | +const MAX_TRACKED_AGE = 15 * 60 * 1000; // Maximum age of tracked environments in milliseconds (15 minutes) |
| 9 | + |
| 10 | +type LastUsedEnvEntry = { uri: Uri | undefined; env: EnvironmentPath; dateTime: number }; |
| 11 | +const lastUsedEnvs: LastUsedEnvEntry[] = []; |
| 12 | + |
| 13 | +/** |
| 14 | + * Track the use of an environment for a given resource (uri). |
| 15 | + * Prunes items older than 60 minutes or if the list grows over 100. |
| 16 | + */ |
| 17 | +export function trackEnvUsedByTool(uri: Uri | undefined, env: EnvironmentPath) { |
| 18 | + const now = Date.now(); |
| 19 | + // Remove any previous entry for this uri |
| 20 | + for (let i = lastUsedEnvs.length - 1; i >= 0; i--) { |
| 21 | + if (urisEqual(lastUsedEnvs[i].uri, uri)) { |
| 22 | + lastUsedEnvs.splice(i, 1); |
| 23 | + } |
| 24 | + } |
| 25 | + // Add the new entry |
| 26 | + lastUsedEnvs.push({ uri, env, dateTime: now }); |
| 27 | + // Prune |
| 28 | + pruneLastUsedEnvs(); |
| 29 | +} |
| 30 | + |
| 31 | +/** |
| 32 | + * Get the last used environment for a given resource (uri), or undefined if not found or expired. |
| 33 | + */ |
| 34 | +export function getLastEnvUsedByTool( |
| 35 | + uri: Uri | undefined, |
| 36 | + api: PythonExtension['environments'], |
| 37 | +): EnvironmentPath | undefined { |
| 38 | + pruneLastUsedEnvs(); |
| 39 | + // Find the most recent entry for this uri that is not expired |
| 40 | + const item = lastUsedEnvs.find((item) => urisEqual(item.uri, uri)); |
| 41 | + if (item) { |
| 42 | + return item.env; |
| 43 | + } |
| 44 | + const envPath = api.getActiveEnvironmentPath(uri); |
| 45 | + if (lastUsedEnvs.some((item) => item.env.id === envPath.id)) { |
| 46 | + // If this env was already used, return it |
| 47 | + return envPath; |
| 48 | + } |
| 49 | + return undefined; |
| 50 | +} |
| 51 | + |
| 52 | +/** |
| 53 | + * Compare two uris (or undefined) for equality. |
| 54 | + */ |
| 55 | +function urisEqual(a: Uri | undefined, b: Uri | undefined): boolean { |
| 56 | + if (a === b) { |
| 57 | + return true; |
| 58 | + } |
| 59 | + if (!a || !b) { |
| 60 | + return false; |
| 61 | + } |
| 62 | + return a.toString() === b.toString(); |
| 63 | +} |
| 64 | + |
| 65 | +/** |
| 66 | + * Remove items older than 60 minutes or if the list grows over 100. |
| 67 | + */ |
| 68 | +function pruneLastUsedEnvs() { |
| 69 | + const now = Date.now(); |
| 70 | + // Remove items older than 60 minutes |
| 71 | + for (let i = lastUsedEnvs.length - 1; i >= 0; i--) { |
| 72 | + if (now - lastUsedEnvs[i].dateTime > MAX_TRACKED_AGE) { |
| 73 | + lastUsedEnvs.splice(i, 1); |
| 74 | + } |
| 75 | + } |
| 76 | + // If still over 100, remove oldest |
| 77 | + if (lastUsedEnvs.length > MAX_TRACKED_URIS) { |
| 78 | + lastUsedEnvs.sort((a, b) => b.dateTime - a.dateTime); |
| 79 | + lastUsedEnvs.length = MAX_TRACKED_URIS; |
| 80 | + } |
| 81 | +} |
0 commit comments