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 as StdRwLock};
use tokio::sync::mpsc::Sender;
use tokio::sync::RwLock;
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<StdRwLock<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(StdRwLock::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 async fn record_event(&self, event_data: ChainEventData) -> ChainEvent {
let mut chain = self.chain.write().await;
chain
.add_typed_event(event_data)
.await
.expect("Failed to record event")
}
pub async fn record_wasm_event(
&self,
event_type: String,
data: crate::events::wasm::WasmEventData,
) -> ChainEvent {
self.record_event(ChainEventData {
event_type,
data: ChainEventPayload::Wasm(data),
})
.await
}
pub async 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),
})
.await
}
pub async fn head_hash(&self) -> Option<Vec<u8>> {
let chain = self.chain.read().await;
chain.head_hash().map(|h| h.to_vec())
}
pub async fn subscribe_to_events(
&self,
tx: tokio::sync::mpsc::Sender<(crate::TheaterId, ChainEvent)>,
) {
let mut chain = self.chain.write().await;
chain.add_subscriber(tx);
}
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)
}
}