mattp5657 commented on code in PR #4104:
URL: https://github.com/apache/iggy/pull/4104#discussion_r3973384336


##########
core/connectors/sdk/src/retry.rs:
##########
@@ -181,6 +190,114 @@ pub fn parse_retry_after(value: &str) -> Option<Duration> 
{
     None
 }
 
+// ---------------------------------------------------------------------------
+// Generic retry loop
+// ---------------------------------------------------------------------------
+
+/// Parameters for [`retry_async`].
+///
+/// `max_attempts` is a *total attempt count*, not a count of extra retries:
+/// `1` runs the operation once and never retries, `3` allows two retries. `0`
+/// behaves as `1`, so a misconfigured value degrades to a single attempt
+/// rather than skipping the operation entirely.
+#[derive(Debug, Clone, Copy)]
+pub struct RetryPolicy {
+    pub max_attempts: u32,
+    pub base_delay: Duration,
+    pub max_delay: Duration,
+}
+
+impl RetryPolicy {
+    /// Jittered backoff before retry number `retry` (1-based). See
+    /// [`retry_backoff`].
+    pub fn backoff(&self, retry: u32) -> Duration {
+        retry_backoff(self.base_delay, retry, self.max_delay)
+    }
+}
+
+/// Jittered, capped backoff before retry number `retry` (1-based): the first
+/// retry waits `base_delay`, the second `2 × base_delay`, and so on, which is
+/// the convention the `retry_delay` config fields document.
+///
+/// The cap is re-applied after [`jitter`], because ±20 % jitter on an
+/// already-capped delay can otherwise land above `max_delay`, which the config
+/// fields document as a strict upper bound.
+///
+/// Prefer [`retry_async`], which calls this for you. Reach for it directly
+/// only in a loop that cannot be expressed as a retried `Result`.
+pub fn retry_backoff(base_delay: Duration, retry: u32, max_delay: Duration) -> 
Duration {
+    jitter(exponential_backoff(
+        base_delay,
+        retry.saturating_sub(1),
+        max_delay,
+    ))
+    .min(max_delay)
+}

Review Comment:
   Nit: Once backoff saturates (base_delay * 2^k >= max_delay), 
exponential_backoff returns exactly max_delay every time, and this trailing 
.min(max_delay) clamps away the upper half of jitter's +/-20% draw. Verified 
empirically. 
   
   Maybe we should document it, but not a huge issue.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to