History

Retry desktop project bootstrap when list is transiently empty

Cursor Agent committed 9 months ago

Commit cec360e1 parent 5cda7712 files · +35 −2Browse files

Unified · Split

2 files
  1. apps/web/src/App.tsx +12 −2
  2. scripts/desktop-perf-trace.mjs +23 −0
apps/web/src/App.tsx+12−2
@@ -124,7 +124,7 @@ function AutoProjectBootstrap() { · 123 unmodified lines
124 124
125function DesktopProjectBootstrap() {125function DesktopProjectBootstrap() {
126 const api = useNativeApi();126 const api = useNativeApi();
127 const { dispatch } = useStore();127 const { state, dispatch } = useStore();
128 const bootstrappedRef = useRef(false);128 const bootstrappedRef = useRef(false);
129 129
130 useEffect(() => {130 useEffect(() => {
@@ -138,6 +138,16 @@ function DesktopProjectBootstrap() { · 7 unmodified lines
138 try {138 try {
139 const projects = await api.projects.list();139 const projects = await api.projects.list();
140 if (disposed) return;140 if (disposed) return;
141 if (projects.length === 0 && (state.projects.length > 0 || state.threads.length > 0)) {
142 // Avoid wiping hydrated renderer state if the initial projects.list races
143 // backend startup and transiently returns no projects.
144 retryTimer = setTimeout(() => {
145 retryTimer = null;
146 void attemptBootstrap();
147 }, retryDelayMs);
148 retryDelayMs = Math.min(retryDelayMs * 2, 5_000);
149 return;
150 }
141 dispatch({151 dispatch({
142 type: "SYNC_PROJECTS",152 type: "SYNC_PROJECTS",
143 projects: projects.map((project) => ({153 projects: projects.map((project) => ({
@@ -167,7 +177,7 @@ function DesktopProjectBootstrap() { · 23 unmodified lines
167 clearTimeout(retryTimer);177 clearTimeout(retryTimer);
168 }178 }
169 };179 };
170 }, [api, dispatch]);180 }, [api, dispatch, state.projects.length, state.threads.length]);
171 181
172 return null;182 return null;
173}183}
scripts/desktop-perf-trace.mjs+23−0
@@ -668,6 +668,29 @@ async function main() { · 667 unmodified lines
668 );668 );
669 }669 }
670 670
671 const interactionChecks = [];
672 const threadClicks = Number(donePayload.interactions?.threadClicks ?? 0);
673 const typedChars = Number(donePayload.interactions?.typedChars ?? 0);
674 const terminalOpened = donePayload.interactions?.terminal?.openedByShortcut === true;
675 const terminalCommandTouched = donePayload.interactions?.terminal?.commandFileTouched === true;
676 if (threadClicks <= 0) {
677 interactionChecks.push("thread clicks");
678 }
679 if (typedChars <= 0) {
680 interactionChecks.push("typed chars");
681 }
682 if (!terminalOpened) {
683 interactionChecks.push("terminal shortcut open");
684 }
685 if (!terminalCommandTouched) {
686 interactionChecks.push("terminal command execution");
687 }
688 if (interactionChecks.length > 0) {
689 throw new Error(
690 `Desktop perf automation completed without required scripted interactions: ${interactionChecks.join(", ")}`,
691 );
692 }
693
671 const summary = summarizeTrace(tracePath);694 const summary = summarizeTrace(tracePath);
672 const markdown = createMarkdownSummary({695 const markdown = createMarkdownSummary({
673 tracePath,696 tracePath,