feat: add http client
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-01-10 21:42:20 +01:00
parent efec76d28c
commit 8923c60d9e
6 changed files with 242 additions and 163 deletions

View File

@@ -18,6 +18,7 @@ impl Plan {
Ok(vec![
AptTask::new().into_task(),
PluginTask::new("alloy@0.1.0", self.store.clone()).into_task(),
PluginTask::new("dev_packages@0.1.0", self.store.clone()).into_task(),
])
}
}

View File

@@ -8,7 +8,6 @@ use wasmtime::component::*;
use wasmtime::{Config, Engine, Store};
use wasmtime_wasi::{DirPerms, FilePerms, WasiCtx, WasiCtxBuilder, WasiView};
use super::agent_state::State;
use super::config::AgentConfig;
wasmtime::component::bindgen!({
@@ -16,10 +15,13 @@ wasmtime::component::bindgen!({
//world: "churn",
async: true,
with: {
"component:churn-tasks/process/process": CustomProcess
"component:churn-tasks/process/process": CustomProcess,
"component:churn-tasks/http/client": http::HttpClient
}
});
mod http;
pub struct CustomProcess {
agent_config: AgentConfig,
}
@@ -75,6 +77,10 @@ impl PluginStore {
pub async fn execute(&self, plugin: &str) -> anyhow::Result<()> {
let mut inner = self.inner.lock().await;
// FIXME: hack to avoid memory leak issues from instantiating plugins
*inner = InnerPluginStore::new(inner.agent_config.clone())?;
inner.execute(plugin).await
}
}
@@ -83,6 +89,7 @@ pub struct InnerPluginStore {
store: wasmtime::Store<ServerWasiView>,
linker: wasmtime::component::Linker<ServerWasiView>,
engine: wasmtime::Engine,
agent_config: AgentConfig,
}
impl InnerPluginStore {
@@ -101,13 +108,18 @@ impl InnerPluginStore {
|state: &mut ServerWasiView| state,
)?;
let wasi_view = ServerWasiView::new(agent_config);
component::churn_tasks::http::add_to_linker(&mut linker, |state: &mut ServerWasiView| {
state
})?;
let wasi_view = ServerWasiView::new(agent_config.clone());
let store = Store::new(&engine, wasi_view);
Ok(Self {
store,
linker,
engine,
agent_config,
})
}
@@ -124,6 +136,8 @@ impl InnerPluginStore {
pub async fn execute(&mut self, plugin: &str) -> anyhow::Result<()> {
let plugin = self.ensure_plugin(plugin).await?;
self.store.gc_async().await;
if plugin
.interface0
.call_should_run(&mut self.store)
@@ -205,6 +219,7 @@ struct ServerWasiView {
table: ResourceTable,
ctx: WasiCtx,
processes: ResourceTable,
clients: ResourceTable,
agent_config: AgentConfig,
}
@@ -215,6 +230,7 @@ impl ServerWasiView {
let ctx = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_stdout()
.inherit_env()
.inherit_stderr()
.inherit_network()
.preopened_dir("/", "/", DirPerms::all(), FilePerms::all())
@@ -225,6 +241,7 @@ impl ServerWasiView {
table,
ctx,
processes: ResourceTable::default(),
clients: ResourceTable::default(),
agent_config,
}
}
@@ -279,3 +296,33 @@ impl HostProcess for ServerWasiView {
Ok(())
}
}
impl component::churn_tasks::http::Host for ServerWasiView {}
#[async_trait::async_trait]
impl component::churn_tasks::http::HostClient for ServerWasiView {
async fn new(&mut self) -> wasmtime::component::Resource<component::churn_tasks::http::Client> {
self.clients.push(http::HttpClient::new()).unwrap()
}
async fn get(
&mut self,
self_: wasmtime::component::Resource<component::churn_tasks::http::Client>,
url: wasmtime::component::__internal::String,
) -> Vec<u8> {
let process = self.clients.get(&self_).unwrap();
process
.get(&url)
.await
.expect("to be able to make http call")
}
async fn drop(
&mut self,
rep: wasmtime::component::Resource<component::churn_tasks::http::Client>,
) -> wasmtime::Result<()> {
self.clients.delete(rep)?;
Ok(())
}
}

View File

@@ -0,0 +1,12 @@
pub struct HttpClient {}
impl HttpClient {
pub fn new() -> Self {
Self {}
}
pub async fn get(&self, url: &str) -> anyhow::Result<Vec<u8>> {
let bytes = reqwest::get(url).await?.bytes().await?;
Ok(bytes.into())
}
}

View File

@@ -8,6 +8,13 @@ interface process {
}
}
interface http {
resource client {
constructor();
get: func(url: string) -> list<u8>;
}
}
interface task {
id: func() -> string;
should-run: func() -> bool;
@@ -17,4 +24,5 @@ interface task {
world churn {
export task;
import process;
import http;
}