use crate::metrics::ActorMetrics;
use crate::pack_bridge::{InterfaceHash, Value};
use crate::ChainEvent;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use thiserror::Error;
use tokio::sync::oneshot;
use tokio::time::Duration;
use wasmtime::component::{ComponentType, Lift, Lower};
pub const DEFAULT_OPERATION_TIMEOUT: Duration = Duration::from_secs(3000);
#[derive(
Error, Debug, Clone, ComponentType, Lift, Lower, Serialize, Deserialize, PartialEq, Hash, Eq,
)]
#[component(variant)]
pub enum ActorError {
#[error("Operation timed out after {0:?}")]
#[component(name = "operation-timeout")]
OperationTimeout(u64),
#[error("Operation channel closed")]
#[component(name = "channel-closed")]
ChannelClosed,
#[error("Actor is shutting down")]
#[component(name = "shutting-down")]
ShuttingDown,
#[error("Function not found: {0}")]
#[component(name = "function-not-found")]
FunctionNotFound(String),
#[error("Type mismatch for function {0}")]
#[component(name = "type-mismatch")]
TypeMismatch(String),
#[error("Internal error: {0}")]
#[component(name = "internal-error")]
Internal(ChainEvent),
#[error("Unexpected error: {0}")]
#[component(name = "unexpected-error")]
UnexpectedError(String),
#[error("Serialization error")]
#[component(name = "serialization-error")]
SerializationError,
#[error("Failed to update package: {0}")]
#[component(name = "update-package-error")]
UpdatePackageError(String),
#[error("Actor is paused")]
#[component(name = "actor-paused")]
Paused,
#[error("Actor is not paused")]
#[component(name = "actor-not-paused")]
NotPaused,
#[error("Handler error: {0}")]
#[component(name = "handler-error")]
HandlerError(String),
}
#[derive(Debug, Clone, ComponentType, Lift, Lower, Serialize, Deserialize)]
#[component(record)]
pub struct WitActorError {
#[component(name = "error-type")]
error_type: WitErrorType,
data: Option<Vec<u8>>,
}
#[derive(Debug, Clone, ComponentType, Lift, Lower, Serialize, Deserialize, Copy)]
#[component(enum)]
#[repr(u8)]
pub enum WitErrorType {
#[component(name = "operation-timeout")]
OperationTimeout,
#[component(name = "channel-closed")]
ChannelClosed,
#[component(name = "shutting-down")]
ShuttingDown,
#[component(name = "function-not-found")]
FunctionNotFound,
#[component(name = "type-mismatch")]
TypeMismatch,
#[component(name = "internal")]
Internal,
#[component(name = "serialization-error")]
SerializationError,
#[component(name = "update-package-error")]
UpdatePackageError,
#[component(name = "paused")]
Paused,
}
impl From<ActorError> for WitActorError {
fn from(error: ActorError) -> Self {
let (error_type, data) = match error {
ActorError::OperationTimeout(data) => (
WitErrorType::OperationTimeout,
Some(data.to_le_bytes().to_vec()),
),
ActorError::ChannelClosed => (WitErrorType::ChannelClosed, None),
ActorError::ShuttingDown => (WitErrorType::ShuttingDown, None),
ActorError::FunctionNotFound(data) => {
(WitErrorType::FunctionNotFound, Some(data.into_bytes()))
}
ActorError::TypeMismatch(data) => (WitErrorType::TypeMismatch, Some(data.into_bytes())),
ActorError::Internal(data) => (
WitErrorType::Internal,
Some(serde_json::to_vec(&data).unwrap()),
),
ActorError::SerializationError => (WitErrorType::SerializationError, None),
ActorError::UpdatePackageError(data) => {
(WitErrorType::UpdatePackageError, Some(data.into_bytes()))
}
ActorError::Paused => (WitErrorType::Paused, None),
ActorError::NotPaused => (WitErrorType::Paused, None),
ActorError::UnexpectedError(data) => (WitErrorType::Internal, Some(data.into_bytes())),
ActorError::HandlerError(data) => (WitErrorType::Internal, Some(data.into_bytes())),
};
Self { error_type, data }
}
}
#[derive(Debug)]
pub enum ActorOperation {
CallFunctionPack {
name: String,
params: Vec<u8>,
response_tx: oneshot::Sender<Result<Vec<u8>, ActorError>>,
},
HandleWasiHttpRequest {
method: String,
scheme: Option<String>,
authority: Option<String>,
path_with_query: Option<String>,
headers: Vec<(String, Vec<u8>)>,
body: Vec<u8>,
response_tx: oneshot::Sender<Result<WasiHttpResponse, ActorError>>,
},
}
#[derive(Debug, Clone)]
pub struct WasiHttpResponse {
pub status: u16,
pub headers: Vec<(String, Vec<u8>)>,
pub body: Vec<u8>,
}
#[derive(Debug)]
pub enum ActorControl {
Pause {
response_tx: oneshot::Sender<Result<(), ActorError>>,
},
Resume {
response_tx: oneshot::Sender<Result<(), ActorError>>,
},
Shutdown {
response_tx: oneshot::Sender<Result<(), ActorError>>,
},
Terminate {
response_tx: oneshot::Sender<Result<(), ActorError>>,
},
}
#[derive(Debug)]
pub enum ActorInfo {
GetState {
response_tx: oneshot::Sender<Result<Value, ActorError>>,
},
GetChain {
response_tx: oneshot::Sender<Result<Vec<ChainEvent>, ActorError>>,
},
SaveChain {
response_tx: oneshot::Sender<Result<(), ActorError>>,
},
GetMetrics {
response_tx: oneshot::Sender<Result<ActorMetrics, ActorError>>,
},
GetStatus {
response_tx: oneshot::Sender<Result<String, ActorError>>,
},
GetExportHashes {
response_tx: oneshot::Sender<Result<Vec<InterfaceHash>, ActorError>>,
},
}