use concepts::StrVariant;
use std::{error::Error, path::PathBuf, sync::Arc};
use utils::wasm_tools::{self};
use wasmtime::Engine;
pub mod activity_worker;
pub mod component_detector;
pub mod epoch_ticker;
mod event_history;
mod workflow_ctx;
pub mod workflow_worker;
#[derive(Clone)]
pub struct EngineConfig {
pub allocation_strategy: wasmtime::InstanceAllocationStrategy,
}
impl Default for EngineConfig {
fn default() -> Self {
Self {
allocation_strategy: wasmtime::InstanceAllocationStrategy::pooling(),
}
}
}
#[derive(thiserror::Error, Debug)]
pub enum WasmFileError {
#[error("cannot read wasm component from `{0}` - {1}")]
CannotReadComponent(PathBuf, wasmtime::Error),
#[error("cannot decode `{0}` - {1}")]
DecodeError(PathBuf, wasm_tools::DecodeError),
#[error("cannot link `{file}` - {reason}, details: {err}")]
LinkingError {
file: PathBuf,
reason: StrVariant,
err: Box<dyn Error + Send + Sync>,
},
}
pub struct Engines {
pub activity_engine: Arc<Engine>,
pub workflow_engine: Arc<Engine>,
}
impl Engines {
#[must_use]
pub fn new(engine_config: EngineConfig) -> Self {
Engines {
activity_engine: activity_worker::get_activity_engine(engine_config.clone()),
workflow_engine: workflow_worker::get_workflow_engine(engine_config),
}
}
}
#[cfg(test)]
pub(crate) mod tests {
use crate::component_detector::ComponentDetector;
use chrono::{DateTime, Utc};
use concepts::{
storage::{Component, ComponentWithMetadata, DbConnection},
ComponentId, ComponentType, FunctionFqn, ParameterTypes,
};
use std::path::Path;
pub(crate) async fn component_add_dummy<DB: DbConnection>(
db_connection: &DB,
created_at: DateTime<Utc>,
ffqn: FunctionFqn,
) {
db_connection
.component_add(
created_at,
ComponentWithMetadata {
component: Component {
component_id: ComponentId::new(
concepts::HashType::Sha256,
ulid::Ulid::new().to_string(),
),
component_type: ComponentType::WasmActivity,
config: serde_json::Value::String(String::new()),
file_name: String::new(),
},
exports: vec![(ffqn, ParameterTypes::default(), None)],
imports: vec![],
},
true,
)
.await
.unwrap();
}
pub(crate) async fn component_add_real<DB: DbConnection>(
db_connection: &DB,
created_at: DateTime<Utc>,
wasm_path: impl AsRef<Path>,
) {
let wasm_path = wasm_path.as_ref();
let file_name = wasm_path
.file_name()
.unwrap()
.to_string_lossy()
.into_owned();
let component_id = crate::component_detector::hash(wasm_path).unwrap();
let engine = ComponentDetector::get_engine();
let detected = ComponentDetector::new(wasm_path, &engine).unwrap();
let config = serde_json::Value::String("fake, not deserialized in tests".to_string());
let component = ComponentWithMetadata {
component: Component {
component_id,
component_type: detected.component_type,
config,
file_name,
},
exports: detected.exports,
imports: detected.imports,
};
db_connection
.component_add(created_at, component, true)
.await
.unwrap();
}
}