use std::sync::Arc;
use hyphae::{Cell, CellImmutable, CellMap, CellValue};
use serde::{Serialize, de::DeserializeOwned};
use uuid::Uuid;
#[cfg(not(target_arch = "wasm32"))]
use crate::client::{ConnectionStatus, MykoClient};
#[cfg(not(target_arch = "wasm32"))]
use crate::core::view::{TypedViewCellMap, ViewFactory};
#[cfg(not(target_arch = "wasm32"))]
use crate::item::typed_map_from_any_item_with_typed_id;
#[cfg(not(target_arch = "wasm32"))]
use crate::query::FilteredCellMap;
#[cfg(not(target_arch = "wasm32"))]
use crate::server::CellServerCtx;
#[cfg(not(target_arch = "wasm32"))]
use crate::server::PersistHealth;
#[cfg(not(target_arch = "wasm32"))]
use crate::store::StoreRegistry;
use crate::{
cache::CacheKey,
common::{
to_value::ToValue,
with_id::{WithId, WithTypedId},
},
core::item::Eventable,
query::QueryParams,
report::ReportId,
request::RequestContext,
};
#[derive(Clone)]
pub struct ReportContext {
pub req: Arc<RequestContext>,
#[cfg(not(target_arch = "wasm32"))]
server_ctx: Arc<CellServerCtx>,
}
impl ReportContext {
#[cfg(not(target_arch = "wasm32"))]
pub fn new(req: Arc<RequestContext>, server_ctx: Arc<CellServerCtx>) -> Self {
Self { req, server_ctx }
}
pub fn tx(&self) -> &str {
&self.req.tx
}
pub fn client_id(&self) -> Option<&str> {
self.req.client_id.as_deref()
}
pub fn host_id(&self) -> Uuid {
self.req.host_id
}
pub fn lineage(&self) -> &[Arc<str>] {
&self.req.lineage
}
#[cfg(not(target_arch = "wasm32"))]
pub fn query_map<Q>(
&self,
query: Q,
) -> CellMap<<Q::Item as WithTypedId>::Id, Arc<Q::Item>, CellImmutable>
where
Q: QueryParams + 'static,
Q::Item: Eventable
+ WithId
+ WithTypedId
+ DeserializeOwned
+ Clone
+ std::fmt::Debug
+ Send
+ Sync
+ CellValue
+ 'static,
{
typed_map_from_any_item_with_typed_id(
self.server_ctx.query_map_untyped(query, self.req.clone()),
"ReportContext::query_map",
)
}
#[cfg(target_arch = "wasm32")]
pub fn query_map<Q>(
&self,
query: Q,
) -> CellMap<<Q::Item as WithTypedId>::Id, Arc<Q::Item>, CellImmutable>
where
Q: QueryParams + 'static,
Q::Item: Eventable
+ WithId
+ WithTypedId
+ DeserializeOwned
+ Clone
+ std::fmt::Debug
+ Send
+ Sync
+ CellValue
+ 'static,
{
let _ = query;
unreachable!("ReportContext::query_map is not available on wasm32");
}
#[cfg(not(target_arch = "wasm32"))]
pub fn query_map_by_str<Q>(&self, query: Q) -> CellMap<Arc<str>, Arc<Q::Item>, CellImmutable>
where
Q: QueryParams + 'static,
Q::Item: Eventable
+ WithId
+ DeserializeOwned
+ Clone
+ std::fmt::Debug
+ Send
+ Sync
+ CellValue
+ 'static,
{
self.server_ctx.query_map(query, self.req.clone())
}
#[cfg(target_arch = "wasm32")]
pub fn query_map_by_str<Q>(&self, query: Q) -> CellMap<Arc<str>, Arc<Q::Item>, CellImmutable>
where
Q: QueryParams + 'static,
Q::Item: Eventable
+ WithId
+ DeserializeOwned
+ Clone
+ std::fmt::Debug
+ Send
+ Sync
+ CellValue
+ 'static,
{
let _ = query;
unreachable!("ReportContext::query_map_by_str is not available on wasm32");
}
#[cfg(not(target_arch = "wasm32"))]
pub fn query_map_untyped<Q>(&self, query: Q) -> FilteredCellMap
where
Q: QueryParams + 'static,
Q::Item:
Eventable + WithId + DeserializeOwned + Clone + std::fmt::Debug + Send + Sync + 'static,
{
self.server_ctx.query_map_untyped(query, self.req.clone())
}
pub fn search(&self, entity_type: &str, query: &str, limit: usize) -> Vec<Arc<str>> {
#[cfg(not(target_arch = "wasm32"))]
{
self.server_ctx
.search_index()
.search(entity_type, query, limit)
}
#[cfg(target_arch = "wasm32")]
{
let _ = (entity_type, query, limit);
unreachable!();
}
}
pub fn report<R>(&self, report: R) -> Cell<Arc<R::Output>, CellImmutable>
where
R: ReportHandler + ReportId + CacheKey + Clone + serde::Serialize + 'static,
{
#[cfg(not(target_arch = "wasm32"))]
{
self.server_ctx.report(report, self.req.clone())
}
#[cfg(target_arch = "wasm32")]
{
let _ = report;
unreachable!();
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn view<V>(&self, view: V) -> TypedViewCellMap<V::Item>
where
V: ViewFactory + Clone + Send + Sync + 'static,
V::Item: DeserializeOwned + Clone + std::fmt::Debug + Send + Sync + 'static,
{
self.server_ctx.view(view, self.req.clone())
}
#[cfg(not(target_arch = "wasm32"))]
pub fn peer_client(&self, peer_id: &str) -> Option<Arc<MykoClient>> {
self.server_ctx.peer_client(peer_id)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn peer_connection_status(&self, peer_id: &str) -> Option<ConnectionStatus> {
self.server_ctx.peer_connection_status(peer_id)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn peer_clients_tick(&self) -> Cell<u64, CellImmutable> {
self.server_ctx.peer_clients_tick()
}
#[cfg(not(target_arch = "wasm32"))]
pub fn persist_health(&self) -> Arc<PersistHealth> {
self.server_ctx.persist_health()
}
#[cfg(not(target_arch = "wasm32"))]
pub fn registry(&self) -> Arc<StoreRegistry> {
self.server_ctx.registry.clone()
}
#[cfg(not(target_arch = "wasm32"))]
pub fn replay_store(&self, until: &str) -> Result<Arc<StoreRegistry>, String> {
let provider = self
.server_ctx
.history_replay()
.ok_or_else(|| "No history replay provider configured".to_string())?;
provider.replay_to_store(until, &self.server_ctx.handler_registry)
}
}
pub trait ReportHandler: Sized + Send + Sync + 'static {
type Output: Serialize
+ DeserializeOwned
+ Clone
+ std::fmt::Debug
+ PartialEq
+ Send
+ Sync
+ ToValue
+ 'static;
fn compute(&self, ctx: ReportContext) -> Cell<Arc<Self::Output>, CellImmutable>;
}