Writes the edits an editing session holds and no draft does — on every change, on the way out of the editor, and before a reopened session is moved off its draft.
Why the session, and not the LiveView
An edit lands in the session first: MishkaCmsBuilder.EditorSession stores it in ETS, where it
outlives the LiveView that made it. It reaches a draft row a moment later, when the chrome writes
it — and that moment used to belong to the LiveView. The write ran in a task linked to it, and
what the write settled (the draft it made, the revision it carried) was recorded by the LiveView
when the answer came back. A tab closed, a page left or a socket dropped inside that moment took
the write down with the LiveView, and the next visit detached the session from its draft and threw
the unwritten edit away with the tree it replaced. A drop followed by closing the tab at once was
enough.
So a write here:
- runs in a process of its own under
MishkaCmsCore.Runtime.TaskSupervisor, linked to nobody, so the caller exiting does not stop it; - records what it wrote on the session itself —
EditorSession.mark_saved/2with the draft and the revision it serialized — so the session knows its draft even when no LiveView is left to hear the answer; - waits its turn: one write per session at a time, and each reads the session as stored when its turn comes. A write asked for on the way out therefore follows the one already running and writes only what that one did not carry, and an older document never lands over a newer one.
A session with nothing unwritten is left alone, so asking costs one ETS read.
Summary
Functions
Writes token's session with write when it holds edits no draft has, and marks it saved as of
the revision written.
Types
@type outcome() :: {:ok, struct(), MishkaCmsBuilder.EditorSession.t()} | {:clean, MishkaCmsBuilder.EditorSession.t()} | :running | :error | term()
What a keep did: wrote, found nothing to write, or did not write.
Functions
@spec keep( String.t(), (MishkaCmsBuilder.EditorSession.t() -> {:ok, struct()} | term()), timeout() ) :: outcome()
Writes token's session with write when it holds edits no draft has, and marks it saved as of
the revision written.
write receives the session as stored when this write's turn comes, and answers {:ok, draft} for
a draft it wrote; anything else is a write that did not happen and is answered as it came.
Answers {:ok, draft, session} with the session as marked, {:clean, session} when there was
nothing to write, :error when there is no such session, {:error, {:exit, reason}} when the write
crashed, and :running when timeout passed first — the write then goes on without the caller,
and still records what it wrote.