fix: skip stale da-admin reload when client pushes Y.js state after reconnect#136
Merged
fix: skip stale da-admin reload when client pushes Y.js state after reconnect#136
Conversation
…econnect When a debounced PUT to da-admin returns 412, the collab DO clears its worker storage and closes all WebSocket connections. On reconnect a fresh bindState runs and, finding no worker storage, schedules a 1-second deferred reload from da-admin. Because the debounce (2 s) fires after the timeout (1 s), the client's latest changes (e.g. a newly uploaded image URL) had not yet been written to da-admin, so the reload was overwriting them with a stale snapshot. Fix: snapshot Y.encodeStateVector(ydoc) before the timeout. At fire time, if the state vector has advanced (the client already synced its authoritative state via Y.js), the da-admin reload is skipped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bosschaert
approved these changes
May 5, 2026
adobe-bot
pushed a commit
that referenced
this pull request
May 5, 2026
## [1.2.2](v1.2.1...v1.2.2) (2026-05-05) ### Bug Fixes * skip stale da-admin reload when client pushes Y.js state after reconnect ([#136](#136)) ([a8ddc23](a8ddc23))
Collaborator
|
🎉 This PR is included in version 1.2.2 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
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.
User scenario
A user uploads several images one after another in the DA editor. After uploading the 4th image, the real image briefly appears then reverts to the FPO/upload-icon placeholder (
/blocks/edit/img/fpo.svg).The same issue was reported for a single image upload by a second user.
Root cause
The chain of events that triggers the regression:
da-liveinserts a temporary FPO placeholder, sends the file to da-admin, then replaces the FPO with the real image URL.updateHandlerdebounces (2 s, max 10 s) saving the updated doc state to da-admin.da-collabreacts by clearing its worker storage (storage.deleteAll()) and closing all WebSocket connections.bindStateruns and, finding empty worker storage, fetches the current document from da-admin. Because the 2 s debounce has not yet flushed, da-admin still holds the stale snapshot (image URL not yet written).bindStateschedules a 1-second deferred reload to avoid a race with Y.js sync. After 1 s the doc is overwritten with the stale snapshot, replacing the real image URL with the FPO placeholder.Fix
Snapshot
Y.encodeStateVector(ydoc)before the 1-second timeout. At fire time, if the state vector has advanced (the reconnected client already pushed its authoritative Y.js state), the da-admin reload is skipped — the client state takes precedence over the stale snapshot.Related PRs
Tests
Test bindState skips da-admin reload when client sends Y.js update before timeoutTest bindState still reloads from da-admin when no client update arrives before timeout