[Website] Prevent stale thumbnail captures from overwriting saved metadata - #4167
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Prevents stale or cancelled thumbnail captures and background OPFS syncs from overwriting current site metadata by validating capture recency, abort state, and client ownership before persisting.
Changes:
- Add per-site capture tokens + Redux client ownership checks before writing thumbnail metadata.
- Plumb
getState/signalinto thumbnail capture and gate capture on initial OPFS sync success (returning an explicit boolean). - Add focused Vitest coverage for out-of-order captures, client replacement/abort, and OPFS copy failure behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/playground/website/src/lib/state/redux/persist-temporary-site.ts | Passes getState through to enable ownership checks during persistence. |
| packages/playground/website/src/lib/state/redux/capture-site-thumbnail.ts | Adds capture tokening, abort checks, and Redux client ownership validation before persisting thumbnails. |
| packages/playground/website/src/lib/state/redux/capture-site-thumbnail.spec.ts | Adds tests for overlapping captures, client replacement, and abort behavior. |
| packages/playground/website/src/lib/state/redux/boot-site-client.ts | Makes initial OPFS background sync return success/failure and only captures thumbnails on success. |
| packages/playground/website/src/lib/state/redux/boot-site-client.spec.ts | Adds a regression test ensuring thumbnail capture does not run when initial OPFS copy fails. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
#4142 bounds page loading and gives
modern-screenshotthree seconds to render. That prevents one capture from hanging forever. It does not order results.A saved Playground keeps its site metadata in
wp-runtime.jsoninside that site's OPFS directory. Every open tab has its own Redux copy of the record, while all tabs write to the same OPFS file. #4152 made those writes atomic:OpfsSiteStorage.update()takes an origin-wide Web Lock keyed by site slug, reads the latest record, merges only the supplied patch, and writes it back. A thumbnail update therefore cannot restore an old name or runtime setting from that tab's Redux state.The lock only serializes writes. It cannot know when
captureSiteThumbnail()started. An old iframe can finish after a newer capture and then acquire the lock with a valid{ thumbnail }patch, replacing the newer image.This change
Before passing a thumbnail patch to
OpfsSiteStorage.update(), this PR requires that the request is still the latest one for that site in the current tab, its boot signal has not been aborted, and Redux still owns the client that started it.The initial OPFS copy now returns its own success result. Thumbnail capture no longer infers that copy's outcome from
initialOpfsSyncPending, whose value can change independently.Two live tabs remain valid writers. Their per-site Web Lock serializes thumbnail updates, and the last completed live-tab write wins.
Testing
The focused tests resolve captures out of order, replace and abort clients, and fail an initial OPFS copy after the metadata flag changes.