use pacta_contract::{Pact, Registry, Timestamp};
use pacta_memory::MemoryRegistry;
use uuid::Uuid;
const DOCKET: &str = "retries";
const LEASE_MILLIS: u64 = 1000;
fn at(millis: u64) -> Timestamp {
Timestamp::from_millis(millis)
}
fn backoff_millis(attempt: u32) -> u64 {
1000 * u64::from(attempt)
}
fn a_pact() -> Pact {
Pact::new(
Uuid::new_v4(),
DOCKET.to_string(),
"retry-demo".to_string(),
Vec::new(),
)
}
fn main() {
let registry = MemoryRegistry::seeded(vec![a_pact()], LEASE_MILLIS);
let mut attempts = 0u32;
let mut now = 0u64;
let first = registry
.claim(&[DOCKET], at(now))
.expect("claim should not error")
.expect("the pact should be claimable");
attempts += 1;
let delay = backoff_millis(attempts); registry
.release(&first.retainer, at(now + delay))
.expect("release should succeed for the current holder");
println!(
"attempt {attempts} failed; released until t={}",
now + delay
);
assert!(
registry
.claim(&[DOCKET], at(now + delay / 2))
.expect("claim should not error")
.is_none(),
"a released pact must be withheld before its reclaimable instant"
);
now += delay;
let second = registry
.claim(&[DOCKET], at(now))
.expect("claim should not error")
.expect("the pact should be reclaimable at its reclaimable instant");
assert_ne!(
first.retainer.id(),
second.retainer.id(),
"reclaiming must rotate the retainer"
);
attempts += 1;
registry
.fulfill(&second.retainer)
.expect("fulfill should settle the reclaimed pact");
println!("attempt {attempts} succeeded; fulfilled");
assert!(
registry
.claim(&[DOCKET], at(now + LEASE_MILLIS + 1))
.expect("claim should not error")
.is_none(),
"a fulfilled pact must not be claimable again"
);
assert_eq!(
attempts, 2,
"the pact should have taken exactly two attempts"
);
println!("durable retry OK: withheld through backoff, reclaimed, fulfilled on retry");
}