Repository navigation
fix(autobiographical): a removal or a view filter no longer halts compression; the debt report says when the chain-break guard does - #423
Open
nissa-seru wants to merge 1 commit into
Conversation
…pression; the debt report says when the chain-break guard does rebuildChunks' fail-closed guard counted a chunk record as orphaned when none of its messages was in the strategy's view, and halted all compression once more than half of at least three records were. Its case is a store whose messages were renumbered: records naming ids the store never held. A host's removal (removeMessage, removeMessages, removeBodyGroup, an operator's suppress) or a viewFilter hiding old history produced the same count from ids the store did hold, so compression of every later message stopped for good, across reopens, while getCompressionDebt() read healthy with nothing pending. - MessageStore.held(id): whether the store ever held a message under an id, on any of its branches: true for a live message and for one removed since (removal is a Redact state operation; the message's append record stays in the chronicle, compaction included), false for an id that names no Append to this store's messages slot. MessageStoreView gains it as optional held?; filterMessageStoreView passes it through unfiltered (a hidden message is held) and mergeMessageStoreViews answers when every source can. - The guard counts a record with no message in the view only when the store can't show it held any of the record's ids; a view without held counts as before. The answer is memoized per record for the load, except a negative over a record number the store hasn't used yet, the only kind of id a later write can give a message. - While the guard holds, getCompressionDebt() reads critical, with error and failure: 'chunk-records', an addition to failure's union; if the quarantine ledger can't be read then too, error carries both messages. Requirements, each pinned in test/removal-guard.test.ts: 1. Removing the messages of more than half the chunk records (3 of 5 one by one; 2 of 2 as a range) leaves later messages compressing. 2. A store reopened under a viewFilter hiding the messages of 5 of 8 records compresses later messages. 3. A store whose records a removal emptied before it closed compresses later messages after it reopens. 4. Records each naming a removed message beside ids the store never held leave later messages compressing; records naming numbers the store gives messages later in the same load stop halting compression once it has. 5. Records naming ids the store never held, of another form or record numbers it never assigned, still halt compression, and the debt report reads critical with failure 'chunk-records', carrying the ledger's error too when the ledger can't be read. 6. held answers as above, through filtered and merged views, after compactState, after a reopen and on a fork.
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.
With this change, removing the messages behind most of
AutobiographicalStrategy's chunk records, or hiding them with aviewFilter, no longer stops compression of the messages that follow. While the chain-break guard does stop it,getCompressionDebt()readscriticaland says why. The guard now counts a chunk record against the store only when the store can't show it ever held any of the record's message ids. It does that with a newMessageStore.held(id). Records naming ids the store never held, the case the guard exists for, still stop compression.Fixes #421.
@antra-tess, we're asking you to review this before it's merged, since it changes whether a resident's memory goes on compressing after a removal or under a
viewFilter, and whatgetCompressionDebt()reports while the guard stops it.Problem
rebuildChunks' guard (src/strategies/autobiographical.ts:17901–17920atfb4cf1046) counted a chunk record as orphaned when none of its messages was in the strategy's view. Once at least three records existed and more than half were orphaned, no new chunk formed. A removal (removeMessage,removeMessages) or aviewFilterhiding old history gives that count from ids the store did hold. #421 shows it by a test file it carries, atfb4cf1046, on Linux with Node 24.22.2. These are its lines after a removal of the messages behind 5 of 8 records, and after a reopen under a filter hiding them:Changes
MessageStore.held(id)(src/message-store.ts:1175) answers whether the store ever held a message under an id, on any of its branches. It answers true for a live message and for one removed since, and false for an id that names noAppendto this store's messages state, including one chronicle refuses as a record id.MessageStoreViewgains it as the optionalheld?(src/types/strategy.ts:36).filterMessageStoreViewpasses it through, so a filtered view answers for the messages it hides (src/message-view.ts:62).mergeMessageStoreViewsanswers when every source can (:152).src/strategies/autobiographical.ts:17848,:17925). A view withoutheldcounts as before. The answer is kept per record for the load, except a negative over a record number the store hasn't used yet, which a later write can give a message (:17857).getCompressionDebt(), while the guard holds, readscritical, withfailure: 'chunk-records', an addition tofailure's union, and anerrorsaying what happened, withCause:,Effect:andFix:lines (:237,:8549). When the quarantine ledger can't be read at the same time,errorholds both messages.FAIL-CLOSEDlog line and the guard's comments now say the records name ids the store can't show it ever held.test/removal-guard.test.tsis new, and one comment intest/chunk-persistence.test.tschanges.changelog.d/removal-keeps-compressing.fixed.mdandchangelog.d/removal-keeps-compressing.added.md.In all, 8 files, +413 −14. Merged at 19:04 UTC on October 30 with each of the 13 open pull requests' heads, this head conflicts where
maindoes, except with #350 (below).With #350
@tel-0s, by
git merge-treeat 19:04 UTC on October 30, your #350 at4d04b425aemerges intomainfb4cf1046cleanly and conflicts with this head insrc/types/strategy.ts, where each adds an optional method toMessageStoreViewaftersequenceOf: this headheld?and yourspositionOf?. Both can stand.Tests
On Linux with Node 24.22.2, after
npm cifrom the lockfile, which pins@animalabs/membrane0.9.0 and@animalabs/chronicle0.5.1. Each run is in a clean checkout of the commit named, with a file added where one is named.c1dcc0fd0:npm run buildexits 0.test/removal-guard.test.tspasses 11 of 11, andtest/chunk-persistence.test.ts6 of 6, its chain-break test unchanged.fb4cf1046'ssrcand this head's tests,npm ciandnpm run buildeach exit 2 on 14 type errors, all at the tests' calls ofheld, and the tests then run from whattscemitted. All 11 ofremoval-guard's tests fail. Five removal and filter cases fail at "an L1 covers messages added after it". The numbers-given-later case and the two never-held cases fail at the debt report, which readshealthywhere they expectcritical, and the ledger case where it readsunknown.held's two tests fail wherefb4cf1046has noheld.FAIL-CLOSEDline:removal-guardpins:viewFilterhiding the messages of 5 of 8 records compresses later messages;critical, carrying the ledger's error too when the ledger can't be read;heldanswers as above, through filtered and merged views, aftercompactState, after a reopen and on a fork.The whole suite runs in this pull request's CI.
Not verified
heldcosts on a large store. An emptied record's check decodes one removed message's record per load. No timing of it here ran on an unloaded machine.6dfbd9c83c,strategyMessageViewwraps the strategy's view inaudienceMessageStoreView(src/context-manager.ts:600), whose view has noheld(src/message-view.ts:168). Merged with it, an earlier version of this change, never pushed, failed its five removal and filter tests at "an L1 covers messages added after it". This head differs from that version in two tests and one rule for what the guard keeps per record, and wasn't run merged with feat(view): blocks with an audience, and the reader a manager compiles for #364's head.heldthrough. No run here merged them.changelog.d/removal-keeps-compressing.fixed.mdandchangelog.d/removal-keeps-compressing.added.md.Fern-2426 found the defect. Cedric-2315 made the change and measured where the guard trips, Alfred-2570 checked that each part is needed, and Oscar-1005 placed it. Lottie-2661 ran the tests at this head and wrote this description.