chore(lint): parallelize more safe awaits in server (no-await-in-loop)

- Workspace reconciliation: archive missing workspaces and orphaned
  projects concurrently instead of sequentially.
- Directory suggestions: resolve child directory candidates in parallel
  before filtering.
This commit is contained in:
Mohamed Boudra
2026-04-24 01:44:29 +07:00
parent 1ffec56bbe
commit 0302b5b32e
2 changed files with 30 additions and 30 deletions

View File

@@ -114,8 +114,9 @@ export class WorkspaceReconciliationService {
}
// 1. Archive workspaces whose directories no longer exist
for (const workspace of activeWorkspaces) {
if (!existsSync(workspace.cwd)) {
const missingWorkspaces = activeWorkspaces.filter((workspace) => !existsSync(workspace.cwd));
await Promise.all(
missingWorkspaces.map(async (workspace) => {
const timestamp = new Date().toISOString();
await this.workspaceRegistry.archive(workspace.workspaceId, timestamp);
changes.push({
@@ -131,13 +132,16 @@ export class WorkspaceReconciliationService {
const updated = siblings.filter((w) => w.workspaceId !== workspace.workspaceId);
workspacesByProject.set(workspace.projectId, updated);
}
}
}
}),
);
// 2. Archive orphaned projects (all workspaces archived/removed)
for (const project of activeProjects) {
const orphanedProjects = activeProjects.filter((project) => {
const siblings = workspacesByProject.get(project.projectId) ?? [];
if (siblings.length === 0) {
return siblings.length === 0;
});
await Promise.all(
orphanedProjects.map(async (project) => {
const timestamp = new Date().toISOString();
await this.projectRegistry.archive(project.projectId, timestamp);
changes.push({
@@ -146,8 +150,8 @@ export class WorkspaceReconciliationService {
directory: project.rootPath,
reason: "no_active_workspaces",
});
}
}
}),
);
// 3. Reconcile git metadata for active projects whose directories still exist
const projectsToReconcile = activeProjects.filter((project) => {

View File

@@ -720,28 +720,24 @@ async function listChildDirectories(input: {
const dirents = await readdir(input.directory, { withFileTypes: true }).catch(
() => [] as Dirent[],
);
const entries: ChildDirectoryEntry[] = [];
for (const dirent of dirents) {
if (isHiddenDirectoryName(dirent.name)) {
continue;
}
if (!dirent.isDirectory() && !dirent.isSymbolicLink()) {
continue;
}
const candidatePath = path.join(input.directory, dirent.name);
const absolutePath = await resolveDirectoryCandidate({
candidatePath,
dirent,
homeRoot: input.homeRoot,
});
if (!absolutePath) {
continue;
}
entries.push({
name: dirent.name,
absolutePath,
});
}
const candidates = dirents.filter(
(dirent) =>
!isHiddenDirectoryName(dirent.name) && (dirent.isDirectory() || dirent.isSymbolicLink()),
);
const resolved = await Promise.all(
candidates.map(async (dirent) => {
const candidatePath = path.join(input.directory, dirent.name);
const absolutePath = await resolveDirectoryCandidate({
candidatePath,
dirent,
homeRoot: input.homeRoot,
});
return absolutePath ? { name: dirent.name, absolutePath } : null;
}),
);
const entries: ChildDirectoryEntry[] = resolved.filter(
(entry): entry is ChildDirectoryEntry => entry !== null,
);
setDirectoryListCache(input.directory, {
expiresAt: now + DIRECTORY_LIST_CACHE_TTL_MS,