Skip to content

fix(chrome-extension): fix crash when generating script after stop recording#2172

Merged
quanru merged 3 commits intomainfrom
fix/chrome-extension-stop-recording-crash
Mar 18, 2026
Merged

fix(chrome-extension): fix crash when generating script after stop recording#2172
quanru merged 3 commits intomainfrom
fix/chrome-extension-stop-recording-crash

Conversation

@quanru
Copy link
Collaborator

@quanru quanru commented Mar 18, 2026

Summary

Changes

Issue Fix
persistEventToSession duplicated addEvent persistence Removed — addEvent already writes to IndexedDB
addEvent wrote full events array to IndexedDB on every event (O(n²)) Debounced writes with 2s delay, flush on stop/emergency
updateSession called getAllSessions() after every update, reloading all screenshots from IndexedDB Update in-memory state directly, only reload from DB on cache miss
generateElementDescriptions ran all AI calls in parallel via Promise.all Batch with max 3 concurrent calls to limit peak memory
Logger calls passed full events arrays (with base64 screenshots) in yamlGenerator.ts, ProgressModal.tsx, useRecordingControl.ts, store.tsx Log only eventsCount
saveEventsToStorage became dead code after removing duplicate persistence Deleted
Commented-out code // const finalEvents = [...] Deleted

Validation

  • pnpm run lint passes

Test plan

  • Manual: record 20+ interactions (~2 min), click stop, verify no crash during script generation
  • Manual: verify generated YAML/Playwright code is correct after recording
  • Manual: verify events survive page navigation during recording (debounce flush on stop)
  • Manual: close extension during recording, reopen — verify events are recovered

🤖 Generated with Claude Code

…cording

Multiple memory issues caused the extension to crash during script
generation after clicking stop:

- Remove duplicate persistEventToSession (addEvent already persists)
- Debounce IndexedDB writes in addEvent to avoid O(n²) IO
- Avoid reloading all sessions from IndexedDB after every updateSession
- Limit concurrent AI description calls to 3 to reduce peak memory
- Remove full events array (with base64 screenshots) from all logger calls
- Delete dead saveEventsToStorage code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 18, 2026

Deploying midscene with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5645be6
Status: ✅  Deploy successful!
Preview URL: https://961c4044.midscene.pages.dev
Branch Preview URL: https://fix-chrome-extension-stop-re.midscene.pages.dev

View logs

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e9b7869dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 353 to 359
if (state.isRecording) {
// Debounce IndexedDB writes to avoid O(n²) IO.
// In-memory state is updated immediately; DB write is batched.
const sessionId = useRecordingSessionStore.getState().currentSessionId;
if (sessionId) {
await dbManager.updateSession(sessionId, {
events: newEvents,
updatedAt: Date.now(),
});
scheduleSessionPersist(sessionId, newEvents);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep recording-events updated during active recording

Because useRecordStore.initialize() still restores in-progress recordings from dbManager.getRecordingEvents() in store.tsx, and Recorder reapplies that recovered data on reopen in extension/recorder/index.tsx, removing the per-event write here breaks the existing crash/reload recovery path. If the popup refreshes or crashes mid-recording, any events captured since the last debounced session flush will reopen as an empty or stale timeline instead of the live recording the user just made.

Useful? React with 👍 / 👎.

Comment on lines +290 to +294
pendingSessionPersist = { sessionId, events };
if (sessionPersistTimer) {
clearTimeout(sessionPersistTimer);
}
sessionPersistTimer = setTimeout(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh the debounced session snapshot after later event updates

pendingSessionPersist now captures the event array exactly as it looked when addEvent ran, but updateEvent and setEvents still persist newer versions of the same session immediately. During recording, optimizeEvent() issues asynchronous updateEvent calls after addEvent (first the loading placeholder, then the final description/screenshot), so the 2s timer can write the older snapshot back to IndexedDB and silently revert those later mutations. Users who reopen the popup or read the session from storage before stopping can therefore see placeholder descriptions or otherwise stale event data.

Useful? React with 👍 / 👎.

quanru and others added 2 commits March 18, 2026 11:44
Tests cover:
- Debounced persistence: rapid writes coalesce into single DB call
- Flush behavior: explicit flush writes immediately and clears state
- In-memory session update: avoids full DB reload
- Batched concurrency: peak concurrent AI calls bounded by limit
- Navigation/scroll pre-processing: skips concurrency slots
- Logger sanitization: events arrays never passed to loggers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ests

Adds vitest to chrome-extension devDependencies and a "test" script so
unit tests can be run via `npx nx test chrome-extension`. Not added to
the root `pnpm test` yet because the pre-existing event-memory-stress
test is flaky (GC-dependent heap measurements).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@quanru quanru merged commit 8bfdb09 into main Mar 18, 2026
11 checks passed
@quanru quanru deleted the fix/chrome-extension-stop-recording-crash branch March 18, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants