use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
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::{
Database, EagerVec, Exit, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec,
ReadableVec, Rw, StorageMode, Version,
};
use crate::internal::PerResolution;
#[derive(Deref, DerefMut, Traversable)]
pub struct Timestamps<M: StorageMode = Rw> {
pub monotonic: M::Stored<EagerVec<PcoVec<Height, Timestamp>>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
#[allow(clippy::type_complexity)]
pub resolutions: 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 Timestamps {
#[allow(clippy::too_many_arguments)]
pub(crate) fn forced_import_from_locals(
db: &Database,
version: Version,
minute10: &super::Minute10Vecs,
minute30: &super::Minute30Vecs,
hour1: &super::Hour1Vecs,
hour4: &super::Hour4Vecs,
hour12: &super::Hour12Vecs,
day1: &super::Day1Vecs,
day3: &super::Day3Vecs,
week1: &super::Week1Vecs,
month1: &super::Month1Vecs,
month3: &super::Month3Vecs,
month6: &super::Month6Vecs,
year1: &super::Year1Vecs,
year10: &super::Year10Vecs,
) -> Result<Self> {
let monotonic = EagerVec::forced_import(db, "timestamp_monotonic", version)?;
macro_rules! period {
($field:ident) => {
LazyVecFrom1::init(
"timestamp",
version,
$field.first_height.read_only_boxed_clone(),
|idx, _: Height| idx.to_timestamp(),
)
};
}
Ok(Self {
monotonic,
resolutions: 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: ImportableVec::forced_import(db, "timestamp", version)?,
epoch: ImportableVec::forced_import(db, "timestamp", version)?,
},
})
}
pub(crate) fn compute_monotonic(
&mut self,
indexer: &brk_indexer::Indexer,
starting_height: Height,
exit: &Exit,
) -> Result<()> {
let mut prev = None;
self.monotonic.compute_transform(
starting_height,
&indexer.vecs.blocks.timestamp,
|(h, timestamp, this)| {
if prev.is_none()
&& let Some(prev_h) = h.decremented()
{
prev.replace(this.collect_one(prev_h).unwrap());
}
let monotonic = prev.map_or(timestamp, |p| p.max(timestamp));
prev.replace(monotonic);
(h, monotonic)
},
exit,
)?;
Ok(())
}
pub(crate) fn compute_per_resolution(
&mut self,
indexer: &brk_indexer::Indexer,
height: &super::HeightVecs,
halving_vecs: &super::HalvingVecs,
epoch_vecs: &super::EpochVecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let prev_height = starting_indexes.height.decremented().unwrap_or_default();
self.resolutions.halving.compute_indirect_sequential(
height.halving.collect_one(prev_height).unwrap_or_default(),
&halving_vecs.first_height,
&indexer.vecs.blocks.timestamp,
exit,
)?;
self.resolutions.epoch.compute_indirect_sequential(
height.epoch.collect_one(prev_height).unwrap_or_default(),
&epoch_vecs.first_height,
&indexer.vecs.blocks.timestamp,
exit,
)?;
Ok(())
}
}