use async_trait::async_trait;
use axum::{extract::rejection::PathRejection, http::StatusCode, response::IntoResponse};
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt::Display, sync::Arc};
use self::context_client::ActorContextClient;
pub use axum;
pub mod context_client;
pub mod runtime;
pub type ActorFactory = Box<dyn Fn(&str, &str, ActorContextClient) -> Arc<dyn Actor> + Send + Sync>;
#[async_trait]
pub trait Actor: Send + Sync {
async fn on_activate(&self) -> Result<(), ActorError>;
async fn on_deactivate(&self) -> Result<(), ActorError>;
async fn on_reminder(&self, _reminder_name: &str, _data: Vec<u8>) -> Result<(), ActorError>;
async fn on_timer(&self, _timer_name: &str, _data: Vec<u8>) -> Result<(), ActorError>;
}
#[derive(Debug)]
pub enum ActorError {
NotRegistered,
CorruptedState,
MethodNotFound,
ActorNotFound,
MethodError(Box<dyn Error>),
SerializationError(),
}
impl Display for ActorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ActorError::NotRegistered => write!(f, "Actor not registered"),
ActorError::CorruptedState => write!(f, "Actor state corrupted"),
ActorError::MethodNotFound => write!(f, "Method not found"),
ActorError::ActorNotFound => write!(f, "Actor not found"),
ActorError::MethodError(e) => write!(f, "Method error: {e}"),
ActorError::SerializationError() => write!(f, "Serialization error"),
}
}
}
impl IntoResponse for ActorError {
fn into_response(self) -> axum::response::Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
axum::Json(self.to_string()),
)
.into_response()
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ActorPath {
pub actor_id: String,
}
pub enum ActorRejection {
ActorError(String),
Path(PathRejection),
}
impl IntoResponse for ActorRejection {
fn into_response(self) -> axum::response::Response {
match self {
ActorRejection::ActorError(e) => {
(StatusCode::INTERNAL_SERVER_ERROR, axum::Json(e)).into_response()
}
ActorRejection::Path(e) => {
(StatusCode::BAD_REQUEST, axum::Json(e.body_text())).into_response()
}
}
}
}
#[cfg(test)]
mod tests;