feat: allow process from external code
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
21a13f3444
commit
355587234e
@ -1,7 +1,7 @@
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use component::churn_tasks::process::HostProcess;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use std::path::PathBuf;
|
use std::sync::Arc;
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use wasmtime::component::*;
|
use wasmtime::component::*;
|
||||||
@ -10,10 +10,40 @@ use wasmtime_wasi::{DirPerms, FilePerms, WasiCtx, WasiCtxBuilder, WasiView};
|
|||||||
|
|
||||||
wasmtime::component::bindgen!({
|
wasmtime::component::bindgen!({
|
||||||
path: "wit/world.wit",
|
path: "wit/world.wit",
|
||||||
world: "churn",
|
//world: "churn",
|
||||||
async: true
|
async: true,
|
||||||
|
with: {
|
||||||
|
"component:churn-tasks/process/process": CustomProcess
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CustomProcess {}
|
||||||
|
impl CustomProcess {
|
||||||
|
pub fn run(&self, args: Vec<String>) -> String {
|
||||||
|
tracing::info!("calling function");
|
||||||
|
|
||||||
|
match args.split_first() {
|
||||||
|
Some((item, rest)) => {
|
||||||
|
let mut cmd = std::process::Command::new(item);
|
||||||
|
match cmd.args(rest).output() {
|
||||||
|
Ok(output) => std::str::from_utf8(&output.stdout)
|
||||||
|
.expect("to be able to parse utf8")
|
||||||
|
.to_string(),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("command failed with output: {e}");
|
||||||
|
e.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
tracing::warn!("failed to call function because it is empty");
|
||||||
|
panic!("failed to call function because it is empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PluginStore {
|
pub struct PluginStore {
|
||||||
inner: Arc<Mutex<InnerPluginStore>>,
|
inner: Arc<Mutex<InnerPluginStore>>,
|
||||||
@ -53,6 +83,12 @@ impl InnerPluginStore {
|
|||||||
|
|
||||||
// Add the command world (aka WASI CLI) to the linker
|
// Add the command world (aka WASI CLI) to the linker
|
||||||
wasmtime_wasi::add_to_linker_async(&mut linker).context("Failed to link command world")?;
|
wasmtime_wasi::add_to_linker_async(&mut linker).context("Failed to link command world")?;
|
||||||
|
|
||||||
|
component::churn_tasks::process::add_to_linker(
|
||||||
|
&mut linker,
|
||||||
|
|state: &mut ServerWasiView| state,
|
||||||
|
)?;
|
||||||
|
|
||||||
let wasi_view = ServerWasiView::new();
|
let wasi_view = ServerWasiView::new();
|
||||||
let store = Store::new(&engine, wasi_view);
|
let store = Store::new(&engine, wasi_view);
|
||||||
|
|
||||||
@ -130,7 +166,8 @@ impl InnerPluginStore {
|
|||||||
);
|
);
|
||||||
let instance = Churn::instantiate_async(&mut self.store, &component, &self.linker)
|
let instance = Churn::instantiate_async(&mut self.store, &component, &self.linker)
|
||||||
.await
|
.await
|
||||||
.context("Failed to instantiate the example world")?;
|
.context("Failed to instantiate the example world")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
@ -139,6 +176,7 @@ impl InnerPluginStore {
|
|||||||
struct ServerWasiView {
|
struct ServerWasiView {
|
||||||
table: ResourceTable,
|
table: ResourceTable,
|
||||||
ctx: WasiCtx,
|
ctx: WasiCtx,
|
||||||
|
processes: ResourceTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerWasiView {
|
impl ServerWasiView {
|
||||||
@ -153,7 +191,11 @@ impl ServerWasiView {
|
|||||||
.expect("to be able to open root")
|
.expect("to be able to open root")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Self { table, ctx }
|
Self {
|
||||||
|
table,
|
||||||
|
ctx,
|
||||||
|
processes: ResourceTable::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,3 +208,32 @@ impl WasiView for ServerWasiView {
|
|||||||
&mut self.ctx
|
&mut self.ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl component::churn_tasks::process::Host for ServerWasiView {}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl HostProcess for ServerWasiView {
|
||||||
|
async fn new(
|
||||||
|
&mut self,
|
||||||
|
) -> wasmtime::component::Resource<component::churn_tasks::process::Process> {
|
||||||
|
self.processes.push(CustomProcess::default()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_process(
|
||||||
|
&mut self,
|
||||||
|
self_: wasmtime::component::Resource<component::churn_tasks::process::Process>,
|
||||||
|
inputs: wasmtime::component::__internal::Vec<String>,
|
||||||
|
) -> String {
|
||||||
|
let process = self.processes.get(&self_).unwrap();
|
||||||
|
process.run(inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn drop(
|
||||||
|
&mut self,
|
||||||
|
rep: wasmtime::component::Resource<component::churn_tasks::process::Process>,
|
||||||
|
) -> wasmtime::Result<()> {
|
||||||
|
self.processes.delete(rep)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package component:churn-tasks@0.1.0;
|
package component:churn-tasks@0.1.0;
|
||||||
|
|
||||||
|
interface process {
|
||||||
|
resource process {
|
||||||
|
constructor();
|
||||||
|
run-process: func(inputs: list<string>) -> string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface task {
|
interface task {
|
||||||
id: func() -> string;
|
id: func() -> string;
|
||||||
should-run: func() -> bool;
|
should-run: func() -> bool;
|
||||||
@ -8,4 +15,5 @@ interface task {
|
|||||||
|
|
||||||
world churn {
|
world churn {
|
||||||
export task;
|
export task;
|
||||||
|
import process;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user