jev_retry.mojo (1411B)
1 @fieldwise_init 2 struct RetryPolicy(Copyable, Movable): 3 var max_retries: Int 4 var base_delay_ms: Int 5 var max_delay_ms: Int 6 var budget_ms: Int 7 8 9 def retry_policy( 10 max_retries: Int, base_delay_ms: Int, max_delay_ms: Int, budget_ms: Int 11 ) raises -> RetryPolicy: 12 if max_retries < 0: 13 raise Error("max_retries must be non-negative") 14 if base_delay_ms <= 0: 15 raise Error("base_delay_ms must be positive") 16 if max_delay_ms < base_delay_ms: 17 raise Error("max_delay_ms must be at least base_delay_ms") 18 if budget_ms <= 0: 19 raise Error("budget_ms must be positive") 20 return RetryPolicy( 21 max_retries=max_retries, 22 base_delay_ms=base_delay_ms, 23 max_delay_ms=max_delay_ms, 24 budget_ms=budget_ms, 25 ) 26 27 28 def retry_delay_ms(policy: RetryPolicy, attempt: Int) -> Int: 29 var delay = policy.base_delay_ms 30 for _ in range(attempt): 31 delay *= 2 32 if delay >= policy.max_delay_ms: 33 return policy.max_delay_ms 34 if delay > policy.max_delay_ms: 35 return policy.max_delay_ms 36 return delay 37 38 39 def should_retry( 40 policy: RetryPolicy, attempt: Int, elapsed_ms: Int, retryable: Bool 41 ) -> Bool: 42 if not retryable: 43 return False 44 if attempt >= policy.max_retries: 45 return False 46 if elapsed_ms + retry_delay_ms(policy, attempt) >= policy.budget_ms: 47 return False 48 return True