use crate::projection::{ProjectionEventSelector, ProjectionExpression, ProjectionValueType};
use crate::DomainEventOccurrence;
use super::bind::MutationEventBinding;
use super::cache::{lower_mutation_cache, MutationCacheProgram, MutationCacheVisibility};
use super::handler::MutationHandlerRegistration;
use super::program::MutationProgram;
use super::server::MutationServerInterpreter;
use super::MutationProgramError;
#[derive(Clone, Debug)]
pub struct PreviewOwnerContribution {
pub owner: String,
pub program: MutationProgram,
pub cache: MutationCacheProgram,
}
#[derive(Clone, Debug, Default)]
pub struct ComposedPreviewLayer {
pub contributions: Vec<PreviewOwnerContribution>,
}
impl ComposedPreviewLayer {
pub fn has_optimism(&self) -> bool {
!self.contributions.is_empty()
}
pub fn all_effects(&self) -> Vec<&super::cache::MutationCacheEffect> {
self.contributions
.iter()
.flat_map(|contribution| contribution.cache.effects())
.collect()
}
}
pub fn compose_event_preview(
handlers: &[&MutationHandlerRegistration],
selector: &ProjectionEventSelector,
visibility: &MutationCacheVisibility,
) -> Result<ComposedPreviewLayer, MutationProgramError> {
let mut matching = handlers
.iter()
.filter(|handler| handler.binding().selector() == selector)
.copied()
.collect::<Vec<_>>();
matching.sort_by_key(|handler| handler.owner().to_owned());
let mut contributions = Vec::with_capacity(matching.len());
for handler in matching {
let cache = lower_mutation_cache(handler.binding().program(), visibility)?;
contributions.push(PreviewOwnerContribution {
owner: handler.owner().to_owned(),
program: handler.binding().program().clone(),
cache,
});
}
Ok(ComposedPreviewLayer { contributions })
}
pub fn reconcile_with_actual(
interpreter: &MutationServerInterpreter,
occurrence: &DomainEventOccurrence,
visibility: &MutationCacheVisibility,
) -> Result<MutationCacheProgram, MutationProgramError> {
let _resolved = interpreter.resolve(occurrence)?;
lower_mutation_cache(interpreter.program(), visibility)
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MutationCausalScope {
pub model: String,
pub storage: String,
}
pub fn causal_scopes(layer: &ComposedPreviewLayer) -> Vec<MutationCausalScope> {
let mut scopes = layer
.contributions
.iter()
.flat_map(|contribution| {
contribution
.program
.operations()
.iter()
.map(|operation| MutationCausalScope {
model: operation.target().model().to_owned(),
storage: operation.target().storage().to_owned(),
})
})
.collect::<Vec<_>>();
scopes.sort();
scopes.dedup();
scopes
}
pub fn zero_binding_preview() -> ComposedPreviewLayer {
ComposedPreviewLayer::default()
}
pub fn rewrite_binding_ops(
binding: &MutationEventBinding,
bind_input_path: &dyn Fn(
&[String],
&ProjectionValueType,
) -> Result<ProjectionExpression, MutationProgramError>,
) -> Result<Vec<crate::projection::ProjectionOperation>, MutationProgramError> {
binding
.program()
.rewrite_to_projection_operations(bind_input_path)
}