Yield recovery container encoding without changing durable cuts

This commit is contained in:
2026-11-11 04:04:24 +08:00
parent 57dab91a9c
commit b4c40d3087
7 changed files with 195 additions and 18 deletions
+25 -1
View File
@@ -978,10 +978,34 @@ changes still commit in one transaction. No Root is skipped. Reopening validates
headers/sequence, hashes exact Blob bytes, decodes strict UTF-8, checks the decoded
header and then applies later deltas. Future checkpoint versions reject reads
and writes; malformed/tampered data is never treated as an empty document. Legacy
recovery, JSON parse, recovery-image encoding, same-cut retry comparison and
recovery, JSON parse, recovery-image capture, same-cut retry comparison and
individual native operations still have synchronous work; this is not a strict
6ms bound for all storage paths or a disk-space reduction guarantee.
Before Blob serialization, ProjectEngine now awaits cooperative recovery-image
encoding inside its existing ordered Root writer. Private `dataArray` / `dataRecord`
constructors copy and freeze DTO container membership; they do not claim their
children are immutable. Preparation captures each unknown subtree synchronously,
including getters, custom `toJSON`, Dates and external shallow-frozen records.
Previously validated immutable codec facts can be reused. Only then does a
budgeted traversal assemble the owned containers, preserving key order, omitted
values, sparse-array normalization, depth checks and exact UTF-8 byte facts.
The default uses `scheduler.yield()` when available (with its receiver), otherwise
a timer, sharing the 6ms soft budget / 16384-work ceiling. One shared budget spans
nested containers. Public synchronous encoding and recovery/storage formats stay
unchanged; async images receive the same codec ownership seal without a second
full encoding pass.
A yield does not publish or skip a Root. Later edits may publish while encoding
is suspended; the old image still contains its captured state, and the next cut
is saved after it. Request dispatch retains the durable-prefix barrier. Encoding
or scheduling failures retain the pending Root for retry and produce no partial
storage commit. Initial DTO membership copying, synchronous preparation, unknown
subtrees, first-time immutable normalization and individual scalar operations
remain synchronous. This is partial time slicing, not a strict whole-Root latency
bound. In particular, large history/import objects still need producer ownership
review before their internal loops can safely be deferred.
A blocked schema upgrade retires its pending open. If the old connection closes
later, that abandoned request aborts in `onupgradeneeded` rather than silently
upgrading after rejection. A fresh adapter can retry once the blocking client has