fix(store): rebase ages per-entry so non-idle flush doesn't under-count
LogStore::new folded `(now - last_clock)` into every entry's age_ms, but age_ms is persisted at INSERT time and stored_at was never caught up at flush. So an observation inserted before the last flush lost the `last_flush - insert_time` after restart (a store that was non-idle between insert and flush reported an age too small by that gap). Fix by anchoring each entry's age to its own insert tick: carry `stored_at` on the Obs record and fold `(now - stored_at)` per-entry at load, instead of a single global fold against the last clock marker. flush() now also advances each in-memory age to its current value so the representation stays coherent within a run. This is exact for idle stores and observations inserted before the last flush. Adds tests/persistence.rs::ages_rebase_after_nonidle_flush (insert A at tick 1000, flush at 3000, reopen at 9000 -> asserts true age 8100, not 6100).
This commit is contained in:
@@ -95,6 +95,37 @@ fn ages_rebase_on_load() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ages_rebase_after_nonidle_flush() {
|
||||
// An observation inserted *before* the last flush must lose no time when
|
||||
// ages are rebased on load: the reopen fold has to be exact, not folded
|
||||
// against the flush clock as if the entry had been inserted then.
|
||||
let path = store_path("ages_nonidle");
|
||||
|
||||
{
|
||||
let mut s = LogStore::new(&path, 1000, 1).unwrap();
|
||||
let a = obs([1; 16], 1, 100, Some(10));
|
||||
assert!(s.insert(a, 1000).unwrap());
|
||||
// Advance the store clock via a second, distinct insert so the flush
|
||||
// below runs at a tick later than `a`'s insert — the store is
|
||||
// non-idle.
|
||||
let b = obs([2; 16], 2, 0, Some(20));
|
||||
assert!(s.insert(b, 3000).unwrap());
|
||||
s.flush().unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
// Reopen at 9000. `a`'s true age is 100 (insert-time) + (9000 - 1000)
|
||||
// = 8100. A flush that fails to catch `age_ms` up folds the reopen
|
||||
// against the flush clock (3000) and under-counts by the 2000ms
|
||||
// between insert and flush, reporting only 6100.
|
||||
let s = LogStore::new(&path, 9000, 1).unwrap();
|
||||
let a = obs([1; 16], 1, 100, Some(10));
|
||||
let g = s.get(&a.id(), 9000).unwrap();
|
||||
assert_eq!(g.age_ms, 8100);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_seq_persists() {
|
||||
let path = store_path("seq");
|
||||
|
||||
Reference in New Issue
Block a user