fn guard
Runs rest (the steps after step k) and, when it fails, the compensation comp of step k with v (the step's result).
A compensation is retried with backoff (SAGA_UNDO_RETRIES); when it never succeeds the saga is stuck and the result is
CompensationFailed{ cause, step } (§11.3). Compensations that are already done (a takeover replays the saga) are skipped.
Example:
@error data Declined { why: str }
service Ledger {
@public @idempotent rpc openAcct(id: u64) -> u64
@public @idempotent rpc closeAcct(id: u64) -> ()
@public @idempotent rpc charge(id: u64) -> u64 | Declined
}
impl Ledger {
rpc openAcct(id) {
print("open {id}")
id
}
rpc closeAcct(id) { print("close {id}") }
rpc charge(id) {
if id > 1 { fail Declined{ why: "limit" } }
id
}
}
saga flow(a: u64, b: u64) -> u64 {
Ledger.openAcct(a) undo x => Ledger.closeAcct(x)
-> Ledger.openAcct(b) undo y => Ledger.closeAcct(y)
-> Ledger.charge(b)
}
fn main() io, net, time, db {
match flow(1, 2) {
u64 v => print("done {v}")
Declined d => print("declined {d.why}")
CompensationFailed c => print("stuck")
NetError e => print("net error")
}
}Output
open 1 open 2 close 2 close 1 declined limit
pub(api) fn guard<A: Serializable, U, T, effect F, effect G>(k: i64, v: A, comp: fn(A) -> U F, rest: fn(A) -> T G) -> T | CompensationFailed net, db, time, F, GSince. 1.0.0-beta
Parameters
| Name | Type |
|---|---|
k | i64 |
v | A |
comp | fn(A) -> U F, rest: fn(A) -> T G |
Returns
T
Errors
CompensationFailed net, db, time, F, G- `CompensationFailed` when a compensation never succeeds.
Effects
none declared (pure unless the body says otherwise)
Defined in: std/saga/saga.oxl:575