openzeppelin_relayer/jobs/handlers/
mod.rs

1use std::sync::Arc;
2
3use apalis::prelude::{Attempt, Error};
4use eyre::Report;
5use tracing::{debug, error, warn};
6
7mod transaction_request_handler;
8pub use transaction_request_handler::*;
9
10mod transaction_submission_handler;
11pub use transaction_submission_handler::*;
12
13mod notification_handler;
14pub use notification_handler::*;
15
16mod transaction_status_handler;
17pub use transaction_status_handler::*;
18
19mod solana_swap_request_handler;
20pub use solana_swap_request_handler::*;
21
22mod transaction_cleanup_handler;
23pub use transaction_cleanup_handler::*;
24
25// Handles job results for simple handlers (no transaction state management).
26//
27// Used by: notification_handler, solana_swap_request_handler, transaction_cleanup_handler
28//
29// # Retry Strategy
30// - On success: Job completes
31// - On error: Retry until max_attempts reached
32// - At max_attempts: Abort job
33mod relayer_health_check_handler;
34pub use relayer_health_check_handler::*;
35
36pub fn handle_result(
37    result: Result<(), Report>,
38    attempt: Attempt,
39    job_type: &str,
40    max_attempts: usize,
41) -> Result<(), Error> {
42    if result.is_ok() {
43        debug!(
44            job_type = %job_type,
45            "request handled successfully"
46        );
47        return Ok(());
48    }
49
50    let err = result.as_ref().unwrap_err();
51    warn!(
52        job_type = %job_type,
53        error = %err,
54        attempt = %attempt.current(),
55        max_attempts = %max_attempts,
56        "request failed"
57    );
58
59    if attempt.current() >= max_attempts {
60        error!(
61            job_type = %job_type,
62            max_attempts = %max_attempts,
63            "max attempts reached, failing job"
64        );
65        return Err(Error::Abort(Arc::new("Failed to handle request".into())));
66    }
67
68    Err(Error::Failed(Arc::new(
69        "Failed to handle request. Retrying".into(),
70    )))
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use apalis::prelude::Attempt;
77
78    #[test]
79    fn test_handle_result_success() {
80        let result: Result<(), Report> = Ok(());
81        let attempt = Attempt::default();
82
83        let handled = handle_result(result, attempt, "test_job", 3);
84        assert!(handled.is_ok());
85    }
86
87    #[test]
88    fn test_handle_result_retry() {
89        let result: Result<(), Report> = Err(Report::msg("Test error"));
90        let attempt = Attempt::default();
91
92        let handled = handle_result(result, attempt, "test_job", 3);
93
94        assert!(handled.is_err());
95        match handled {
96            Err(Error::Failed(_)) => {
97                // This is the expected error type for a retry
98            }
99            _ => panic!("Expected Failed error for retry"),
100        }
101    }
102
103    #[test]
104    fn test_handle_result_abort() {
105        let result: Result<(), Report> = Err(Report::msg("Test error"));
106        let attempt = Attempt::default();
107        for _ in 0..3 {
108            attempt.increment();
109        }
110
111        let handled = handle_result(result, attempt, "test_job", 3);
112
113        assert!(handled.is_err());
114        match handled {
115            Err(Error::Abort(_)) => {
116                // This is the expected error type for an abort
117            }
118            _ => panic!("Expected Abort error for max attempts"),
119        }
120    }
121
122    #[test]
123    fn test_handle_result_max_attempts_exceeded() {
124        let result: Result<(), Report> = Err(Report::msg("Test error"));
125        let attempt = Attempt::default();
126        for _ in 0..5 {
127            attempt.increment();
128        }
129
130        let handled = handle_result(result, attempt, "test_job", 3);
131
132        assert!(handled.is_err());
133        match handled {
134            Err(Error::Abort(_)) => {
135                // This is the expected error type for exceeding max attempts
136            }
137            _ => panic!("Expected Abort error for exceeding max attempts"),
138        }
139    }
140}