use crate::event_store::{Event, MissedOccurrencePolicy};
use crate::shared::{CommandDecision, PrivateField, SensitiveField, TagMapping};
use schemars::JsonSchema;
use serde::{de::DeserializeOwned, Serialize};
pub use skilj_macros::requires_role;
pub const DEFAULT_BOUNDED_CONTEXT: &str = "default";
pub trait BoundedContextEvent: Sized {
fn try_from_event(event: &Event) -> Option<Result<Self, serde_json::Error>>;
}
pub trait CommandType {
type Payload: Serialize + DeserializeOwned + JsonSchema;
type Event: BoundedContextEvent;
const NAME: &'static str;
const BOUNDED_CONTEXT: &'static str = DEFAULT_BOUNDED_CONTEXT;
fn tag_mappings() -> Vec<TagMapping> {
Vec::new()
}
fn owner_tag_key() -> Option<&'static str> {
None
}
fn sensitive_fields() -> Vec<SensitiveField> {
Vec::new()
}
fn private_fields() -> Vec<PrivateField> {
Vec::new()
}
fn rest_trigger_allowed() -> bool {
false
}
fn required_role() -> Option<&'static str> {
None
}
fn decide(payload: &Self::Payload, matching_events: &[Self::Event]) -> CommandDecision;
fn snapshot() -> Option<&'static str> {
None
}
fn decide_from_snapshot(
_payload: &Self::Payload,
_snapshot_state_json: &str,
_events_since_snapshot: &[Self::Event],
) -> CommandDecision {
CommandDecision::Rejected {
reason: "this CommandType declares snapshot() but never overrides \
decide_from_snapshot()"
.to_string(),
kind: "snapshot_misconfigured".to_string(),
}
}
}
pub trait EventType {
type Payload: Serialize + DeserializeOwned + JsonSchema;
const NAME: &'static str;
const BOUNDED_CONTEXT: &'static str = DEFAULT_BOUNDED_CONTEXT;
fn tag_mappings() -> Vec<TagMapping> {
Vec::new()
}
fn owner_tag_key() -> Option<&'static str> {
None
}
fn sensitive_fields() -> Vec<SensitiveField> {
Vec::new()
}
fn private_fields() -> Vec<PrivateField> {
Vec::new()
}
fn external_creation_allowed() -> bool {
false
}
fn direct_creation_allowed() -> bool {
false
}
fn event_read_allowed() -> bool {
false
}
fn system_triggered_allowed() -> bool {
false
}
fn system_triggered_schedule() -> Option<String> {
None
}
fn missed_occurrence_policy() -> Option<MissedOccurrencePolicy> {
None
}
fn scheduled_payload() -> Self::Payload {
unimplemented!(
"{}::scheduled_payload() must be overridden - this event type is registered with \
system_triggered_allowed() = true, so the scheduler needs a payload for every \
occurrence it fires",
Self::NAME
)
}
}
pub trait EventDispatcher: Send + Sync {
fn scheduled_payload(&self, bounded_context: &str, event_type: &str) -> Option<String>;
}
pub trait Projection {
type State: Serialize + DeserializeOwned + JsonSchema + Default;
type Event: BoundedContextEvent;
const NAME: &'static str;
const BOUNDED_CONTEXT: &'static str = DEFAULT_BOUNDED_CONTEXT;
fn consumed_event_types() -> Vec<&'static str>;
fn sync() -> bool {
false
}
fn keys(_event: &Self::Event) -> Vec<String> {
vec![String::new()]
}
const OWNER_TAG_KEY: Option<&'static str> = None;
fn project(state: &mut Self::State, event: &Self::Event, key: &str);
}
pub trait Snapshot {
type State: Serialize + DeserializeOwned + JsonSchema + Default;
type Event: BoundedContextEvent;
const NAME: &'static str;
const BOUNDED_CONTEXT: &'static str = DEFAULT_BOUNDED_CONTEXT;
const TAG_KEY: &'static str;
const OWNER_TAG_KEY: Option<&'static str> = None;
const VERSION: u64;
fn fold(state: &mut Self::State, event: &Self::Event);
}
pub trait CommandDispatcher: Send + Sync {
fn dispatch(
&self,
bounded_context: &str,
command_type: &str,
payload: &str,
matching_events: &[Event],
) -> Option<crate::error::Result<CommandDecision>>;
fn required_role(
&self,
bounded_context: &str,
command_type: &str,
) -> Option<Option<&'static str>>;
fn snapshot_name(
&self,
bounded_context: &str,
command_type: &str,
) -> Option<Option<&'static str>>;
fn dispatch_from_snapshot(
&self,
bounded_context: &str,
command_type: &str,
payload: &str,
snapshot_state_json: &str,
events_since_snapshot: &[Event],
) -> Option<crate::error::Result<CommandDecision>>;
}
pub trait ProjectionDispatcher: Send + Sync {
fn keys(
&self,
bounded_context: &str,
projection_name: &str,
event: &Event,
) -> Option<Vec<String>>;
fn project(
&self,
bounded_context: &str,
projection_name: &str,
state_json: &str,
event: &Event,
key: &str,
) -> Option<crate::error::Result<String>>;
fn default_state(&self, bounded_context: &str, projection_name: &str) -> Option<String>;
fn owner_tag_key(
&self,
bounded_context: &str,
projection_name: &str,
) -> Option<Option<&'static str>>;
}
pub trait SnapshotDispatcher: Send + Sync {
fn snapshot_names(&self, bounded_context: &str) -> Vec<&'static str>;
fn tag_key(&self, bounded_context: &str, snapshot_name: &str) -> Option<&'static str>;
fn owner_tag_key(
&self,
bounded_context: &str,
snapshot_name: &str,
) -> Option<Option<&'static str>>;
fn version(&self, bounded_context: &str, snapshot_name: &str) -> Option<u64>;
fn fold(
&self,
bounded_context: &str,
snapshot_name: &str,
state_json: &str,
event: &Event,
) -> Option<crate::error::Result<String>>;
fn default_state(&self, bounded_context: &str, snapshot_name: &str) -> Option<String>;
}