use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{collections::HashMap, marker::PhantomData};
use crate::{
channels::messages::incoming::{EventMessage, RequestMessage},
Error, ServiceBroker,
};
pub type Callback<T> = fn(Context<T>) -> Result<(), Box<dyn std::error::Error>>;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Action {
name: String,
#[serde(default)]
params: Option<Value>,
#[serde(skip)]
pub(crate) callback: Option<Callback<Action>>,
}
#[derive(Default, Debug)]
pub struct EventBuilder {
name: String,
params: Option<Value>,
callback: Option<Callback<Event>>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Event {
name: String,
#[serde(default)]
params: Option<Value>,
#[serde(skip)]
pub(crate) callback: Option<Callback<Event>>,
}
impl EventBuilder {
pub fn new<S: Into<String>>(name: S) -> Self {
Self {
name: name.into(),
..Self::default()
}
}
pub fn add_params(mut self, params: Value) -> Self {
self.params = Some(params);
self
}
pub fn add_callback(mut self, callback: Callback<Event>) -> Self {
self.callback = Some(callback);
self
}
pub fn build(self) -> Event {
Event {
name: self.name,
params: self.params,
callback: self.callback,
}
}
}
#[derive(Default, Debug)]
pub struct ActionBuilder {
name: String,
params: Option<Value>,
callback: Option<Callback<Action>>,
}
impl ActionBuilder {
pub fn new<S: Into<String>>(name: S) -> Self {
Self {
name: name.into(),
..Self::default()
}
}
pub fn add_params(mut self, params: Value) -> Self {
self.params = Some(params);
self
}
pub fn add_callback(mut self, callback: Callback<Action>) -> Self {
self.callback = Some(callback);
self
}
pub fn build(self) -> Action {
Action {
name: self.name,
params: self.params,
callback: self.callback,
}
}
}
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct Service {
name: String,
version: Option<String>,
#[serde(default)]
#[serde(skip_deserializing)]
settings: HashMap<String, String>,
#[serde(default)]
metadata: Option<Value>,
pub(crate) actions: HashMap<String, Action>,
pub(crate) events: HashMap<String, Event>,
}
impl Service {
pub fn new<S: Into<String>>(name: S) -> Self {
Self {
name: name.into(),
..Default::default()
}
}
pub fn set_version(mut self, version: String) -> Self {
self.version = Some(version);
self
}
fn _make_key(&self, suffix: &str) -> String {
if let Some(ref version) = self.version {
format!("{}.{}.{}", version, self.name, suffix)
} else {
format!("{}.{}", self.name, suffix)
}
}
pub fn add_action(mut self, action: Action) -> Self {
self.actions.insert(self._make_key(&action.name), action);
self
}
pub fn add_event(mut self, event: Event) -> Self {
self.events.insert(self._make_key(&event.name), event);
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
pub enum EventType {
Emit,
Broadcast,
}
pub struct Context<T> {
phantom: PhantomData<T>,
pub id: String,
pub broker: ServiceBroker,
pub node_id: String,
pub action: Option<String>,
pub event_name: Option<String>,
pub event_type: Option<EventType>,
pub event_groups: Vec<String>,
pub caller: Option<String>,
pub request_id: Option<String>,
pub parent_id: Option<String>,
pub params: Value,
pub meta: Value,
pub locals: Option<Value>,
pub level: i32,
}
impl Context<Event> {
pub(crate) fn new(event_message: EventMessage, service_broker: ServiceBroker) -> Self {
let event_type = if event_message.broadcast.unwrap_or(false) {
EventType::Broadcast
} else {
EventType::Emit
};
Self {
phantom: PhantomData,
broker: service_broker,
id: event_message.id,
params: event_message.data,
action: None,
event_type: Some(event_type),
event_name: Some(event_message.event),
event_groups: vec![],
node_id: event_message.sender,
caller: event_message.caller,
parent_id: event_message.parent_id,
request_id: event_message.request_id,
meta: event_message.meta,
level: event_message.level,
locals: None,
}
}
}
impl Context<Action> {
pub(crate) fn new(request_message: RequestMessage, service_broker: ServiceBroker) -> Self {
Self {
phantom: PhantomData,
broker: service_broker,
id: request_message.request_id.clone(),
params: request_message.params,
action: Some(request_message.action),
event_type: None,
event_name: None,
event_groups: vec![],
node_id: request_message.sender,
caller: request_message.caller,
parent_id: request_message.parent_id,
request_id: Some(request_message.request_id),
meta: request_message.meta,
level: 1,
locals: None,
}
}
pub fn reply(&self, params: Value) {
act_zero::send!(self
.broker
.addr
.reply(self.node_id.clone(), self.id.clone(), params));
}
}
impl<T> Context<T> {
pub fn emit<S: Into<String>>(&self, event: S, params: Value) {
self.broker.emit(event, params)
}
pub fn broadcast<S: Into<String>>(&self, event: S, params: Value) {
self.broker.broadcast(event, params)
}
pub async fn call<S: Into<String>>(self, action: S, params: Value) -> Result<Value, Error> {
self.broker.call(action, params).await
}
}