golem_rust/
lib.rs

1// Copyright 2024 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[allow(unused)]
16#[allow(warnings)]
17#[rustfmt::skip]
18pub mod bindings;
19
20#[cfg(feature = "json")]
21mod json;
22
23#[cfg(feature = "json")]
24pub use json::*;
25
26#[cfg(feature = "uuid")]
27mod uuid;
28
29mod transaction;
30
31use bindings::golem::api::host::*;
32
33pub use bindings::golem::api::host::oplog_commit;
34pub use bindings::golem::api::host::PersistenceLevel;
35
36pub use transaction::*;
37
38pub use golem_rust_macro::*;
39
40#[derive(Clone, Debug, PartialEq)]
41pub struct RetryPolicy {
42    pub max_attempts: u32,
43    pub min_delay: std::time::Duration,
44    pub max_delay: std::time::Duration,
45    pub multiplier: f64,
46    pub max_jitter_factor: Option<f64>,
47}
48
49impl From<bindings::golem::api::host::RetryPolicy> for RetryPolicy {
50    fn from(value: bindings::golem::api::host::RetryPolicy) -> Self {
51        Self {
52            max_attempts: value.max_attempts,
53            min_delay: std::time::Duration::from_nanos(value.min_delay),
54            max_delay: std::time::Duration::from_nanos(value.max_delay),
55            multiplier: value.multiplier,
56            max_jitter_factor: value.max_jitter_factor,
57        }
58    }
59}
60
61impl From<RetryPolicy> for bindings::golem::api::host::RetryPolicy {
62    fn from(val: RetryPolicy) -> Self {
63        bindings::golem::api::host::RetryPolicy {
64            max_attempts: val.max_attempts,
65            min_delay: val.min_delay.as_nanos() as u64,
66            max_delay: val.max_delay.as_nanos() as u64,
67            multiplier: val.multiplier,
68            max_jitter_factor: val.max_jitter_factor,
69        }
70    }
71}
72
73pub struct PersistenceLevelGuard {
74    original_level: PersistenceLevel,
75}
76
77impl Drop for PersistenceLevelGuard {
78    fn drop(&mut self) {
79        set_oplog_persistence_level(self.original_level);
80    }
81}
82
83/// Temporarily sets the oplog persistence level to the given value.
84///
85/// When the returned guard is dropped, the original persistence level is restored.
86#[must_use]
87pub fn use_persistence_level(level: PersistenceLevel) -> PersistenceLevelGuard {
88    let original_level = get_oplog_persistence_level();
89    set_oplog_persistence_level(level);
90    PersistenceLevelGuard { original_level }
91}
92
93/// Executes the given function with the oplog persistence level set to the given value.
94pub fn with_persistence_level<R>(level: PersistenceLevel, f: impl FnOnce() -> R) -> R {
95    let _guard = use_persistence_level(level);
96    f()
97}
98
99pub struct IdempotenceModeGuard {
100    original: bool,
101}
102
103impl Drop for IdempotenceModeGuard {
104    fn drop(&mut self) {
105        set_idempotence_mode(self.original);
106    }
107}
108
109/// Temporarily sets the idempotence mode to the given value.
110///
111/// When the returned guard is dropped, the original idempotence mode is restored.
112#[must_use]
113pub fn use_idempotence_mode(mode: bool) -> IdempotenceModeGuard {
114    let original = get_idempotence_mode();
115    set_idempotence_mode(mode);
116    IdempotenceModeGuard { original }
117}
118
119/// Executes the given function with the idempotence mode set to the given value.
120pub fn with_idempotence_mode<R>(mode: bool, f: impl FnOnce() -> R) -> R {
121    let _guard = use_idempotence_mode(mode);
122    f()
123}
124
125/// Generates an idempotency key. This operation will never be replayed —
126/// i.e. not only is this key generated, but it is persisted and committed, such that the key can be used in third-party systems (e.g. payment processing)
127/// to introduce idempotence.
128#[cfg(feature = "uuid")]
129pub fn generate_idempotency_key() -> ::uuid::Uuid {
130    Into::into(bindings::golem::api::host::generate_idempotency_key())
131}
132
133/// Generates an idempotency key. This operation will never be replayed —
134/// i.e. not only is this key generated, but it is persisted and committed, such that the key can be used in third-party systems (e.g. payment processing)
135/// to introduce idempotence.
136#[cfg(not(feature = "uuid"))]
137pub fn generate_idempotency_key() -> Uuid {
138    bindings::golem::api::host::generate_idempotency_key()
139}
140
141pub struct RetryPolicyGuard {
142    original: RetryPolicy,
143}
144
145impl Drop for RetryPolicyGuard {
146    fn drop(&mut self) {
147        set_retry_policy(Into::into(self.original.clone()));
148    }
149}
150
151/// Temporarily sets the retry policy to the given value.
152///
153/// When the returned guard is dropped, the original retry policy is restored.
154#[must_use]
155pub fn use_retry_policy(policy: RetryPolicy) -> RetryPolicyGuard {
156    let original = Into::into(get_retry_policy());
157    set_retry_policy(Into::into(policy));
158    RetryPolicyGuard { original }
159}
160
161/// Executes the given function with the retry policy set to the given value.
162pub fn with_retry_policy<R>(policy: RetryPolicy, f: impl FnOnce() -> R) -> R {
163    let _guard = use_retry_policy(policy);
164    f()
165}
166
167pub struct AtomicOperationGuard {
168    begin: OplogIndex,
169}
170
171impl Drop for AtomicOperationGuard {
172    fn drop(&mut self) {
173        mark_end_operation(self.begin);
174    }
175}
176
177/// Marks a block as an atomic operation
178///
179/// When the returned guard is dropped, the operation gets committed.
180/// In case of a failure, the whole operation will be reexecuted during retry.
181#[must_use]
182pub fn mark_atomic_operation() -> AtomicOperationGuard {
183    let begin = mark_begin_operation();
184    AtomicOperationGuard { begin }
185}
186
187/// Executes the given function as an atomic operation.
188///
189/// In case of a failure, the whole operation will be reexecuted during retry.
190pub fn atomically<T>(f: impl FnOnce() -> T) -> T {
191    let _guard = mark_atomic_operation();
192    f()
193}