use std::any::TypeId;
use dashmap::DashMap;
use either::Either;
use crate::arc_erase::ArcEraseDyn;
use crate::storage::data::DataKey;
use crate::storage::data::PagableData;
use crate::storage::support::SerializerForPaging;
use crate::traits::SessionContext;
#[async_trait::async_trait]
pub trait PagableStorage: Send + Sync + 'static {
fn fetch_arc_or_data_blocking(
&self,
type_id: &TypeId,
key: &DataKey,
) -> anyhow::Result<Either<Box<dyn ArcEraseDyn>, std::sync::Arc<PagableData>>>;
async fn fetch_data(&self, key: &DataKey) -> anyhow::Result<std::sync::Arc<PagableData>>;
fn on_arc_deserialized(
&self,
typeid: TypeId,
key: DataKey,
arc: Box<dyn ArcEraseDyn>,
) -> Option<Box<dyn ArcEraseDyn>>;
fn schedule_for_paging(&self, arc: Box<dyn ArcEraseDyn>);
fn session_context(&self) -> &SessionContext;
fn store_data(&self, data: PagableData) -> anyhow::Result<DataKey>;
fn flush(&self) -> anyhow::Result<()> {
Ok(())
}
fn page_out_item(
&self,
item_data: Vec<u8>,
item_arcs: Vec<Box<dyn ArcEraseDyn>>,
finished: &DashMap<usize, DataKey>,
session_context: &SessionContext,
) -> anyhow::Result<DataKey> {
enum Task {
Start(Box<dyn ArcEraseDyn>),
Finish((Box<dyn ArcEraseDyn>, Vec<u8>, Vec<Box<dyn ArcEraseDyn>>)),
}
let mut tasks: Vec<Task> = item_arcs
.iter()
.map(|arc| Task::Start(arc.clone_dyn()))
.collect();
while let Some(task) = tasks.pop() {
match task {
Task::Start(v) => {
if finished.contains_key(&v.identity()) {
continue;
}
let mut serializer = SerializerForPaging::new(session_context);
v.serialize(&mut serializer)?;
let (data, arcs) = serializer.finish();
let subtasks: Vec<_> = arcs
.iter()
.filter(|arc| !finished.contains_key(&arc.identity()))
.map(|arc| Task::Start(arc.clone_dyn()))
.collect();
tasks.push(Task::Finish((v, data, arcs)));
tasks.extend(subtasks);
}
Task::Finish((arc, data, serialized_arcs)) => {
let arcs: Vec<DataKey> = serialized_arcs
.iter()
.map(|arc| {
*finished
.get(&arc.identity())
.expect("nested arc should have been serialized first")
})
.collect();
let key = self.store_data(PagableData { data, arcs })?;
finished.insert(arc.identity(), key);
arc.set_data_key(key);
}
}
}
let arcs: Vec<DataKey> = item_arcs
.iter()
.map(|arc| {
*finished
.get(&arc.identity())
.expect("nested arc should have been serialized first")
})
.collect();
self.store_data(PagableData {
data: item_data,
arcs,
})
}
}
static_assertions::assert_obj_safe!(PagableStorage);