global: snapshot

This commit is contained in:
nym21
2026-03-26 15:57:22 +01:00
parent 6d3307c0df
commit 18bb4186a8
72 changed files with 2013 additions and 1150 deletions
+9 -8
View File
@@ -17,12 +17,10 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
// Sequential: time → lookback (dependency chain)
self.time
.timestamp
.compute(indexer, indexes, starting_indexes, exit)?;
self.lookback
.compute(&self.time, starting_indexes, exit)?;
self.db.sync_bg_tasks()?;
// lookback depends on indexes.timestamp.monotonic
self.lookback.compute(indexes, starting_indexes, exit)?;
// Parallel: remaining sub-modules are independent of each other.
// size depends on lookback (already computed above).
@@ -52,8 +50,11 @@ impl Vecs {
Ok(())
})?;
let _lock = exit.lock();
self.db.compact()?;
let exit = exit.clone();
self.db.run_bg(move |db| {
let _lock = exit.lock();
db.compact()
});
Ok(())
}
}
+1 -3
View File
@@ -10,7 +10,7 @@ use crate::{
};
use super::{
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, TimeVecs, Vecs,
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, Vecs,
WeightVecs,
};
@@ -30,7 +30,6 @@ impl Vecs {
let interval = IntervalVecs::forced_import(&db, version, indexes, cached_starts)?;
let size = SizeVecs::forced_import(&db, version, indexes, cached_starts)?;
let weight = WeightVecs::forced_import(&db, version, indexes, cached_starts, &size)?;
let time = TimeVecs::forced_import(&db, version, indexes)?;
let difficulty = DifficultyVecs::forced_import(&db, version, indexer, indexes)?;
let halving = HalvingVecs::forced_import(&db, version, indexes)?;
@@ -41,7 +40,6 @@ impl Vecs {
interval,
size,
weight,
time,
difficulty,
halving,
};
+55 -54
View File
@@ -3,9 +3,10 @@ use brk_traversable::Traversable;
use brk_types::{Height, Indexes, Timestamp, Version};
use vecdb::{AnyVec, CachedVec, Cursor, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw, StorageMode, VecIndex};
use crate::internal::{CachedWindowStarts, Windows, WindowStarts};
use super::time;
use crate::{
indexes,
internal::{CachedWindowStarts, Windows, WindowStarts},
};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
@@ -178,71 +179,71 @@ impl Vecs {
pub(crate) fn compute(
&mut self,
time: &time::Vecs,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_rolling_start_hours(time, starting_indexes, exit, 1, |s| {
self.compute_rolling_start_hours(indexes, starting_indexes, exit, 1, |s| {
&mut s._1h
})?;
self.compute_rolling_start(time, starting_indexes, exit, 1, |s| &mut s._24h)?;
self.compute_rolling_start(time, starting_indexes, exit, 3, |s| &mut s._3d)?;
self.compute_rolling_start(time, starting_indexes, exit, 7, |s| &mut s._1w)?;
self.compute_rolling_start(time, starting_indexes, exit, 8, |s| &mut s._8d)?;
self.compute_rolling_start(time, starting_indexes, exit, 9, |s| &mut s._9d)?;
self.compute_rolling_start(time, starting_indexes, exit, 12, |s| &mut s._12d)?;
self.compute_rolling_start(time, starting_indexes, exit, 13, |s| &mut s._13d)?;
self.compute_rolling_start(time, starting_indexes, exit, 14, |s| &mut s._2w)?;
self.compute_rolling_start(time, starting_indexes, exit, 21, |s| &mut s._21d)?;
self.compute_rolling_start(time, starting_indexes, exit, 26, |s| &mut s._26d)?;
self.compute_rolling_start(time, starting_indexes, exit, 30, |s| &mut s._1m)?;
self.compute_rolling_start(time, starting_indexes, exit, 34, |s| &mut s._34d)?;
self.compute_rolling_start(time, starting_indexes, exit, 55, |s| &mut s._55d)?;
self.compute_rolling_start(time, starting_indexes, exit, 60, |s| &mut s._2m)?;
self.compute_rolling_start(time, starting_indexes, exit, 63, |s| &mut s._9w)?;
self.compute_rolling_start(time, starting_indexes, exit, 84, |s| &mut s._12w)?;
self.compute_rolling_start(time, starting_indexes, exit, 89, |s| &mut s._89d)?;
self.compute_rolling_start(time, starting_indexes, exit, 90, |s| &mut s._3m)?;
self.compute_rolling_start(time, starting_indexes, exit, 98, |s| &mut s._14w)?;
self.compute_rolling_start(time, starting_indexes, exit, 111, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 1, |s| &mut s._24h)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3, |s| &mut s._3d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 7, |s| &mut s._1w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 8, |s| &mut s._8d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 9, |s| &mut s._9d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 12, |s| &mut s._12d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 13, |s| &mut s._13d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 14, |s| &mut s._2w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 21, |s| &mut s._21d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 26, |s| &mut s._26d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 30, |s| &mut s._1m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 34, |s| &mut s._34d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 55, |s| &mut s._55d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 60, |s| &mut s._2m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 63, |s| &mut s._9w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 84, |s| &mut s._12w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 89, |s| &mut s._89d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 90, |s| &mut s._3m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 98, |s| &mut s._14w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 111, |s| {
&mut s._111d
})?;
self.compute_rolling_start(time, starting_indexes, exit, 144, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 144, |s| {
&mut s._144d
})?;
self.compute_rolling_start(time, starting_indexes, exit, 180, |s| &mut s._6m)?;
self.compute_rolling_start(time, starting_indexes, exit, 182, |s| &mut s._26w)?;
self.compute_rolling_start(time, starting_indexes, exit, 200, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 180, |s| &mut s._6m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 182, |s| &mut s._26w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 200, |s| {
&mut s._200d
})?;
self.compute_rolling_start(time, starting_indexes, exit, 270, |s| &mut s._9m)?;
self.compute_rolling_start(time, starting_indexes, exit, 350, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 270, |s| &mut s._9m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 350, |s| {
&mut s._350d
})?;
self.compute_rolling_start(time, starting_indexes, exit, 360, |s| &mut s._12m)?;
self.compute_rolling_start(time, starting_indexes, exit, 365, |s| &mut s._1y)?;
self.compute_rolling_start(time, starting_indexes, exit, 420, |s| &mut s._14m)?;
self.compute_rolling_start(time, starting_indexes, exit, 730, |s| &mut s._2y)?;
self.compute_rolling_start(time, starting_indexes, exit, 780, |s| &mut s._26m)?;
self.compute_rolling_start(time, starting_indexes, exit, 1095, |s| &mut s._3y)?;
self.compute_rolling_start(time, starting_indexes, exit, 1400, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 360, |s| &mut s._12m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 365, |s| &mut s._1y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 420, |s| &mut s._14m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 730, |s| &mut s._2y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 780, |s| &mut s._26m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1095, |s| &mut s._3y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1400, |s| {
&mut s._200w
})?;
self.compute_rolling_start(time, starting_indexes, exit, 1460, |s| &mut s._4y)?;
self.compute_rolling_start(time, starting_indexes, exit, 1825, |s| &mut s._5y)?;
self.compute_rolling_start(time, starting_indexes, exit, 2190, |s| &mut s._6y)?;
self.compute_rolling_start(time, starting_indexes, exit, 2920, |s| &mut s._8y)?;
self.compute_rolling_start(time, starting_indexes, exit, 3285, |s| &mut s._9y)?;
self.compute_rolling_start(time, starting_indexes, exit, 3650, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 1460, |s| &mut s._4y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1825, |s| &mut s._5y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 2190, |s| &mut s._6y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 2920, |s| &mut s._8y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3285, |s| &mut s._9y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3650, |s| {
&mut s._10y
})?;
self.compute_rolling_start(time, starting_indexes, exit, 4380, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 4380, |s| {
&mut s._12y
})?;
self.compute_rolling_start(time, starting_indexes, exit, 5110, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 5110, |s| {
&mut s._14y
})?;
self.compute_rolling_start(time, starting_indexes, exit, 9490, |s| {
self.compute_rolling_start(indexes, starting_indexes, exit, 9490, |s| {
&mut s._26y
})?;
@@ -251,7 +252,7 @@ impl Vecs {
fn compute_rolling_start<F>(
&mut self,
time: &time::Vecs,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
days: usize,
@@ -260,14 +261,14 @@ impl Vecs {
where
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
{
self.compute_rolling_start_inner(time, starting_indexes, exit, get_field, |t, prev_ts| {
self.compute_rolling_start_inner(indexes, starting_indexes, exit, get_field, |t, prev_ts| {
t.difference_in_days_between(prev_ts) >= days
})
}
fn compute_rolling_start_hours<F>(
&mut self,
time: &time::Vecs,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
hours: usize,
@@ -276,14 +277,14 @@ impl Vecs {
where
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
{
self.compute_rolling_start_inner(time, starting_indexes, exit, get_field, |t, prev_ts| {
self.compute_rolling_start_inner(indexes, starting_indexes, exit, get_field, |t, prev_ts| {
t.difference_in_hours_between(prev_ts) >= hours
})
}
fn compute_rolling_start_inner<F, D>(
&mut self,
time: &time::Vecs,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
get_field: F,
@@ -300,12 +301,12 @@ impl Vecs {
} else {
Height::ZERO
};
let mut cursor = Cursor::new(&time.timestamp_monotonic);
let mut cursor = Cursor::new(&indexes.timestamp.monotonic);
cursor.advance(prev.to_usize());
let mut prev_ts = cursor.next().unwrap();
Ok(field.compute_transform(
starting_indexes.height,
&time.timestamp_monotonic,
&indexes.timestamp.monotonic,
|(h, t, ..)| {
while expired(t, prev_ts) {
prev.increment();
+1 -4
View File
@@ -4,7 +4,6 @@ pub mod halving;
pub mod interval;
pub mod lookback;
pub mod size;
pub mod time;
pub mod weight;
mod compute;
@@ -19,7 +18,6 @@ pub use halving::Vecs as HalvingVecs;
pub use interval::Vecs as IntervalVecs;
pub use lookback::Vecs as LookbackVecs;
pub use size::Vecs as SizeVecs;
pub use time::Vecs as TimeVecs;
pub use weight::Vecs as WeightVecs;
pub const DB_NAME: &str = "blocks";
@@ -37,7 +35,7 @@ pub(crate) const ONE_TERA_HASH: f64 = 1_000_000_000_000.0;
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
#[traversable(skip)]
pub(crate) db: Database,
pub db: Database,
pub count: CountVecs<M>,
pub lookback: LookbackVecs<M>,
@@ -46,7 +44,6 @@ pub struct Vecs<M: StorageMode = Rw> {
pub size: SizeVecs<M>,
#[traversable(flatten)]
pub weight: WeightVecs<M>,
pub time: TimeVecs<M>,
pub difficulty: DifficultyVecs<M>,
pub halving: HalvingVecs<M>,
}
@@ -1,34 +0,0 @@
use brk_error::Result;
use brk_indexer::Indexer;
use vecdb::{Exit, ReadableVec};
use super::Vecs;
impl Vecs {
pub(crate) fn compute(
&mut self,
indexer: &Indexer,
starting_height: brk_types::Height,
exit: &Exit,
) -> Result<()> {
let mut prev_timestamp_monotonic = None;
self.timestamp_monotonic.compute_transform(
starting_height,
&indexer.vecs.blocks.timestamp,
|(h, timestamp, this)| {
if prev_timestamp_monotonic.is_none()
&& let Some(prev_h) = h.decremented()
{
prev_timestamp_monotonic.replace(this.collect_one(prev_h).unwrap());
}
let timestamp_monotonic =
prev_timestamp_monotonic.map_or(timestamp, |prev_d| prev_d.max(timestamp));
prev_timestamp_monotonic.replace(timestamp_monotonic);
(h, timestamp_monotonic)
},
exit,
)?;
Ok(())
}
}
@@ -1,66 +0,0 @@
use brk_error::Result;
use brk_types::{Date, Height, Version};
use vecdb::{Database, EagerVec, ImportableVec, LazyVecFrom1, ReadableCloneableVec};
use super::{TimestampIndexes, Vecs};
use crate::indexes;
impl Vecs {
pub(crate) fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let timestamp_monotonic = EagerVec::forced_import(db, "timestamp_monotonic", version)?;
Ok(Self {
date: LazyVecFrom1::init(
"date",
version,
timestamp_monotonic.read_only_boxed_clone(),
|_height: Height, timestamp| Date::from(timestamp),
),
timestamp_monotonic,
timestamp: TimestampIndexes::forced_import(db, version, indexes)?,
})
}
}
impl TimestampIndexes {
fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
macro_rules! period {
($field:ident) => {
LazyVecFrom1::init(
"timestamp",
version,
indexes.$field.first_height.read_only_boxed_clone(),
|idx, _: Height| idx.to_timestamp(),
)
};
}
macro_rules! epoch {
($field:ident) => {
ImportableVec::forced_import(db, "timestamp", version)?
};
}
Ok(Self(crate::internal::PerResolution {
minute10: period!(minute10),
minute30: period!(minute30),
hour1: period!(hour1),
hour4: period!(hour4),
hour12: period!(hour12),
day1: period!(day1),
day3: period!(day3),
week1: period!(week1),
month1: period!(month1),
month3: period!(month3),
month6: period!(month6),
year1: period!(year1),
year10: period!(year10),
halving: epoch!(halving),
epoch: epoch!(difficulty),
}))
}
}
@@ -1,5 +0,0 @@
mod compute;
mod import;
mod vecs;
pub use vecs::{TimestampIndexes, Vecs};
@@ -1,80 +0,0 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
Date, Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Indexes,
Minute10, Minute30, Month1, Month3, Month6, Timestamp, Week1, Year1, Year10,
};
use derive_more::{Deref, DerefMut};
use vecdb::{EagerVec, Exit, LazyVecFrom1, PcoVec, ReadableVec, Rw, StorageMode};
use crate::{indexes, internal::PerResolution};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub date: LazyVecFrom1<Height, Date, Height, Timestamp>,
pub timestamp_monotonic: M::Stored<EagerVec<PcoVec<Height, Timestamp>>>,
pub timestamp: TimestampIndexes<M>,
}
/// Per-period timestamp indexes.
///
/// Time-based periods (minute10year10) are lazy: `idx.to_timestamp()` is a pure
/// function of the index, so no storage or decompression is needed.
/// Epoch-based periods (halving, difficulty) are eager: their timestamps
/// come from block data via `compute_indirect_sequential`.
#[derive(Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct TimestampIndexes<M: StorageMode = Rw>(
#[allow(clippy::type_complexity)]
pub PerResolution<
LazyVecFrom1<Minute10, Timestamp, Minute10, Height>,
LazyVecFrom1<Minute30, Timestamp, Minute30, Height>,
LazyVecFrom1<Hour1, Timestamp, Hour1, Height>,
LazyVecFrom1<Hour4, Timestamp, Hour4, Height>,
LazyVecFrom1<Hour12, Timestamp, Hour12, Height>,
LazyVecFrom1<Day1, Timestamp, Day1, Height>,
LazyVecFrom1<Day3, Timestamp, Day3, Height>,
LazyVecFrom1<Week1, Timestamp, Week1, Height>,
LazyVecFrom1<Month1, Timestamp, Month1, Height>,
LazyVecFrom1<Month3, Timestamp, Month3, Height>,
LazyVecFrom1<Month6, Timestamp, Month6, Height>,
LazyVecFrom1<Year1, Timestamp, Year1, Height>,
LazyVecFrom1<Year10, Timestamp, Year10, Height>,
M::Stored<EagerVec<PcoVec<Halving, Timestamp>>>,
M::Stored<EagerVec<PcoVec<Epoch, Timestamp>>>,
>,
);
impl TimestampIndexes {
/// Compute epoch timestamps via indirect lookup from block timestamps.
/// Time-based periods are lazy (idx.to_timestamp()) and need no compute.
pub(crate) fn compute(
&mut self,
indexer: &brk_indexer::Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let prev_height = starting_indexes.height.decremented().unwrap_or_default();
self.halving.compute_indirect_sequential(
indexes
.height
.halving
.collect_one(prev_height)
.unwrap_or_default(),
&indexes.halving.first_height,
&indexer.vecs.blocks.timestamp,
exit,
)?;
self.epoch.compute_indirect_sequential(
indexes
.height
.epoch
.collect_one(prev_height)
.unwrap_or_default(),
&indexes.epoch.first_height,
&indexer.vecs.blocks.timestamp,
exit,
)?;
Ok(())
}
}