rightkit_agent_engine_protocol/
retry_notice.rs1use std::fmt;
7use std::sync::Arc;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct RetryNotice {
12 pub provider: String,
14 pub reason: String,
17 pub attempt: u32,
19 pub max_attempts: u32,
21 pub delay_ms: u64,
23}
24
25type NotifyFn = dyn Fn(RetryNotice) + Send + Sync;
26
27#[derive(Clone, Default)]
29pub struct RetryNotifier(Option<Arc<NotifyFn>>);
30
31impl RetryNotifier {
32 pub fn new(f: impl Fn(RetryNotice) + Send + Sync + 'static) -> Self {
33 Self(Some(Arc::new(f)))
34 }
35
36 pub fn notify(&self, notice: RetryNotice) {
37 if let Some(f) = &self.0 {
38 f(notice);
39 }
40 }
41}
42
43impl fmt::Debug for RetryNotifier {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.write_str(if self.0.is_some() {
46 "RetryNotifier(set)"
47 } else {
48 "RetryNotifier(none)"
49 })
50 }
51}
52
53impl PartialEq for RetryNotifier {
54 fn eq(&self, other: &Self) -> bool {
55 match (&self.0, &other.0) {
56 (None, None) => true,
57 (Some(a), Some(b)) => Arc::ptr_eq(a, b),
58 _ => false,
59 }
60 }
61}
62
63impl Eq for RetryNotifier {}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use std::sync::Mutex;
69
70 #[test]
71 fn notifier_delivers_and_default_is_silent() {
72 RetryNotifier::default().notify(RetryNotice {
73 provider: "p".into(),
74 reason: "r".into(),
75 attempt: 1,
76 max_attempts: 3,
77 delay_ms: 10,
78 });
79 let seen = Arc::new(Mutex::new(Vec::new()));
80 let sink = seen.clone();
81 let n = RetryNotifier::new(move |notice| sink.lock().unwrap().push(notice.attempt));
82 n.notify(RetryNotice {
83 provider: "p".into(),
84 reason: "r".into(),
85 attempt: 2,
86 max_attempts: 3,
87 delay_ms: 10,
88 });
89 assert_eq!(*seen.lock().unwrap(), vec![2]);
90 assert_eq!(n.clone(), n);
91 }
92}