use std::sync::Arc;
use hyphae::{Cell, CellImmutable};
use super::{
cell::FilteredCellMap, registration::QueryFactory, request::QueryRequest, traits::AnyQuery,
};
use crate::{
core::report::{ReportFactory, ReportHandler, ReportOutputType},
request::RequestContext,
server::MykoServerContext,
store::StoreRegistry,
};
#[derive(Clone, Debug)]
pub struct QueryContext {
pub req: Arc<RequestContext>,
}
impl crate::core::capability::sealed::Sealed for QueryContext {}
impl crate::core::capability::RequestScoped for QueryContext {
fn __request(&self) -> &Arc<RequestContext> {
&self.req
}
}
#[derive(Clone)]
pub struct QueryBuildContext {
pub query_context: Arc<QueryContext>,
registry: Arc<StoreRegistry>,
server_ctx: Option<Arc<MykoServerContext>>,
}
impl QueryBuildContext {
#[must_use]
pub const fn new(
query_context: Arc<QueryContext>,
registry: Arc<StoreRegistry>,
server_ctx: Option<Arc<MykoServerContext>>,
) -> Self {
Self {
query_context,
registry,
server_ctx,
}
}
pub fn query<Q>(&self, query: Q) -> Result<FilteredCellMap, String>
where
Q: QueryFactory + Clone,
Q::Item: crate::core::item::Eventable
+ crate::common::with_id::WithId
+ serde::de::DeserializeOwned
+ Clone
+ std::fmt::Debug
+ Send
+ Sync
+ 'static,
{
if let Some(server_ctx) = self.server_ctx.clone() {
return Ok(server_ctx.query_map_untyped(query, self.query_context.req.clone()));
}
let wrapped = QueryRequest::with_tx(query, self.query_context.req.tx.clone());
let any_query: Arc<dyn AnyQuery> = Arc::new(wrapped);
Q::cell_factory(
any_query,
self.registry.clone(),
self.query_context.req.clone(),
self.server_ctx.clone(),
)
}
pub fn report<R>(
&self,
report: R,
) -> Result<Cell<Arc<<R as ReportOutputType>::Output>, CellImmutable>, String>
where
R: ReportFactory + ReportHandler<Output = <R as ReportOutputType>::Output> + Clone,
<R as ReportOutputType>::Output:
crate::common::to_value::ToValue + std::fmt::Debug + Send + Sync + 'static,
{
let Some(server_ctx) = self.server_ctx.clone() else {
return Err("QueryBuildContext.report requires server context".to_string());
};
Ok(server_ctx.report(report, self.query_context.req.clone()))
}
#[must_use]
pub fn registry(&self) -> Arc<StoreRegistry> {
self.registry.clone()
}
}
impl crate::core::capability::sealed::Sealed for QueryBuildContext {}
impl crate::core::capability::RequestScoped for QueryBuildContext {
fn __request(&self) -> &Arc<RequestContext> {
&self.query_context.req
}
}