mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-21 00:59:11 +00:00
* fix: capture head revision atomically with atext to prevent mismatched apply When constructing CLIENT_VARS, pad.atext was captured at one point but pad.getHeadRevisionNumber() was called later. If concurrent edits advanced the revision between these two reads, the client received initialAttributedText from rev N but rev=N+3, causing "mismatched apply" errors when the next changeset arrived (expecting rev N+3 text). Now captures headRev at the same time as atext and uses the captured value consistently in CLIENT_VARS and sessionInfo. Fixes #4040 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: flush missed revisions after socket joins pad room During handleClientReady(), the server awaits the clientVars hook before socket.join(). Any revisions appended during that await window are broadcast to existing room members but the connecting socket misses them. Call updatePadClients(pad) after joining to flush any such revisions. Also adds a regression test that injects a slow clientVars hook and verifies the connecting client receives catch-up changesets for edits that occurred during the hook await window. Fixes #4040 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: fix race condition in clientVars hook test Listen for messages during handshake to avoid missing NEW_CHANGES that arrive before the explicit waitForSocketEvent listener is attached. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: initialize sessionInfo.time before catch-up updatePadClients The catch-up updatePadClients() call introduced in this PR could send NEW_CHANGES with timeDelta=NaN because sessionInfo.time was never set for new sessions. NaN poisons the client-side broadcast/timeslider currentTime tracking. Initialize sessionInfo.time to the timestamp of the snapshot revision before the catch-up flush, with a fallback to Date.now() if the revision date is unavailable. Also strengthens the regression tests: - Validate that initialAttributedText matches the pad AText at the EXACT advertised rev (not just the latest pad text), using pad.getInternalRevisionAText(rev). - Add a load test that hammers the pad with concurrent edits while multiple clients connect, asserting CLIENT_VARS consistency under the exact race condition the fix is targeting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: replace open-ended load loop with bounded mid-handshake edit The previous load test ran 'while (!stopLoad) await pad.setText(...)' in the background while the test connected clients. This saturated ueberDB's write queue and on shutdown the queued writes never drained, hanging the mocha process for the full 6h GitHub Actions job timeout. Replace it with a bounded approach: a clientVars hook lands 3 edits mid-handshake (deterministic, no background loop, no shutdown hang). Still exercises the exact race the fix targets — an edit advancing the rev after the atext snapshot but before CLIENT_VARS is sent — and asserts AText / rev consistency via getInternalRevisionAText. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: address remaining Qodo concerns on PR #7480 Addresses Qodo review items 1, 2, 5 from https://github.com/ether/etherpad-lite/issues/comments/4194702740 : - Concern 1 (no loadTesting reproduction test): the suite now toggles settings.loadTest = true in before(), restores in after(). The middle test also pre-populates the pad with 20 revisions before connecting so we genuinely exercise a busy/loaded pad rather than a fresh one. - Concern 2 (no CLIENT_VARS / NEW_CHANGES delay test): the slow clientVars hook in the middle test now has explicit setTimeout delays before AND after the mid-handshake edits, so the race window between atext snapshot and CLIENT_VARS send is observably wide rather than relying on async scheduling alone. The test also collects post-handshake messages and asserts a NEW_CHANGES catch-up arrives when the pad advanced past the advertised rev. - Concern 5 (test doesn't validate rev): both rev-consistency tests use pad.getInternalRevisionAText(advertisedRev) and assert text and attribs match, not just `pad.text() === clientVars.text`. Concerns 3 (connect can miss revisions) and 4 (NaN timeDelta) were already addressed in earlier commits on this branch via the catch-up updatePadClients() call and the sessionInfo.time initialization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| locales | ||
| node | ||
| static | ||
| templates | ||
| tests | ||
| .eslintrc.cjs | ||
| ep.json | ||
| etherpad_icon.svg | ||
| package.json | ||
| playwright.config.ts | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
| web.config | ||
Ignore this file and see the file in the base installation folder