[ZEPPELIN-6697] Prevent live NOTE_UPDATED from mutating revision snapshots - #5468
Conversation
updateNote() broadcasts NOTE_UPDATED to every socket associated with the note, and a socket that navigated to a saved revision keeps that association. The Angular handler applied the payload unconditionally, so a look and feel change made on the live note rewrote the historical snapshot the revision view was showing. Guard the handler with revisionView, which is what the paragraph handlers in the same component already do, and what ZEPPELIN-2452 did for the classic UI before the guard was only partly carried over. The new Playwright spec opens a note, saves a revision, enters it on the same socket, then changes look and feel from an independent browser context. It waits until the revision view has actually received NOTE_UPDATED before asserting, so it fails without this guard rather than passing by checking too early. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
voidmatcha
left a comment
There was a problem hiding this comment.
Ignoring NOTE_UPDATED while viewing a revision looks reasonable to me.
I noticed two things in the test. The current CI uses VFS storage, which does not support revisions, so the test fails while waiting for the commit button. Also, livePage is the page making the change, so checking its value alone does not verify that a live viewer received the broadcast.
I prepared a follow-up commit that runs this test separately with Git storage and checks the update in another live viewer that makes no local edits. Feel free to use it as a reference or cherry-pick it if helpful.
voidmatcha
left a comment
There was a problem hiding this comment.
LGTM 👍
One minor thing: skipWhenAuthenticationIsStillRequired is missing from this spec's guard (still present in collaborative-mode.spec.ts etc.). Not blocking, worth cleaning up later.
|
Merged into master (5e36932). |
What is this PR for?
NotebookServer.updateNote()broadcastsNOTE_UPDATEDto every socket associated with the note, and a socket that navigates to a saved revision keeps that association. The Angular handler applied the payload unconditionally:So changing the live note's look and feel from another browser rewrote the snapshot the revision view was showing.
The guard already exists elsewhere in the same component —
removeParagraph,addParagraphandmoveParagraphall checkrevisionView, and ZEPPELIN-2452 added the same check to the classic UI. It was only partly carried over during the migration, andnoteUpdatedwas the one left out. This adds it there.Per the issue, this stays out of
noteId, request correlation and socket generation: the reproduction only proves a revision-isolation defect, and nothing here required a wire change. The Shared Notebook Core revision adapter is not covered yet, since that slice has not landed.What type of PR is it?
Bug Fix
Todos
noteUpdatedwithrevisionViewWhat is the Jira issue?
How should this be tested?
New spec
e2e/tests/notebook/revision/revision-isolation.spec.tsopens a note, saves a revision, enters it on the same socket, then changes look and feel from an independent browser context. It asserts the live follower applies the update, and that the revision view still shows the value it was saved with.Result:
2 passed (22.5s).--reporter=listis worth passing locally, since the configured HTML reporter opens a report server afterwards and the command does not return on its own.Reverting only the guard makes it fail, so it does catch the defect rather than passing by construction:
Two details the spec depends on, both found the hard way:
renameNote, which answers withbroadcastNote()(OP.NOTE) and never emitsNOTE_UPDATED.setLookAndFeel()is what callsupdateNote(), which is why the issue names it in the reproduction.Receive: NOTE_UPDATED, then asserts.Screenshots (if appropriate)
N/A
Questions: