wasmer_wasix/runners/dcgi/
factory.rs

1use std::sync::{Arc, Mutex};
2
3use virtual_fs::Pipe;
4use wasmer_wasix_types::types::{__WASI_STDERR_FILENO, __WASI_STDIN_FILENO, __WASI_STDOUT_FILENO};
5
6use crate::{
7    WasiStateCreationError,
8    runners::wcgi::{CreateEnvConfig, CreateEnvResult, RecycleEnvConfig},
9    state::conv_env_vars,
10};
11
12use super::*;
13
14#[derive(Debug, Default)]
15struct State {
16    /// Once the instance is running it will
17    instance: Option<DcgiInstance>,
18}
19
20/// This factory will store and reuse instances between invocations thus
21/// allowing for the instances to be stateful.
22#[derive(Debug, Clone, Default)]
23pub struct DcgiInstanceFactory {
24    state: Arc<Mutex<State>>,
25}
26
27impl DcgiInstanceFactory {
28    pub fn new() -> Self {
29        Default::default()
30    }
31
32    pub async fn release(&self, conf: RecycleEnvConfig) {
33        let mut state = self.state.lock().unwrap();
34        state.instance.replace(DcgiInstance {
35            env: conf.env,
36            //memory: conf.memory,
37            //store: conf.store,
38        });
39    }
40
41    pub async fn acquire(&self, conf: &mut CreateEnvConfig) -> Option<CreateEnvResult> {
42        let mut state = self.state.lock().unwrap();
43        if let Some(inst) = state.instance.take() {
44            tracing::debug!("attempting to reinitialize DCGI instance");
45            match convert_instance(inst, conf) {
46                Ok(converted) => return Some(converted),
47                Err(err) => {
48                    tracing::warn!("failed to reinitialize DCGI instance - {}", err);
49                }
50            }
51        }
52
53        None
54    }
55}
56
57fn convert_instance(
58    inst: DcgiInstance,
59    conf: &mut CreateEnvConfig,
60) -> anyhow::Result<CreateEnvResult> {
61    let mut env = inst.env;
62
63    let (req_body_sender, req_body_receiver) = Pipe::channel();
64    let (res_body_sender, res_body_receiver) = Pipe::channel();
65    let (stderr_sender, stderr_receiver) = Pipe::channel();
66
67    env.reinit()?;
68
69    // Replace the environment variables as these will change
70    // depending on the WCGI call
71    *env.state.envs.lock().unwrap() = conv_env_vars(
72        conf.env
73            .iter()
74            .map(|(k, v)| (k.clone(), v.as_bytes().to_vec()))
75            .collect(),
76    );
77
78    // The stdio have to be reattached on each call as they are
79    // read to completion (EOF) during nominal flows
80    env.state
81        .fs
82        .swap_file(__WASI_STDIN_FILENO, Box::new(req_body_receiver))
83        .map_err(WasiStateCreationError::FileSystemError)?;
84
85    env.state
86        .fs
87        .swap_file(__WASI_STDOUT_FILENO, Box::new(res_body_sender))
88        .map_err(WasiStateCreationError::FileSystemError)?;
89
90    env.state
91        .fs
92        .swap_file(__WASI_STDERR_FILENO, Box::new(stderr_sender))
93        .map_err(WasiStateCreationError::FileSystemError)?;
94
95    Ok(CreateEnvResult {
96        env,
97        //memory: Some((inst.memory, inst.store)),
98        memory: None,
99        body_sender: req_body_sender,
100        body_receiver: res_body_receiver,
101        stderr_receiver,
102    })
103}