Skip to content

Commit c440cd5

Browse files
authored
Use adaptive retry delay for transaction resolution (#100)
* Use adaptive retry delay for transaction resolution Add transaction_hash_retry_delay(attempts) to compute exponential/backoff-style delays based on job.attempts(), and apply it when requeueing transaction-hash fetches. Replace hardcoded 1s/2s delays with the computed delay for both bundler errors (nack) and Pending responses (map_err_nack), and add tracing logs to record bundler_transaction_id, attempt, and retry_delay_seconds. This reduces aggressive retries and centralizes retry timing logic. * Add tests for transaction_hash_retry_delay Adds a unit test module verifying that transaction_hash_retry_delay respects bucket boundaries. The test checks edge cases around thresholds (5/6, 20/21, 100/101, 1000/1001) and ensures the function returns the expected Durations (2s, 10s, 30s, 5min, 30min) for those ranges.
1 parent 3ede6ab commit c440cd5

1 file changed

Lines changed: 56 additions & 2 deletions

File tree

executors/src/eip7702_executor/confirm.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ use crate::{
2929
},
3030
};
3131

32+
fn transaction_hash_retry_delay(attempts: u32) -> Duration {
33+
match attempts {
34+
0..=5 => Duration::from_secs(2),
35+
6..=20 => Duration::from_secs(10),
36+
21..=100 => Duration::from_secs(30),
37+
101..=1000 => Duration::from_secs(5 * 60),
38+
_ => Duration::from_secs(30 * 60),
39+
}
40+
}
41+
3242
// --- Job Payload ---
3343
#[derive(Serialize, Deserialize, Debug, Clone)]
3444
#[serde(rename_all = "camelCase")]
@@ -174,6 +184,7 @@ where
174184
job: &BorrowedJob<Self::JobData>,
175185
) -> JobResult<Self::Output, Self::ErrorData> {
176186
let job_data = &job.job.data;
187+
let transaction_hash_delay = transaction_hash_retry_delay(job.attempts());
177188

178189
// 1. Get Chain
179190
let chain = self
@@ -214,10 +225,16 @@ where
214225
}
215226
.fail()
216227
} else {
228+
tracing::warn!(
229+
bundler_transaction_id = job_data.bundler_transaction_id,
230+
attempt = job.attempts(),
231+
retry_delay_seconds = transaction_hash_delay.as_secs(),
232+
"Retrying transaction hash fetch after bundler error"
233+
);
217234
Eip7702ConfirmationError::TransactionHashError {
218235
message: e.to_string(),
219236
}
220-
.nack(Some(Duration::from_secs(2)), RequeuePosition::Last)
237+
.nack(Some(transaction_hash_delay), RequeuePosition::Last)
221238
}
222239
})?;
223240

@@ -232,10 +249,16 @@ where
232249
}
233250

234251
TwGetTransactionHashResponse::Pending => {
252+
tracing::debug!(
253+
bundler_transaction_id = job_data.bundler_transaction_id,
254+
attempt = job.attempts(),
255+
retry_delay_seconds = transaction_hash_delay.as_secs(),
256+
"Transaction hash still pending, scheduling retry"
257+
);
235258
return Err(Eip7702ConfirmationError::TransactionHashPending {
236259
message: "Transaction hash not yet available".to_string(),
237260
})
238-
.map_err_nack(Some(Duration::from_secs(1)), RequeuePosition::Last);
261+
.map_err_nack(Some(transaction_hash_delay), RequeuePosition::Last);
239262
}
240263
};
241264

@@ -384,3 +407,34 @@ where
384407
}
385408
}
386409
}
410+
411+
#[cfg(test)]
412+
mod tests {
413+
use std::time::Duration;
414+
415+
use super::transaction_hash_retry_delay;
416+
417+
#[test]
418+
fn transaction_hash_retry_delay_respects_bucket_boundaries() {
419+
assert_eq!(transaction_hash_retry_delay(5), Duration::from_secs(2));
420+
assert_eq!(transaction_hash_retry_delay(6), Duration::from_secs(10));
421+
422+
assert_eq!(transaction_hash_retry_delay(20), Duration::from_secs(10));
423+
assert_eq!(transaction_hash_retry_delay(21), Duration::from_secs(30));
424+
425+
assert_eq!(transaction_hash_retry_delay(100), Duration::from_secs(30));
426+
assert_eq!(
427+
transaction_hash_retry_delay(101),
428+
Duration::from_secs(5 * 60)
429+
);
430+
431+
assert_eq!(
432+
transaction_hash_retry_delay(1000),
433+
Duration::from_secs(5 * 60)
434+
);
435+
assert_eq!(
436+
transaction_hash_retry_delay(1001),
437+
Duration::from_secs(30 * 60)
438+
);
439+
}
440+
}

0 commit comments

Comments
 (0)