openzeppelin_relayer/jobs/handlers/
transaction_status_handler.rs1use actix_web::web::ThinData;
8use apalis::prelude::{Attempt, Data, *};
9
10use eyre::Result;
11use log::info;
12
13use crate::{
14 constants::WORKER_DEFAULT_MAXIMUM_RETRIES,
15 domain::{get_relayer_transaction, get_transaction_by_id, Transaction},
16 jobs::{handle_result, Job, TransactionStatusCheck},
17 models::DefaultAppState,
18};
19
20pub async fn transaction_status_handler(
21 job: Job<TransactionStatusCheck>,
22 state: Data<ThinData<DefaultAppState>>,
23 attempt: Attempt,
24) -> Result<(), Error> {
25 info!("Handling transaction status job: {:?}", job.data);
26
27 let result = handle_request(job.data, state).await;
28
29 handle_result(
30 result,
31 attempt,
32 "Transaction Status",
33 WORKER_DEFAULT_MAXIMUM_RETRIES,
34 )
35}
36
37async fn handle_request(
38 status_request: TransactionStatusCheck,
39 state: Data<ThinData<DefaultAppState>>,
40) -> Result<()> {
41 let relayer_transaction =
42 get_relayer_transaction(status_request.relayer_id.clone(), &state).await?;
43
44 let transaction = get_transaction_by_id(status_request.transaction_id, &state).await?;
45
46 relayer_transaction
47 .handle_transaction_status(transaction)
48 .await?;
49
50 info!("Status check handled successfully");
51
52 Ok(())
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use apalis::prelude::Attempt;
59 use std::collections::HashMap;
60
61 #[tokio::test]
62 async fn test_status_check_job_validation() {
63 let check_job = TransactionStatusCheck::new("tx123", "relayer-1");
65 let job = Job::new(crate::jobs::JobType::TransactionStatusCheck, check_job);
66
67 assert_eq!(job.data.transaction_id, "tx123");
69 assert_eq!(job.data.relayer_id, "relayer-1");
70 assert!(job.data.metadata.is_none());
71 }
72
73 #[tokio::test]
74 async fn test_status_check_with_metadata() {
75 let mut metadata = HashMap::new();
77 metadata.insert("retry_count".to_string(), "2".to_string());
78 metadata.insert("last_status".to_string(), "pending".to_string());
79
80 let check_job =
81 TransactionStatusCheck::new("tx123", "relayer-1").with_metadata(metadata.clone());
82
83 assert!(check_job.metadata.is_some());
85 let job_metadata = check_job.metadata.unwrap();
86 assert_eq!(job_metadata.get("retry_count").unwrap(), "2");
87 assert_eq!(job_metadata.get("last_status").unwrap(), "pending");
88 }
89
90 #[tokio::test]
91 async fn test_status_handler_attempt_tracking() {
92 let first_attempt = Attempt::default();
94 assert_eq!(first_attempt.current(), 0);
95
96 let second_attempt = Attempt::default();
97 second_attempt.increment();
98 assert_eq!(second_attempt.current(), 1);
99
100 let final_attempt = Attempt::default();
101 for _ in 0..WORKER_DEFAULT_MAXIMUM_RETRIES {
102 final_attempt.increment();
103 }
104 assert_eq!(final_attempt.current(), WORKER_DEFAULT_MAXIMUM_RETRIES);
105 }
106}