use crate::actor::handle::ActorHandle;
use crate::chain::{ChainEvent, StateChain};
use crate::events::{ChainEventData, ChainEventPayload};
use crate::id::TheaterId;
use crate::messages::TheaterCommand;
use crate::pack_bridge::Value;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use tokio::sync::mpsc::Sender;
use wasmtime::component::ResourceTable;
#[derive(Clone)]
pub struct ActorStore {
pub id: TheaterId,
pub theater_tx: Sender<TheaterCommand>,
pub chain: Arc<RwLock<StateChain>>,
pub state: Value,
pub actor_handle: ActorHandle,
pub resource_table: Arc<Mutex<ResourceTable>>,
pub extensions: Arc<RwLock<HashMap<TypeId, Box<dyn Any + Send + Sync>>>>,
}
impl ActorStore {
pub fn new(
id: TheaterId,
theater_tx: Sender<TheaterCommand>,
actor_handle: ActorHandle,
chain: Arc<RwLock<StateChain>>,
initial_state: Value,
) -> Self {
Self {
id,
theater_tx: theater_tx.clone(),
chain,
state: initial_state,
actor_handle,
resource_table: Arc::new(Mutex::new(ResourceTable::new())),
extensions: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn get_id(&self) -> TheaterId {
self.id
}
pub fn get_theater_tx(&self) -> Sender<TheaterCommand> {
self.theater_tx.clone()
}
pub fn get_state(&self) -> Value {
self.state.clone()
}
pub fn set_state(&mut self, state: Value) {
self.state = state;
}
pub fn record_event(&self, event_data: ChainEventData) -> ChainEvent {
let mut chain = self.chain.write().unwrap();
chain
.add_typed_event(event_data)
.expect("Failed to record event")
}
pub fn record_wasm_event(
&self,
event_type: String,
data: crate::events::wasm::WasmEventData,
) -> ChainEvent {
self.record_event(ChainEventData {
event_type,
data: ChainEventPayload::Wasm(data),
})
}
pub fn record_theater_runtime_event(
&self,
event_type: String,
data: crate::events::theater_runtime::TheaterRuntimeEventData,
) -> ChainEvent {
let wasm_data = crate::events::wasm::WasmEventData::WasmCall {
function_name: event_type.clone(),
params: Value::String(serde_json::to_string(&data).unwrap_or_default()),
};
self.record_event(ChainEventData {
event_type: format!("theater-runtime/{}", event_type),
data: ChainEventPayload::Wasm(wasm_data),
})
}
pub fn verify_chain(&self) -> bool {
let chain = self.chain.read().unwrap();
chain.verify()
}
pub fn get_last_event(&self) -> Option<ChainEvent> {
let chain = self.chain.read().unwrap();
chain.get_last_event().cloned()
}
pub fn get_all_events(&self) -> Vec<ChainEvent> {
let chain = self.chain.read().unwrap();
chain.get_events().to_vec()
}
pub fn get_chain(&self) -> Vec<ChainEvent> {
self.get_all_events()
}
pub fn subscribe_to_events(&self) -> tokio::sync::broadcast::Receiver<ChainEvent> {
let chain = self.chain.read().unwrap();
chain.subscribe()
}
pub fn save_chain(&self) -> anyhow::Result<()> {
let chain = self.chain.read().unwrap();
chain.save_chain()?;
Ok(())
}
pub fn get_actor_handle(&self) -> ActorHandle {
self.actor_handle.clone()
}
pub fn set_extension<T: Send + Sync + 'static>(&self, value: T) {
let mut extensions = self.extensions.write().unwrap();
extensions.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn get_extension<T: Clone + Send + Sync + 'static>(&self) -> Option<T> {
let extensions = self.extensions.read().unwrap();
extensions
.get(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_ref::<T>())
.cloned()
}
pub fn has_extension<T: Send + Sync + 'static>(&self) -> bool {
let extensions = self.extensions.read().unwrap();
extensions.contains_key(&TypeId::of::<T>())
}
pub fn remove_extension<T: Send + Sync + 'static>(&self) -> Option<T> {
let mut extensions = self.extensions.write().unwrap();
extensions
.remove(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast::<T>().ok())
.map(|b| *b)
}
pub fn get_events_by_type(&self, event_type: &str) -> Vec<ChainEvent> {
let chain = self.chain.read().unwrap();
chain
.get_events()
.iter()
.filter(|e| e.event_type == event_type)
.cloned()
.collect()
}
pub fn get_recent_events(&self, count: usize) -> Vec<ChainEvent> {
let chain = self.chain.read().unwrap();
let events = chain.get_events();
events.iter().rev().take(count).cloned().collect()
}
pub fn has_event_type(&self, event_type: &str) -> bool {
let chain = self.chain.read().unwrap();
chain
.get_events()
.iter()
.any(|e| e.event_type == event_type)
}
}