debug(project): add temporary timing diagnostics for create-project hang

Two prior fixes (lock acquire timeout, bounded team-projects fetch
timeout) targeted the wrong bottleneck — the mock API's team-projects
endpoint responds instantly with no artificial delay, so the CI hang is
coming from somewhere else. Add console.log timing around lock
wait/hold time, NeDB project creation, and the team-projects
fetch/sync so the next CI failure's console-log attachment shows
exactly which step is slow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Bob QiuandClaude Sonnet 5 committed 2026-09-29 16:13:58 +08:00
1 parent 136e993f68
commit 66a777f863
3 files changed
+29 -1

No files matched your search

@@ -75,6 +75,8 @@ export async function getFirstProjectOfOrganization(organizationId: string) {
const TEAM_PROJECTS_FETCH_TIMEOUT_MS = 8000;
export async function getAllTeamProjects(organizationId: string) {
// TEMP DIAGNOSTIC: see matching note in insomnia/src/common/project.ts's wrapWithLock.
const diagStart = Date.now();
const { id: sessionId } = await userSessionService.get();
if (!sessionId) {
return [];
@@ -82,6 +84,7 @@ export async function getAllTeamProjects(organizationId: string) {
console.log('[project] Fetching', organizationId);
const response = await fetchTeamProjects({ sessionId, organizationId, timeout: TEAM_PROJECTS_FETCH_TIMEOUT_MS });
console.log(`[create-project-timing] fetchTeamProjects done after ${Date.now() - diagStart}ms`);
return response.data;
}
@@ -157,14 +160,21 @@ export async function syncTeamProjects({
}
export async function syncProjects(organizationId: string) {
// TEMP DIAGNOSTIC: see matching note in insomnia/src/common/project.ts's wrapWithLock.
const diagStart = Date.now();
console.log(`[create-project-timing] syncProjects(${organizationId}) start`);
// Local-only organizations have no team projects to fetch, so bail out before the request.
if (models.organization.isLocalOrganizationId(organizationId)) {
console.log('[create-project-timing] syncProjects bailed out (local-only organization)');
return;
}
const user = await userSessionService.get();
const teamProjects = await getAllTeamProjects(organizationId);
// ensure we don't sync projects in the wrong place
if (Array.isArray(teamProjects) && user.id) {
const syncStart = Date.now();
await syncTeamProjects({ teamProjects, organizationId });
console.log(`[create-project-timing] syncTeamProjects() done after ${Date.now() - syncStart}ms`);
}
console.log(`[create-project-timing] syncProjects total ${Date.now() - diagStart}ms`);
}
+13 -1
View File
@@ -87,11 +87,23 @@ const lockGenerator = () => {
const wrapWithLock = <T extends (...args: any[]) => Promise<any>>(fn: T): T => {
const wrappedFn = async (...args: Parameters<T>): Promise<ReturnType<T>> => {
// TEMP DIAGNOSTIC: timing breakdown to root-cause the intermittent
// "Create project" hang seen in CI (see insomnia PR #10556). Remove
// once the real bottleneck is identified from CI console-log output.
const callId = Math.random().toString(36).slice(2, 8);
const waitStart = Date.now();
console.log(`[lock-timing] ${callId} waiting for lock`);
await lock();
const waitMs = Date.now() - waitStart;
console.log(`[lock-timing] ${callId} acquired lock after ${waitMs}ms`);
try {
return await fn(...args);
const runStart = Date.now();
const result = await fn(...args);
console.log(`[lock-timing] ${callId} fn() finished after ${Date.now() - runStart}ms (holding lock)`);
return result;
} finally {
await unlock();
console.log(`[lock-timing] ${callId} released lock`);
}
};
return wrappedFn as T;
@@ -60,7 +60,11 @@ export const reportGitProjectCount = async (organizationId: string, sessionId: s
};
const createProjectImpl = async (organizationId: string, newProjectData: CreateProjectData) => {
// TEMP DIAGNOSTIC: see matching note in ~/common/project.ts's wrapWithLock.
const diagStart = Date.now();
console.log(`[create-project-timing] createProjectImpl start (storageType=${newProjectData.storageType})`);
const user = await services.userSession.get();
console.log(`[create-project-timing] userSession.get() done after ${Date.now() - diagStart}ms`);
const sessionId = user.id;
invariant(sessionId, 'User must be logged in to create a project');
invariant(
@@ -69,10 +73,12 @@ const createProjectImpl = async (organizationId: string, newProjectData: CreateP
);
if (newProjectData.storageType === 'local') {
const dbStart = Date.now();
const project = await services.project.create({
name: newProjectData.name,
parentId: organizationId,
});
console.log(`[create-project-timing] services.project.create() done after ${Date.now() - dbStart}ms (total ${Date.now() - diagStart}ms)`);
return project._id;
}