perf(app): fetch project and workspace directories concurrently (#7242)

This commit is contained in:
Mohamed Boudra
2026-10-17 22:06:09 +07:00
committed by GitHub
parent 86ab49153a
commit 86817a24fc
2 changed files with 72 additions and 10 deletions
@@ -1207,6 +1207,60 @@ describe("DirectorySync session readiness", () => {
directory.dispose();
});
it.each(["projects", "workspaces"] as const)(
"requests projects and workspaces together and commits once when %s responds first",
async (firstResponse) => {
const serverId = `parallel-directory-${firstResponse}`;
const { client, directory } = createDirectory(serverId);
const store = useSessionStore.getState();
store.initializeSession(serverId, client as unknown as DaemonClient, 1);
store.updateSessionServerInfo(serverId, {
serverId,
hostname: null,
version: "test",
features: { workspaceMultiplicity: true, projectList: true },
});
const releaseProjects = client.holdProjectFetch();
const releaseWorkspaces = client.holdWorkspaceFetch();
const project = {
projectId: "parallel-project",
projectDisplayName: "Project baseline",
projectRootPath: "/repo/parallel",
projectKind: "git" as const,
};
const projects: ProjectListResult = { requestId: "projects", projects: [project] };
const workspaces: WorkspaceFetchResult = {
requestId: "workspaces",
entries: [createWorkspaceEntry("parallel-workspace")],
emptyProjects: [{ ...project, projectDisplayName: "Newer workspace overlay" }],
pageInfo: { hasMore: false, nextCursor: null, prevCursor: null },
};
const refresh = directory.refreshWorkspaces();
try {
await expect.poll(() => client.listProjectsCalls).toBe(1);
await expect.poll(() => client.fetchWorkspacesCalls).toBe(1);
if (firstResponse === "projects") releaseProjects(projects);
else releaseWorkspaces(workspaces);
await new Promise<void>((resolve) => setTimeout(resolve, 0));
expect(useSessionStore.getState().sessions[serverId].workspaces.size).toBe(0);
expect(useSessionStore.getState().sessions[serverId].projects.size).toBe(0);
releaseProjects(projects);
releaseWorkspaces(workspaces);
await refresh;
const session = useSessionStore.getState().sessions[serverId];
expect(session.workspaces.has("parallel-workspace")).toBe(true);
expect(session.projects.get(project.projectId)?.projectDisplayName).toBe(
"Newer workspace overlay",
);
} finally {
releaseProjects(projects);
releaseWorkspaces(workspaces);
await refresh;
directory.dispose();
}
},
);
it("keeps the accepted baseline when an old connection finishes its workspace request", async () => {
const serverId = "superseded-workspace-baseline";
const { client, directory } = createDirectory(serverId);
@@ -563,16 +563,20 @@ export class DirectorySync {
const serverInfo = useSessionStore.getState().sessions[this.serverId]?.serverInfo;
const supportsProjectList = serverInfo?.features?.projectList === true;
const supportsDirectorySync = serverInfo?.features?.directorySync === true;
if (supportsProjectList) {
await this.fetchProjectSnapshot(client, source, transaction, supportsDirectorySync);
}
await this.fetchWorkspaceSnapshot(
client,
source,
transaction,
input?.subscribe === true,
supportsDirectorySync,
);
const projectsReady = supportsProjectList
? this.fetchProjectSnapshot(client, source, transaction, supportsDirectorySync)
: Promise.resolve();
await Promise.all([
projectsReady,
this.fetchWorkspaceSnapshot(
client,
source,
transaction,
input?.subscribe === true,
supportsDirectorySync,
projectsReady,
),
]);
if (!supportsProjectList) {
this.buildLegacyProjectSnapshot(transaction.snapshot);
(transaction.snapshot.syncModes ??= {}).projects =
@@ -592,6 +596,7 @@ export class DirectorySync {
transaction: DirectoryTransaction<WorkspaceRefreshSnapshot, WorkspaceDirectoryDelta>,
initialSubscribe: boolean,
supportsDirectorySync: boolean,
projectsReady: Promise<void>,
): Promise<void> {
let cursor: string | null = null;
let subscribe = initialSubscribe;
@@ -618,6 +623,9 @@ export class DirectorySync {
});
payload = await subscription.ready;
} else payload = await client.fetchWorkspaces(query);
// Fetch both directories together, but apply the project baseline before the
// workspace page's empty-project overlays, regardless of response order.
await projectsReady;
this.assertWorkspaceTransactionCurrent(client, source, transaction);
applyWorkspaceSnapshotPage(transaction.snapshot, payload, cursor === null);
if (!payload.pageInfo.hasMore || !payload.pageInfo.nextCursor) return;