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
914use wasmtime:: component:: ResourceTable ;
1015use wasmtime_wasi:: { WasiCtx , WasiCtxBuilder , WasiCtxView , WasiView } ;
1116use wasmtime_wasi_http:: { WasiHttpCtx , WasiHttpView } ;
1217
1318use 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 }
0 commit comments