use super::activity_worker::ActivityConfig;
use crate::component_logger::{ComponentLogger, LogStrageConfig, log_activities};
use crate::http_hooks::{HttpClientTracesContainer, HttpHooks};
use crate::policy_builder::build_http_policy;
use crate::std_output_stream::{LogStream, StdOutput};
use concepts::storage::LogLevel;
use concepts::time::ClockFn;
use executor::worker::WorkerContext;
use wasmtime::Engine;
use wasmtime::{Store, component::ResourceTable};
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpCtxView, WasiHttpView};
use wasmtime_wasi_io::IoView;
pub struct ActivityCtx {
table: ResourceTable,
wasi_ctx: WasiCtx,
http_ctx: WasiHttpCtx,
component_logger: ComponentLogger,
pub(crate) http_hooks: HttpHooks,
}
impl wasmtime::component::HasData for ActivityCtx {
type Data<'a> = &'a mut ActivityCtx;
}
impl WasiView for ActivityCtx {
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
ctx: &mut self.wasi_ctx,
table: &mut self.table,
}
}
}
impl IoView for ActivityCtx {
fn table(&mut self) -> &mut ResourceTable {
&mut self.table
}
}
impl WasiHttpView for ActivityCtx {
fn http(&mut self) -> WasiHttpCtxView<'_> {
WasiHttpCtxView {
ctx: &mut self.http_ctx,
table: &mut self.table,
hooks: &mut self.http_hooks,
}
}
}
pub(crate) fn store(
engine: &Engine,
ctx: WorkerContext,
config: &ActivityConfig,
clock_fn: Box<dyn ClockFn>,
stdout: Option<StdOutput>,
stderr: Option<StdOutput>,
logs_storage_config: Option<LogStrageConfig>,
) -> Store<ActivityCtx> {
let execution_id = ctx.execution_id;
let run_id = ctx.locked_event.run_id;
let mut wasi_ctx = WasiCtxBuilder::new();
if let Some(stdout) = stdout {
let stdout = LogStream::new(
format!(
"[{component_id} {execution_id} stdout]",
component_id = config.component_id
),
stdout,
);
wasi_ctx.stdout(stdout);
}
if let Some(stderr) = stderr {
let stderr = LogStream::new(
format!(
"[{component_id} {execution_id} stderr]",
component_id = config.component_id
),
stderr,
);
wasi_ctx.stderr(stderr);
}
for env_var in config.env_vars.iter() {
wasi_ctx.env(&env_var.key, &env_var.val);
}
let http_policy = build_http_policy(
&config.allowed_hosts,
&config.global_http_config,
config.secrets.as_ref(),
&mut wasi_ctx,
);
let component_logger = ComponentLogger {
span: ctx.worker_span,
execution_id,
run_id,
logs_storage_config,
};
let ctx = ActivityCtx {
table: ResourceTable::new(),
wasi_ctx: wasi_ctx.build(),
http_ctx: WasiHttpCtx::new(),
http_hooks: HttpHooks {
clock_fn,
http_client_traces: HttpClientTracesContainer::default(),
http_policy,
component_logger: component_logger.clone(),
config_section_hint: config.config_section_hint,
},
component_logger,
};
Store::new(engine, ctx)
}
impl log_activities::obelisk::log::log::Host for ActivityCtx {
async fn trace(&mut self, message: String) {
self.component_logger.log(LogLevel::Trace, message);
}
async fn debug(&mut self, message: String) {
self.component_logger.log(LogLevel::Debug, message);
}
async fn info(&mut self, message: String) {
self.component_logger.log(LogLevel::Info, message);
}
async fn warn(&mut self, message: String) {
self.component_logger.log(LogLevel::Warn, message);
}
async fn error(&mut self, message: String) {
self.component_logger.log(LogLevel::Error, message);
}
}