Skip to content

Commit 391848d

Browse files
committed
fix(rt): incorrect Ctx for inter-component call
Signed-off-by: if0ne <pavel.agafonov.al@gmail.com>
1 parent db332aa commit 391848d

File tree

17 files changed

+277
-129
lines changed

17 files changed

+277
-129
lines changed

crates/wash-runtime/src/engine/ctx.rs

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,83 @@
44
//! for wasmtime when executing WebAssembly components. It integrates WASI
55
//! interfaces, HTTP capabilities, and plugin access into a unified context.
66
7-
use std::{any::Any, collections::HashMap, sync::Arc};
7+
use std::{
8+
any::Any,
9+
collections::HashMap,
10+
ops::{Deref, DerefMut},
11+
sync::Arc,
12+
};
813

914
use wasmtime::component::ResourceTable;
1015
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
1116
use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView};
1217

1318
use crate::plugin::HostPlugin;
1419

20+
/// Shared context
21+
pub struct SharedCtx {
22+
/// Current active context
23+
pub active_ctx: Ctx,
24+
/// The resource table used to manage resources in the Wasmtime store.
25+
pub table: wasmtime::component::ResourceTable,
26+
/// Contexts for linked components
27+
pub contexts: HashMap<Arc<str>, Ctx>,
28+
}
29+
30+
impl SharedCtx {
31+
pub fn new(context: Ctx) -> Self {
32+
Self {
33+
active_ctx: context,
34+
table: ResourceTable::new(),
35+
contexts: Default::default(),
36+
}
37+
}
38+
39+
pub fn set_active_ctx(&mut self, id: &Arc<str>) -> anyhow::Result<()> {
40+
if id == &self.active_ctx.component_id {
41+
return Ok(());
42+
}
43+
44+
if let Some(ctx) = self.contexts.remove(id) {
45+
let old_ctx = std::mem::replace(&mut self.active_ctx, ctx);
46+
self.contexts.insert(old_ctx.component_id.clone(), old_ctx);
47+
Ok(())
48+
} else {
49+
Err(anyhow::anyhow!("Context for component {id} not found"))
50+
}
51+
}
52+
}
53+
54+
impl wasmtime::component::HasData for SharedCtx {
55+
type Data<'a> = ActiveCtx<'a>;
56+
}
57+
58+
pub fn extract_active_ctx(ctx: &mut SharedCtx) -> ActiveCtx<'_> {
59+
ActiveCtx {
60+
table: &mut ctx.table,
61+
ctx: &mut ctx.active_ctx,
62+
}
63+
}
64+
65+
pub struct ActiveCtx<'a> {
66+
pub table: &'a mut wasmtime::component::ResourceTable,
67+
pub ctx: &'a mut Ctx,
68+
}
69+
70+
impl<'a> Deref for ActiveCtx<'a> {
71+
type Target = Ctx;
72+
73+
fn deref(&self) -> &Self::Target {
74+
self.ctx
75+
}
76+
}
77+
78+
impl<'a> DerefMut for ActiveCtx<'a> {
79+
fn deref_mut(&mut self) -> &mut Self::Target {
80+
self.ctx
81+
}
82+
}
83+
1584
/// The context for a component store and linker, providing access to implementations of:
1685
/// - wasi@0.2 interfaces
1786
/// - wasi:http@0.2 interfaces
@@ -22,8 +91,6 @@ pub struct Ctx {
2291
pub component_id: Arc<str>,
2392
/// The unique identifier for the workload this component belongs to
2493
pub workload_id: Arc<str>,
25-
/// The resource table used to manage resources in the Wasmtime store.
26-
pub table: wasmtime::component::ResourceTable,
2794
/// The WASI context used to provide WASI functionality to the components using this context.
2895
pub ctx: WasiCtx,
2996
/// The HTTP context used to provide HTTP functionality to the component.
@@ -56,31 +123,30 @@ impl std::fmt::Debug for Ctx {
56123
f.debug_struct("Ctx")
57124
.field("id", &self.id)
58125
.field("workload_id", &self.workload_id.as_ref())
59-
.field("table", &self.table)
60126
.finish()
61127
}
62128
}
63129

64130
// TODO(#103): Do some cleverness to pull up the WasiCtx based on what component is actively executing
65-
impl WasiView for Ctx {
131+
impl WasiView for SharedCtx {
66132
fn ctx(&mut self) -> WasiCtxView<'_> {
67133
WasiCtxView {
68-
ctx: &mut self.ctx,
134+
ctx: &mut self.active_ctx.ctx,
69135
table: &mut self.table,
70136
}
71137
}
72138
}
73139

74-
impl wasmtime_wasi_io::IoView for Ctx {
140+
impl wasmtime_wasi_io::IoView for SharedCtx {
75141
fn table(&mut self) -> &mut wasmtime_wasi::ResourceTable {
76142
&mut self.table
77143
}
78144
}
79145

80146
// Implement WasiHttpView for wasi:http@0.2
81-
impl WasiHttpView for Ctx {
147+
impl WasiHttpView for SharedCtx {
82148
fn ctx(&mut self) -> &mut WasiHttpCtx {
83-
&mut self.http
149+
&mut self.active_ctx.http
84150
}
85151

86152
fn table(&mut self) -> &mut ResourceTable {
@@ -92,8 +158,10 @@ impl WasiHttpView for Ctx {
92158
request: hyper::Request<wasmtime_wasi_http::body::HyperOutgoingBody>,
93159
config: wasmtime_wasi_http::types::OutgoingRequestConfig,
94160
) -> wasmtime_wasi_http::HttpResult<wasmtime_wasi_http::types::HostFutureIncomingResponse> {
95-
match &self.http_handler {
96-
Some(handler) => handler.outgoing_request(&self.workload_id, request, config),
161+
match &self.active_ctx.http_handler {
162+
Some(handler) => {
163+
handler.outgoing_request(&self.active_ctx.workload_id, request, config)
164+
}
97165
None => Err(wasmtime_wasi_http::HttpError::trap(anyhow::anyhow!(
98166
"http client not available"
99167
))),
@@ -162,7 +230,6 @@ impl CtxBuilder {
162230
workload_id: self.workload_id,
163231
component_id: self.component_id,
164232
http: WasiHttpCtx::new(),
165-
table: ResourceTable::new(),
166233
plugins,
167234
http_handler: self.http_handler,
168235
}

crates/wash-runtime/src/engine/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use anyhow::{Context, bail};
4343
use wasmtime::PoolingAllocationConfig;
4444
use wasmtime::component::{Component, Linker};
4545

46-
use crate::engine::ctx::Ctx;
46+
use crate::engine::ctx::SharedCtx;
4747
use crate::engine::workload::{UnresolvedWorkload, WorkloadComponent, WorkloadService};
4848
use crate::types::{EmptyDirVolume, HostPathVolume, VolumeType, Workload};
4949
use std::path::PathBuf;
@@ -204,7 +204,7 @@ impl Engine {
204204
.context("failed to create component from bytes")?;
205205

206206
// Create a linker for this component
207-
let mut linker: Linker<Ctx> = Linker::new(&self.inner);
207+
let mut linker: Linker<SharedCtx> = Linker::new(&self.inner);
208208

209209
// Add WASI@0.2 interfaces to the linker
210210
wasmtime_wasi::p2::add_to_linker_async(&mut linker)
@@ -257,7 +257,7 @@ impl Engine {
257257
.context("failed to create component from bytes")?;
258258

259259
// Create a linker for this component
260-
let mut linker: Linker<Ctx> = Linker::new(&self.inner);
260+
let mut linker: Linker<SharedCtx> = Linker::new(&self.inner);
261261

262262
// Add WASI@0.2 interfaces to the linker
263263
wasmtime_wasi::p2::add_to_linker_async(&mut linker)

crates/wash-runtime/src/engine/value.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use tracing::trace;
66
use wasmtime::component::Val;
77
use wasmtime::{AsContextMut, StoreContextMut};
88

9-
use crate::engine::ctx::Ctx;
9+
use crate::engine::ctx::SharedCtx;
1010

11-
pub(crate) fn lower(store: &mut StoreContextMut<'_, Ctx>, v: &Val) -> anyhow::Result<Val> {
11+
pub(crate) fn lower(store: &mut StoreContextMut<SharedCtx>, v: &Val) -> anyhow::Result<Val> {
1212
match v {
1313
&Val::Bool(v) => Ok(Val::Bool(v)),
1414
&Val::S8(v) => Ok(Val::S8(v)),
@@ -126,7 +126,7 @@ pub(crate) fn lower(store: &mut StoreContextMut<'_, Ctx>, v: &Val) -> anyhow::Re
126126
}
127127
}
128128

129-
pub(crate) fn lift(store: &mut StoreContextMut<'_, Ctx>, v: Val) -> anyhow::Result<Val> {
129+
pub(crate) fn lift(store: &mut StoreContextMut<SharedCtx>, v: Val) -> anyhow::Result<Val> {
130130
match v {
131131
Val::Bool(v) => Ok(Val::Bool(v)),
132132
Val::S8(v) => Ok(Val::S8(v)),

0 commit comments

Comments
 (0)