1use std::fmt;
16use std::fmt::{Display, Formatter};
17use std::str::FromStr;
18
19#[cfg(test)]
20test_r::enable!();
21
22pub use uuid::Uuid;
23
24pub mod bindings {
25 use wit_bindgen::generate;
26
27 generate!({
28 path: "wit",
29 world: "golem-rust",
30 generate_all,
31 generate_unused_types: true,
32 pub_export_macro: true,
33 with: {
34 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
35 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
36 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock
37 }
38 });
39}
40
41#[cfg(feature = "export_load_snapshot")]
42pub mod load_snapshot {
43 use wit_bindgen::generate;
44
45 generate!({
46 path: "wit",
47 world: "golem-rust-load-snapshot",
48 generate_all,
49 generate_unused_types: true,
50 pub_export_macro: true,
51 with: {
52 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
53 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
54 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock,
55
56 "golem:api/host@1.3.0": crate::bindings::golem::api::host,
57 "golem:api/oplog@1.3.0": crate::bindings::golem::api::oplog,
58 "golem:api/context@1.3.0": crate::bindings::golem::api::context,
59 "golem:durability/durability@1.3.0": crate::bindings::golem::durability::durability,
60 "golem:rdbms/mysql@0.0.1": crate::bindings::golem::rdbms::mysql,
61 "golem:rdbms/postgres@0.0.1": crate::bindings::golem::rdbms::postgres,
62 "golem:rdbms/types@0.0.1": crate::bindings::golem::rdbms::types,
63 "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
64 "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
65 "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
66 "wasi:clocks/monotonic-clock@0.2.3": crate::bindings::wasi::clocks::monotonic_clock,
67 "wasi:filesystem/preopens@0.2.3": crate::bindings::wasi::filesystem::preopens,
68 "wasi:filesystem/types@0.2.3": crate::bindings::wasi::filesystem::types,
69 "wasi:http/types@0.2.3": crate::bindings::wasi::http::types,
70 "wasi:http/outgoing-handler@0.2.3": crate::bindings::wasi::http::outgoing_handler,
71 "wasi:io/error@0.2.3": crate::bindings::wasi::io::error,
72 "wasi:io/streams@0.2.3": crate::bindings::wasi::io::streams,
73 "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
74 "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
75 "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
76 "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
77 "wasi:logging/logging": crate::bindings::wasi::logging::logging,
78 "wasi:sockets/ip-name-lookup@0.2.3": crate::bindings::wasi::sockets::ip_name_lookup,
79 "wasi:sockets/instance-network@0.2.3": crate::bindings::wasi::sockets::instance_network,
80 "wasi:sockets/network@0.2.3": crate::bindings::wasi::sockets::network,
81 }
82 });
83
84 pub use __export_golem_rust_load_snapshot_impl as export_load_snapshot;
85}
86
87#[cfg(feature = "export_save_snapshot")]
88pub mod save_snapshot {
89 use wit_bindgen::generate;
90
91 generate!({
92 path: "wit",
93 world: "golem-rust-save-snapshot",
94 generate_all,
95 generate_unused_types: true,
96 pub_export_macro: true,
97 with: {
98 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
99 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
100 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock,
101
102 "golem:api/host@1.3.0": crate::bindings::golem::api::host,
103 "golem:api/oplog@1.3.0": crate::bindings::golem::api::oplog,
104 "golem:api/context@1.3.0": crate::bindings::golem::api::context,
105 "golem:durability/durability@1.3.0": crate::bindings::golem::durability::durability,
106 "golem:rdbms/mysql@0.0.1": crate::bindings::golem::rdbms::mysql,
107 "golem:rdbms/postgres@0.0.1": crate::bindings::golem::rdbms::postgres,
108 "golem:rdbms/types@0.0.1": crate::bindings::golem::rdbms::types,
109 "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
110 "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
111 "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
112 "wasi:clocks/monotonic-clock@0.2.3": crate::bindings::wasi::clocks::monotonic_clock,
113 "wasi:filesystem/preopens@0.2.3": crate::bindings::wasi::filesystem::preopens,
114 "wasi:filesystem/types@0.2.3": crate::bindings::wasi::filesystem::types,
115 "wasi:http/types@0.2.3": crate::bindings::wasi::http::types,
116 "wasi:http/outgoing-handler@0.2.3": crate::bindings::wasi::http::outgoing_handler,
117 "wasi:io/error@0.2.3": crate::bindings::wasi::io::error,
118 "wasi:io/streams@0.2.3": crate::bindings::wasi::io::streams,
119 "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
120 "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
121 "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
122 "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
123 "wasi:logging/logging": crate::bindings::wasi::logging::logging,
124 "wasi:sockets/ip-name-lookup@0.2.3": crate::bindings::wasi::sockets::ip_name_lookup,
125 "wasi:sockets/instance-network@0.2.3": crate::bindings::wasi::sockets::instance_network,
126 "wasi:sockets/network@0.2.3": crate::bindings::wasi::sockets::network,
127 }
128 });
129
130 pub use __export_golem_rust_save_snapshot_impl as export_save_snapshot;
131}
132
133#[cfg(feature = "export_golem_agentic")]
134pub mod golem_agentic {
135 use wit_bindgen::generate;
136
137 generate!({
138 path: "wit",
139 world: "golem-agentic",
140 generate_all,
141 generate_unused_types: true,
142 pub_export_macro: true,
143 with: {
144 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
145 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
146 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock,
147
148 "golem:api/host@1.3.0": crate::bindings::golem::api::host,
149 "golem:api/oplog@1.3.0": crate::bindings::golem::api::oplog,
150 "golem:api/context@1.3.0": crate::bindings::golem::api::context,
151 "golem:durability/durability@1.3.0": crate::bindings::golem::durability::durability,
152 "golem:rdbms/mysql@0.0.1": crate::bindings::golem::rdbms::mysql,
153 "golem:rdbms/postgres@0.0.1": crate::bindings::golem::rdbms::postgres,
154 "golem:rdbms/types@0.0.1": crate::bindings::golem::rdbms::types,
155 "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
156 "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
157 "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
158 "wasi:clocks/monotonic-clock@0.2.3": crate::bindings::wasi::clocks::monotonic_clock,
159 "wasi:filesystem/preopens@0.2.3": crate::bindings::wasi::filesystem::preopens,
160 "wasi:filesystem/types@0.2.3": crate::bindings::wasi::filesystem::types,
161 "wasi:http/types@0.2.3": crate::bindings::wasi::http::types,
162 "wasi:http/outgoing-handler@0.2.3": crate::bindings::wasi::http::outgoing_handler,
163 "wasi:io/error@0.2.3": crate::bindings::wasi::io::error,
164 "wasi:io/streams@0.2.3": crate::bindings::wasi::io::streams,
165 "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
166 "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
167 "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
168 "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
169 "wasi:logging/logging": crate::bindings::wasi::logging::logging,
170 "wasi:sockets/ip-name-lookup@0.2.3": crate::bindings::wasi::sockets::ip_name_lookup,
171 "wasi:sockets/instance-network@0.2.3": crate::bindings::wasi::sockets::instance_network,
172 "wasi:sockets/network@0.2.3": crate::bindings::wasi::sockets::network,
173 }
174 });
175
176 pub use __export_golem_agentic_impl as export_golem_agentic;
177}
178
179#[cfg(feature = "golem_ai")]
180pub mod golem_ai {
181 use wit_bindgen::generate;
182 generate!({
183 path: "wit",
184 world: "golem-ai",
185 generate_all,
186 generate_unused_types: true,
187 additional_derives: [crate::Schema],
188 pub_export_macro: true,
189 with: {
190 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
191 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
192 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock,
193
194 "golem:api/host@1.3.0": crate::bindings::golem::api::host,
195 "golem:api/oplog@1.3.0": crate::bindings::golem::api::oplog,
196 "golem:api/context@1.3.0": crate::bindings::golem::api::context,
197 "golem:durability/durability@1.3.0": crate::bindings::golem::durability::durability,
198 "golem:rdbms/mysql@0.0.1": crate::bindings::golem::rdbms::mysql,
199 "golem:rdbms/postgres@0.0.1": crate::bindings::golem::rdbms::postgres,
200 "golem:rdbms/types@0.0.1": crate::bindings::golem::rdbms::types,
201 "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
202 "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
203 "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
204 "wasi:clocks/monotonic-clock@0.2.3": crate::bindings::wasi::clocks::monotonic_clock,
205 "wasi:filesystem/preopens@0.2.3": crate::bindings::wasi::filesystem::preopens,
206 "wasi:filesystem/types@0.2.3": crate::bindings::wasi::filesystem::types,
207 "wasi:http/types@0.2.3": crate::bindings::wasi::http::types,
208 "wasi:http/outgoing-handler@0.2.3": crate::bindings::wasi::http::outgoing_handler,
209 "wasi:io/error@0.2.3": crate::bindings::wasi::io::error,
210 "wasi:io/streams@0.2.3": crate::bindings::wasi::io::streams,
211 "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
212 "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
213 "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
214 "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
215 "wasi:logging/logging": crate::bindings::wasi::logging::logging,
216 "wasi:sockets/ip-name-lookup@0.2.3": crate::bindings::wasi::sockets::ip_name_lookup,
217 "wasi:sockets/instance-network@0.2.3": crate::bindings::wasi::sockets::instance_network,
218 "wasi:sockets/network@0.2.3": crate::bindings::wasi::sockets::network,
219 }
220 });
221}
222
223#[cfg(feature = "export_golem_agentic")]
224pub use ctor;
225
226#[cfg(feature = "export_golem_agentic")]
227pub use async_trait;
228
229#[cfg(feature = "export_oplog_processor")]
230pub mod oplog_processor {
231 use wit_bindgen::generate;
232
233 generate!({
234 path: "wit",
235 world: "golem-rust-oplog-processor",
236 generate_all,
237 generate_unused_types: true,
238 pub_export_macro: true,
239 with: {
240 "golem:rpc/types@0.2.2": golem_wasm::golem_rpc_0_2_x::types,
241 "wasi:io/poll@0.2.3": golem_wasm::wasi::io::poll,
242 "wasi:clocks/wall-clock@0.2.3": golem_wasm::wasi::clocks::wall_clock,
243
244 "golem:api/host@1.3.0": crate::bindings::golem::api::host,
245 "golem:api/oplog@1.3.0": crate::bindings::golem::api::oplog,
246 "golem:api/context@1.3.0": crate::bindings::golem::api::context,
247 "golem:durability/durability@1.3.0": crate::bindings::golem::durability::durability,
248 "golem:rdbms/mysql@0.0.1": crate::bindings::golem::rdbms::mysql,
249 "golem:rdbms/postgres@0.0.1": crate::bindings::golem::rdbms::postgres,
250 "golem:rdbms/types@0.0.1": crate::bindings::golem::rdbms::types,
251 "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
252 "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
253 "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
254 "wasi:clocks/monotonic-clock@0.2.3": crate::bindings::wasi::clocks::monotonic_clock,
255 "wasi:filesystem/preopens@0.2.3": crate::bindings::wasi::filesystem::preopens,
256 "wasi:filesystem/types@0.2.3": crate::bindings::wasi::filesystem::types,
257 "wasi:http/types@0.2.3": crate::bindings::wasi::http::types,
258 "wasi:http/outgoing-handler@0.2.3": crate::bindings::wasi::http::outgoing_handler,
259 "wasi:io/error@0.2.3": crate::bindings::wasi::io::error,
260 "wasi:io/streams@0.2.3": crate::bindings::wasi::io::streams,
261 "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
262 "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
263 "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
264 "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
265 "wasi:logging/logging": crate::bindings::wasi::logging::logging,
266 "wasi:sockets/ip-name-lookup@0.2.3": crate::bindings::wasi::sockets::ip_name_lookup,
267 "wasi:sockets/instance-network@0.2.3": crate::bindings::wasi::sockets::instance_network,
268 "wasi:sockets/network@0.2.3": crate::bindings::wasi::sockets::network,
269 }
270 });
271
272 pub use __export_golem_rust_oplog_processor_impl as export_oplog_processor;
273}
274
275#[cfg(feature = "export_golem_agentic")]
276pub mod agentic;
277
278#[cfg(feature = "durability")]
279pub mod durability;
280
281#[cfg(feature = "json")]
282mod json;
283
284#[cfg(feature = "json")]
285pub use json::*;
286
287mod transaction;
288pub mod value_and_type;
289
290use bindings::golem::api::host::*;
291
292pub use golem_wasm as wasm_rpc;
293
294pub use bindings::golem::api::host::{fork, oplog_commit};
295pub use bindings::golem::api::host::{ForkResult, PersistenceLevel};
296
297pub use transaction::*;
298
299#[cfg(feature = "macro")]
300pub use golem_rust_macro::*;
301
302impl Display for PromiseId {
303 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304 write!(f, "{}/{}", self.agent_id, self.oplog_idx)
305 }
306}
307
308impl FromStr for PromiseId {
309 type Err = String;
310
311 fn from_str(s: &str) -> Result<Self, Self::Err> {
312 let parts: Vec<&str> = s.split('/').collect();
313 if parts.len() == 2 {
314 let agent_id = AgentId::from_str(parts[0]).map_err(|_| {
315 format!("invalid agent id: {s} - expected format: <component_id>/<agent_id>")
316 })?;
317 let oplog_idx = parts[1]
318 .parse()
319 .map_err(|_| format!("invalid oplog index: {s} - expected integer"))?;
320 Ok(Self {
321 agent_id,
322 oplog_idx,
323 })
324 } else {
325 Err(format!(
326 "invalid promise id: {s} - expected format: <agent_id>/<oplog_idx>"
327 ))
328 }
329 }
330}
331
332#[derive(Clone, Debug, PartialEq)]
333pub struct RetryPolicy {
334 pub max_attempts: u32,
335 pub min_delay: std::time::Duration,
336 pub max_delay: std::time::Duration,
337 pub multiplier: f64,
338 pub max_jitter_factor: Option<f64>,
339}
340
341impl From<bindings::golem::api::host::RetryPolicy> for RetryPolicy {
342 fn from(value: bindings::golem::api::host::RetryPolicy) -> Self {
343 Self {
344 max_attempts: value.max_attempts,
345 min_delay: std::time::Duration::from_nanos(value.min_delay),
346 max_delay: std::time::Duration::from_nanos(value.max_delay),
347 multiplier: value.multiplier,
348 max_jitter_factor: value.max_jitter_factor,
349 }
350 }
351}
352
353impl From<RetryPolicy> for bindings::golem::api::host::RetryPolicy {
354 fn from(val: RetryPolicy) -> Self {
355 bindings::golem::api::host::RetryPolicy {
356 max_attempts: val.max_attempts,
357 min_delay: val.min_delay.as_nanos() as u64,
358 max_delay: val.max_delay.as_nanos() as u64,
359 multiplier: val.multiplier,
360 max_jitter_factor: val.max_jitter_factor,
361 }
362 }
363}
364
365pub struct PersistenceLevelGuard {
366 original_level: PersistenceLevel,
367}
368
369impl Drop for PersistenceLevelGuard {
370 fn drop(&mut self) {
371 set_oplog_persistence_level(self.original_level);
372 }
373}
374
375#[must_use]
379pub fn use_persistence_level(level: PersistenceLevel) -> PersistenceLevelGuard {
380 let original_level = get_oplog_persistence_level();
381 set_oplog_persistence_level(level);
382 PersistenceLevelGuard { original_level }
383}
384
385pub fn with_persistence_level<R>(level: PersistenceLevel, f: impl FnOnce() -> R) -> R {
387 let _guard = use_persistence_level(level);
388 f()
389}
390
391pub struct IdempotenceModeGuard {
392 original: bool,
393}
394
395impl Drop for IdempotenceModeGuard {
396 fn drop(&mut self) {
397 set_idempotence_mode(self.original);
398 }
399}
400
401#[must_use]
405pub fn use_idempotence_mode(mode: bool) -> IdempotenceModeGuard {
406 let original = get_idempotence_mode();
407 set_idempotence_mode(mode);
408 IdempotenceModeGuard { original }
409}
410
411pub fn with_idempotence_mode<R>(mode: bool, f: impl FnOnce() -> R) -> R {
413 let _guard = use_idempotence_mode(mode);
414 f()
415}
416
417pub fn generate_idempotency_key() -> uuid::Uuid {
421 Into::into(bindings::golem::api::host::generate_idempotency_key())
422}
423
424pub struct RetryPolicyGuard {
425 original: RetryPolicy,
426}
427
428impl Drop for RetryPolicyGuard {
429 fn drop(&mut self) {
430 set_retry_policy(Into::into(self.original.clone()));
431 }
432}
433
434#[must_use]
438pub fn use_retry_policy(policy: RetryPolicy) -> RetryPolicyGuard {
439 let original = Into::into(get_retry_policy());
440 set_retry_policy(Into::into(policy));
441 RetryPolicyGuard { original }
442}
443
444pub fn with_retry_policy<R>(policy: RetryPolicy, f: impl FnOnce() -> R) -> R {
446 let _guard = use_retry_policy(policy);
447 f()
448}
449
450pub struct AtomicOperationGuard {
451 begin: OplogIndex,
452}
453
454impl Drop for AtomicOperationGuard {
455 fn drop(&mut self) {
456 mark_end_operation(self.begin);
457 }
458}
459
460#[must_use]
465pub fn mark_atomic_operation() -> AtomicOperationGuard {
466 let begin = mark_begin_operation();
467 AtomicOperationGuard { begin }
468}
469
470pub fn atomically<T>(f: impl FnOnce() -> T) -> T {
474 let _guard = mark_atomic_operation();
475 f()
476}