-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhost.rs
More file actions
105 lines (87 loc) · 2.99 KB
/
host.rs
File metadata and controls
105 lines (87 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Host example for wasm-sql guest-app
//!
//! ## Prerequisites
//!
//! 1. Build the guest component:
//! ```bash
//! cd examples/guest-app && cargo build --release --target wasm32-wasip1
//! ```
//!
//! 2. Run the host:
//! ```bash
//! DATABASE_URL="postgres://user:pass@localhost/db" cargo run --example host
//! ```
use std::sync::Arc;
use anyhow::{Context, Result};
use wasm_sql::SqlHostStateView;
use wasmtime::component::{Component, Linker, ResourceTable};
use wasmtime::{Config, Engine, Store};
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
use wasm_sql::core::bindings::SqlHostState;
use wasm_sql::sqldb::SqlDB;
use wasm_sql::sqldb::sqlx::postgres::PgPoolOptions;
/// Combined state for wasmtime store
struct HostState {
sql: SqlHostState,
wasi: WasiCtx,
table: ResourceTable,
}
mod bindings {
wasmtime::component::bindgen!({
world: "example:guest-app/app",
path: ["./wit", "./wit/postgres", "./examples/guest-app/wit"],
});
}
impl WasiView for HostState {
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
ctx: &mut self.wasi,
table: &mut self.table,
}
}
}
impl SqlHostStateView for HostState {
fn sql_host_state(&mut self) -> &mut SqlHostState {
&mut self.sql
}
}
#[tokio::main]
async fn main() -> Result<()> {
// Connect to database
let database_url =
std::env::var("DATABASE_URL").expect("DATABASE_URL variable is not set");
println!("Connecting to database: {}", database_url);
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await
.context("Failed to connect to database")?;
let sql_db = Arc::new(SqlDB::new(pool));
// Set up wasmtime
let mut config = Config::new();
config.async_support(true);
config.wasm_component_model(true);
config.wasm_component_model_async(true);
let engine = Engine::new(&config)?;
let mut linker: Linker<HostState> = Linker::new(&engine);
wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
wasm_sql::add_to_linker(&mut linker)?;
// Load the guest component
let wasm_path = "target/wasm32-wasip2/debug/wasm_sql_guest_app_example.wasm";
println!("Loading component from: {}", wasm_path);
let component = Component::from_file(&engine, wasm_path)
.context("Failed to load WASM component. Did you build guest-app?")?;
// Create store with state
let state = HostState {
sql: SqlHostState::new(sql_db),
wasi: WasiCtxBuilder::new().inherit_stdio().build(),
table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);
let instance = bindings::App::instantiate_async(&mut store, &component, &mut linker).await.expect("failed to instantiate guest-app");
let _ = store.run_concurrent(async move |accessor| {
let _ = instance.example_guest_app_main().call_run(accessor).await;
}).await;
println!("Guest executed successfully!");
Ok(())
}