use async_trait::async_trait;
use crate::LixError;
#[cfg(test)]
use crate::hot_state::MaterializedHotStateBatchBuilder;
use crate::hot_state::{HotStateExactBatchRequest, HotStateScanRequest};
use crate::hot_state::{MaterializedHotStateBatch, MaterializedHotStateExactBatch};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum HotStateReadDomain {
Combined,
Tracked,
Untracked,
}
#[async_trait]
pub(crate) trait HotStateReader: Send + Sync {
async fn scan_batch(
&self,
request: &HotStateScanRequest,
) -> Result<MaterializedHotStateBatch, LixError>;
async fn scan_constraint_batch(
&self,
request: &HotStateScanRequest,
tracked_only: bool,
) -> Result<MaterializedHotStateBatch, LixError> {
if tracked_only {
self.scan_tracked_batch(request).await
} else {
self.scan_batch(request).await
}
}
async fn scan_domain_batch(
&self,
request: &HotStateScanRequest,
domain: HotStateReadDomain,
) -> Result<MaterializedHotStateBatch, LixError> {
match domain {
HotStateReadDomain::Combined => self.scan_constraint_batch(request, false).await,
HotStateReadDomain::Tracked => {
let mut request = request.clone();
request.filter.untracked = Some(false);
self.scan_constraint_batch(&request, true).await
}
HotStateReadDomain::Untracked => {
let mut request = request.clone();
request.filter.untracked = Some(true);
self.scan_constraint_batch(&request, false).await
}
}
}
async fn scan_tracked_batch(
&self,
request: &HotStateScanRequest,
) -> Result<MaterializedHotStateBatch, LixError> {
let mut request = request.clone();
request.filter.untracked = Some(false);
self.scan_batch(&request).await
}
async fn load_exact_batch(
&self,
request: &HotStateExactBatchRequest,
) -> Result<MaterializedHotStateExactBatch, LixError>;
async fn collection_generation(
&self,
_branch_id: &str,
_scope: crate::collection_generation::CollectionScopeRef<'_>,
) -> Result<Option<crate::collection_generation::CollectionGeneration>, LixError> {
Ok(None)
}
}
#[cfg(test)]
pub(crate) async fn load_exact_batch_via_scan_for_test<R>(
reader: &R,
request: &HotStateExactBatchRequest,
) -> Result<MaterializedHotStateExactBatch, LixError>
where
R: HotStateReader + ?Sized,
{
let mut rows = MaterializedHotStateBatchBuilder::with_capacity(request.rows.len());
let mut slots = Vec::with_capacity(request.rows.len());
for row in &request.rows {
let scanned = reader.scan_batch(&request.row_scan_request(row)).await?;
slots.push(
scanned
.get(0)
.map(|row| u32::try_from(rows.push_ref(row, None)))
.transpose()
.map_err(|_| {
LixError::new(
LixError::CODE_INTERNAL_ERROR,
"test exact live-state result exceeds u32 rows",
)
})?,
);
}
MaterializedHotStateExactBatch::new(rows.finish(), slots)
}