use holochain_conductor_api::{OpTimingDump, OpTimingsCursor, OpTimingsDump};
use holochain_data::kind::Dht;
use holochain_data::models::dht::OpTimingRow;
use holochain_data::DbWrite;
use holochain_types::prelude::{AgentPubKey, DhtOpHash, OpValidity, Timestamp};
use super::DhtStore;
use crate::mutations::{StateMutationError, StateMutationResult};
use crate::query::{StateQueryError, StateQueryResult};
impl<Db> DhtStore<Db>
where
Db: AsRef<holochain_data::DbRead<Dht>>,
{
pub async fn op_hashes_in_time_slice(
&self,
arc_start: u32,
arc_end: u32,
start: Timestamp,
end: Timestamp,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2OpHashRow>> {
self.db
.as_ref()
.op_hashes_in_time_slice(arc_start, arc_end, start.as_micros(), end.as_micros())
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn op_ids_since_time_batch(
&self,
arc_start: u32,
arc_end: u32,
t_min: Timestamp,
limit: u32,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2OpIdSinceRow>> {
self.db
.as_ref()
.op_ids_since_time_batch(arc_start, arc_end, t_min.as_micros(), limit)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn check_op_hashes_present(
&self,
op_hashes: &[Vec<u8>],
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2OpPresentRow>> {
self.db
.as_ref()
.check_op_hashes_present(op_hashes)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn get_chain_ops_for_wire(
&self,
op_hashes: &[Vec<u8>],
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2ChainOpForWireRow>> {
self.db
.as_ref()
.get_chain_ops_for_wire(op_hashes)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn get_warrants_for_wire(
&self,
op_hashes: &[Vec<u8>],
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2WarrantForWireRow>> {
self.db
.as_ref()
.get_warrants_for_wire(op_hashes)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn earliest_authored_timestamp_in_arc(
&self,
arc_start: u32,
arc_end: u32,
) -> crate::query::StateQueryResult<Option<Timestamp>> {
let micros = self
.db
.as_ref()
.earliest_authored_timestamp_in_arc(arc_start, arc_end)
.await
.map_err(crate::query::StateQueryError::Sqlx)?;
Ok(micros.map(Timestamp::from_micros))
}
pub async fn limbo_state_counts(
&self,
) -> crate::query::StateQueryResult<(usize, usize, usize)> {
let (validation_limbo, integration_limbo, integrated) = self
.db
.as_ref()
.limbo_state_counts()
.await
.map_err(crate::query::StateQueryError::Sqlx)?;
Ok((
validation_limbo.max(0) as usize,
integration_limbo.max(0) as usize,
integrated.max(0) as usize,
))
}
pub async fn integrated_chain_ops_for_dump(
&self,
after: Option<(i64, &[u8])>,
limit: Option<u32>,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::DumpChainOpRow>> {
if limit == Some(0) {
return Err(crate::query::StateQueryError::InvalidInput(
"dump limit must be greater than zero".to_string(),
));
}
self.db
.as_ref()
.integrated_chain_ops_for_dump(after, limit)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn dht_ops_page_for_dump(
&self,
after: Option<(i64, &DhtOpHash)>,
limit: Option<u32>,
) -> crate::query::StateQueryResult<holochain_data::models::dht::DumpOpPage> {
if limit == Some(0) {
return Err(crate::query::StateQueryError::InvalidInput(
"dump limit must be greater than zero".to_string(),
));
}
self.db
.as_ref()
.dht_ops_page_for_dump(after, limit)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn op_timings_page_for_dump(
&self,
after: Option<&OpTimingsCursor>,
limit: Option<u32>,
) -> StateQueryResult<OpTimingsDump> {
if limit == Some(0) {
return Err(StateQueryError::InvalidInput(
"dump limit must be greater than zero".to_string(),
));
}
let page = self
.db
.as_ref()
.op_timings_page(
after.map(|cursor| (cursor.when_received, &cursor.hash)),
limit,
)
.await
.map_err(StateQueryError::Sqlx)?;
Ok(OpTimingsDump {
timings: page
.rows
.into_iter()
.map(op_timing_dump)
.collect::<StateQueryResult<Vec<_>>>()?,
cursor: page.cursor.map(|cursor| OpTimingsCursor {
when_received: cursor.when_received,
hash: cursor.hash,
}),
})
}
pub async fn limbo_chain_ops_for_dump(
&self,
ready: bool,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2ChainOpForWireRow>> {
self.db
.as_ref()
.limbo_chain_ops_for_dump(ready)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn integrated_warrants_for_dump(
&self,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2WarrantForWireRow>> {
self.db
.as_ref()
.integrated_warrants_for_dump()
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn ops_to_publish_for_wire(
&self,
author: &AgentPubKey,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::K2ChainOpForWireRow>> {
self.db
.as_ref()
.ops_to_publish_for_wire(author)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn total_integrated_op_count(&self) -> crate::query::StateQueryResult<u64> {
let n = self
.db
.as_ref()
.count_integrated_ops()
.await
.map_err(crate::query::StateQueryError::Sqlx)?;
Ok(n)
}
pub async fn slice_hash_count(
&self,
arc_start: u32,
arc_end: u32,
) -> crate::query::StateQueryResult<u64> {
self.db
.as_ref()
.slice_hash_count(arc_start, arc_end)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn get_slice_hash(
&self,
arc_start: u32,
arc_end: u32,
slice_index: u64,
) -> crate::query::StateQueryResult<Option<Vec<u8>>> {
self.db
.as_ref()
.get_slice_hash(arc_start, arc_end, slice_index)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
pub async fn get_slice_hashes(
&self,
arc_start: u32,
arc_end: u32,
) -> crate::query::StateQueryResult<Vec<holochain_data::models::dht::SliceHashIndexedRow>> {
self.db
.as_ref()
.get_slice_hashes(arc_start, arc_end)
.await
.map_err(crate::query::StateQueryError::Sqlx)
}
}
fn op_timing_dump(row: OpTimingRow) -> StateQueryResult<OpTimingDump> {
Ok(OpTimingDump {
op_hash: DhtOpHash::from_raw_36(row.hash),
when_received: Timestamp::from_micros(row.when_received),
when_integrated: row.when_integrated.map(Timestamp::from_micros),
abandoned_at: row.abandoned_at.map(Timestamp::from_micros),
validation_status: row
.validation_status
.map(OpValidity::try_from)
.transpose()
.map_err(|status| {
StateQueryError::Other(format!("invalid stored validation status {status}"))
})?,
locally_validated: row.locally_validated.map(|flag| flag != 0),
})
}
impl DhtStore<DbWrite<Dht>> {
pub async fn store_slice_hash(
&self,
arc_start: u32,
arc_end: u32,
slice_index: u64,
hash: &[u8],
) -> StateMutationResult<()> {
self.db
.insert_slice_hash(arc_start, arc_end, slice_index, hash)
.await
.map_err(StateMutationError::from)?;
Ok(())
}
}