Refactor RunningFunctionTaskMap to use composite string key#4958
Refactor RunningFunctionTaskMap to use composite string key#4958nturinski wants to merge 6 commits into
Conversation
Replace Map<WorkspaceFolder|TaskScope, IRunningFuncTask[]> with Map<string, IRunningFuncTask> using a composite key derived from folder.uri + normalized cwd. This eliminates the linear array search in .get() and moves the path resolution out of the map class into a shared resolveAndNormalizeCwd() utility. Also removes TaskScope from all type signatures since FuncTaskProvider already filters out Global/Workspace scoped tasks, making TaskScope dead code across the codebase. A defensive typeof scope === 'object' guard is added in the event handler for safety. - LocalProject.ts now passes effectiveProjectPath (always available) for more correct map lookups instead of relying on no-arg fallback - pickFuncProcess.ts normalizes buildPath before .has()/.get() calls - All debug view nodes narrow workspaceFolder to WorkspaceFolder
There was a problem hiding this comment.
Pull request overview
Refactors function-host task tracking to use a composite string key (workspaceFolder URI + normalized cwd) so running task lookup is O(1) and ${workspaceFolder}/cwd normalization is centralized in a new utility.
Changes:
- Replaced
Map<WorkspaceFolder|TaskScope, IRunningFuncTask[]>withMap<string, IRunningFuncTask>keyed byfolderUri + "::" + normalizedCwd. - Added
resolveAndNormalizeCwd()and updated call sites to normalize cwd/build paths prior to map operations. - Narrowed multiple APIs/events/interfaces to use
WorkspaceFolderonly (removingTaskScope).
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/funcCoreTools/funcHostTask.ts | Implements the composite-key map, adds resolveAndNormalizeCwd, and narrows scope types. |
| src/workspace/LocalProject.ts | Uses normalized effective project path for running host port lookup. |
| src/workspace/listLocalFunctions.ts | Uses normalized effective project path when checking if host is running. |
| src/tree/localProject/LocalProjectTreeItem.ts | Narrows func-task event scope typing to WorkspaceFolder. |
| src/debug/registerFunctionHostDebugView.ts | Normalizes cwd before map lookups for debug view actions. |
| src/debug/nodes/HostTaskNode.ts | Normalizes cwd before reading task details/errors from the map. |
| src/debug/nodes/HostErrorNode.ts | Narrows stored scope to WorkspaceFolder. |
| src/debug/nodes/funcHostDebugUtils.ts | Removes dead Global scope label branch; WorkspaceFolder only. |
| src/commands/pickFuncProcess.ts | Normalizes build path for has/get checks against the new map. |
|
|
||
| if (buildPath) { | ||
| runningFuncTaskMap.delete(workspaceFolder, buildPath); | ||
| if (normalizedBuildPath) { |
There was a problem hiding this comment.
In stopFuncTaskIfRunning, when buildPath is omitted normalizedBuildPath is undefined, but the map entry is never deleted (if (normalizedBuildPath) ...). This leaves stale entries for hosts started with the default cwd (no explicit options.cwd), causing runningFuncTaskMap.has/get to think the host is still running. Consider deleting the folder-only key when normalizedBuildPath is undefined (or always delete the specific key you looked up).
| if (normalizedBuildPath) { | |
| if (!killAll) { |
| public delete(folder: vscode.WorkspaceFolder, normalizedCwd?: string): void { | ||
| if (normalizedCwd !== undefined) { | ||
| this._map.delete(this.makeKey(folder, normalizedCwd)); | ||
| } else { | ||
| // Delete all entries for this folder | ||
| const prefix = this.folderPrefix(folder); | ||
| for (const key of [...this._map.keys()]) { | ||
| if (key === prefix || key.startsWith(`${prefix}::`)) { | ||
| this._map.delete(key); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
RunningFunctionTaskMap.delete(folder, normalizedCwd?) treats normalizedCwd === undefined as “delete all entries for this folder”. That makes it impossible to delete a single entry whose normalized cwd is actually undefined (i.e., tasks that rely on the default cwd). In the current code, onDidEndTaskProcess calls runningFuncTaskMap.delete(scope, normalizedCwd) where normalizedCwd can be undefined, which would wipe all running tasks for that folder. Consider separating the APIs (e.g., deleteOne(folder, cwdKey) vs deleteAll(folder)), or using a sentinel value for the default-cwd key so single-entry deletion is always possible.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot apply changes based on the comments in this thread |
…tale entry bug Agent-Logs-Url: https://github.com/microsoft/vscode-azurefunctions/sessions/0915379d-9e3e-426b-a047-70794ebb3f65 Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/vscode-azurefunctions/sessions/0915379d-9e3e-426b-a047-70794ebb3f65 Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>
Applied all three reviewer suggestions in commits
|
|
@copilot resolve the merge conflicts in this pull request |
…nflicts Agent-Logs-Url: https://github.com/microsoft/vscode-azurefunctions/sessions/068afa11-97cc-4bb2-b7b1-2adc010c0881 Co-authored-by: nturinski <5290572+nturinski@users.noreply.github.com>
Merge conflicts resolved in commit
|
Summary
Replaces
Map<WorkspaceFolder|TaskScope, IRunningFuncTask[]>withMap<string, IRunningFuncTask>using a composite key derived fromfolder.uri + normalized cwd. This eliminates the linear array search in.get()and moves the${workspaceFolder}path resolution out of the map class into a sharedresolveAndNormalizeCwd()utility.Also removes
TaskScopefrom all type signatures sinceFuncTaskProvideralready filters outGlobal/Workspacescoped tasks, makingTaskScopedead code across the codebase.Changes
Core (
funcHostTask.ts)RunningFunctionTaskMap— internal map is nowMap<string, IRunningFuncTask>with a composite key (folder.uri.toString() + "::" + normalizedCwd). No more array storage or linear search.resolveAndNormalizeCwd()— new exported utility that handles${workspaceFolder}replacement +normalizePath(). All callers use this before interacting with the map..set(folder, normalizedCwd, task)— takes normalized cwd as an explicit parameter..get()/.has()— direct O(1) map lookups instead ofArray.find()..delete(folder, cwd?)/.getAll(folder)— prefix-match forkillAlland tree-view cases.IStoppedFuncTask.workspaceFolder,IRunningFuncTaskWithScope.scope— narrowed fromWorkspaceFolder | TaskScopetoWorkspaceFolder.stopFuncTaskIfRunning(),killFuncProcessByPortOrPid(),getFuncPortFromTaskOrProject()— narrowed parameter types.typeof scope === 'object'guard and normalize cwd before all map operations.Dependent files (8 files)
funcHostDebugUtils.ts—getScopeLabel()narrowed, removed dead'Global'branch.HostTaskNode.ts— narrowed constructor, normalizes cwd before.get().HostErrorNode.ts— narrowed constructor param.registerFunctionHostDebugView.ts— normalizes cwd before all.get()calls.pickFuncProcess.ts— normalizesbuildPathbefore.has()and.get().LocalProject.ts— now passeseffectiveProjectPath(always available) for more correct map lookups instead of relying on no-arg fallback.listLocalFunctions.ts— normalizeseffectiveProjectPathbefore.has().LocalProjectTreeItem.ts— removedTaskScopeimport, narrowedonFuncTaskChanged.Testing
npm run build:checkpasses with zero type errors.