Summary
After a crash/restart, Volume.getTree(name, false) (and step-based MVCC visibility checks generally) can return a stale answer until background maintenance happens to run. Recovery itself completes synchronously inside Persistit.initialize(), but two maintenance tasks are asynchronous after it:
- the
TransactionIndex active-transaction-cache updater thread;
CleanupManager's pruneTimelyResources(), which fires only on its poll timer (default ~1 s).
Until those run, residual tree-version state from before the crash can leak into step-based visibility — e.g. a tree created at transaction step 1 is reported visible at step 0.
How it was found
TreeTransactionalLifetimeTest.createRemoveByStep failed intermittently on CI (ComparisonFailure: expected:<0[],...> but was:<0[:],...> — a tree visible at step 0 that should not be). The test-side fix (#260) forces getTransactionIndex().updateActiveTransactionCache() + pruneTimelyResources() after initialize(), mirroring what sibling tests in the class already do before asserting.
Raised during review of #257: an application calling Volume.getTree(name, false) shortly after initialize() hits the same window — it has no way to know it must wait for internal maintenance timers.
Repro sketch
// createRemoveByStepHelper-style sequence:
txn.begin();
txn.setStep(1);
volume.getTree(treeName, true); // create at step 1
...
persistit.checkpoint();
persistit.crash(); // or close()
persistit = new Persistit(config);
persistit.initialize();
// Immediately after initialize(), on a step-0 view:
volume.getTree(treeName, false); // may report the tree visible at step 0
// After updateActiveTransactionCache() + pruneTimelyResources(): correct answer
Intermittent — depends on whether the CleanupManager timer fired between restart and the query.
Question
Should initialize() settle this state before returning (update the active-transaction cache and prune timely resources at the end of recovery), so applications get correct step visibility immediately rather than depending on an internal timer? The cost is bounded (one ATC update plus one prune pass at startup).
Refs: #257 (review discussion), #260 (test-side workaround).
Summary
After a crash/restart,
Volume.getTree(name, false)(and step-based MVCC visibility checks generally) can return a stale answer until background maintenance happens to run. Recovery itself completes synchronously insidePersistit.initialize(), but two maintenance tasks are asynchronous after it:TransactionIndexactive-transaction-cache updater thread;CleanupManager'spruneTimelyResources(), which fires only on its poll timer (default ~1 s).Until those run, residual tree-version state from before the crash can leak into step-based visibility — e.g. a tree created at transaction step 1 is reported visible at step 0.
How it was found
TreeTransactionalLifetimeTest.createRemoveByStepfailed intermittently on CI (ComparisonFailure: expected:<0[],...> but was:<0[:],...>— a tree visible at step 0 that should not be). The test-side fix (#260) forcesgetTransactionIndex().updateActiveTransactionCache()+pruneTimelyResources()afterinitialize(), mirroring what sibling tests in the class already do before asserting.Raised during review of #257: an application calling
Volume.getTree(name, false)shortly afterinitialize()hits the same window — it has no way to know it must wait for internal maintenance timers.Repro sketch
Intermittent — depends on whether the CleanupManager timer fired between restart and the query.
Question
Should
initialize()settle this state before returning (update the active-transaction cache and prune timely resources at the end of recovery), so applications get correct step visibility immediately rather than depending on an internal timer? The cost is bounded (one ATC update plus one prune pass at startup).Refs: #257 (review discussion), #260 (test-side workaround).