Skip to content

Add opt-in infinite retries with elapsed-time guard#120

Draft
kamui wants to merge 1 commit intomainfrom
feat/infinite-retries
Draft

Add opt-in infinite retries with elapsed-time guard#120
kamui wants to merge 1 commit intomainfrom
feat/infinite-retries

Conversation

@kamui
Copy link
Owner

@kamui kamui commented Mar 7, 2026

Summary

  • add opt-in infinite retry support via tries: :infinite without changing existing finite retry defaults
  • enforce a safety guard by requiring max_elapsed_time to be finite when infinite retries are enabled
  • update interval generation internals to compute backoff per attempt and document the new option in README and CHANGELOG

Testing

  • bundle exec rspec

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

Support infinite retry loops bounded by max_elapsed_time, useful for
long-running worker processes. Raises ArgumentError if max_elapsed_time
is not finite or if custom intervals are empty.

Extracts interval_for on ExponentialBackoff for lazy per-attempt
interval computation without pre-allocating an array.
@kamui kamui force-pushed the feat/infinite-retries branch from 591a500 to e121ead Compare March 7, 2026 03:24
end

def retriable(opts = {}, &block)
def retriable(opts = {}, &block) # rubocop:disable Metrics/PerceivedComplexity
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/CyclomaticComplexity: Cyclomatic complexity for retriable is too high. [7/6]

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +47 to +52
if local_config.intervals
raise ArgumentError, "intervals must not be empty for infinite retries" if local_config.intervals.empty?

custom = local_config.intervals
interval_for = ->(i) { custom[[i, custom.size - 1].min] }
else
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In tries: :infinite mode with custom intervals, only the empty-array case is validated. If intervals contains nil or non-numeric values, interval_for can return a non-numeric interval and can_retry? will raise a TypeError when evaluating elapsed_time + interval. Consider validating that all interval values (and especially the last value, since it is reused) are Numeric, and raising a clear ArgumentError if not (and adding a spec for this behavior).

Copilot uses AI. Check for mistakes.
else
backoff = ExponentialBackoff.new(
base_interval: local_config.base_interval, multiplier: local_config.multiplier,
max_interval: local_config.max_interval, rand_factor: local_config.rand_factor
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This multiline ExponentialBackoff.new(...) call is missing a trailing comma after the last argument. The repo’s RuboCop config enforces trailing commas for multiline argument lists (Style/TrailingCommaInArguments), so this will fail linting.

Suggested change
max_interval: local_config.max_interval, rand_factor: local_config.rand_factor
max_interval: local_config.max_interval, rand_factor: local_config.rand_factor,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants