retriable 3.4.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86086d1d868b9f609e96d2b5e8e5f6e5910a9822b7c21dd86a4014a12105d7f3
4
- data.tar.gz: a7324a228f6b0565428cb10afe6ecf3a98b7a6984ced4f83c32595f97767b09b
3
+ metadata.gz: a551efb6db5acea9e82dde8e48afdea1869f6b93461a3c48c33f8385fbea6392
4
+ data.tar.gz: fbf6bb8c5ade48420e0f2a43532bafff0e4159eb4cf149bce559116ec1c91e50
5
5
  SHA512:
6
- metadata.gz: fc0f71e125a40e52fdb8e4cb99b71b066fc84a067e9011b166a14d08a9f98f20a15a32402818705172275ea8b0a0f814963265eabba9fcae6d7ac40cdfc9e520
7
- data.tar.gz: d13f82d53fdc1c2be693a056fd4d164cddc4a7b34096c6c7367213f899881687854a3df5a20a07ad3678c3aa257297bd42a68cb36e9cf0718a2fa8be54a3bd56
6
+ metadata.gz: 19d5ac72e1614b7fdb3984697db76ad3f6ae2e9b1f60ff1eb470e210738cd67154afc2776b55329fca345fad6263035a41eb0748626f427fd2d05cc0bfea9c89
7
+ data.tar.gz: c1d46594742b7c19985a63037199125b718e6c6395dd8276013719d8c7f9cd64376637471b90fa9249869767da9a2474cafc31afd04f373f73249d8ebdfa0337
@@ -7,37 +7,36 @@ on:
7
7
  branches: [main]
8
8
  types: [opened, synchronize, reopened]
9
9
 
10
+ permissions:
11
+ contents: read
12
+
10
13
  jobs:
11
14
  ci:
12
15
  # The type of runner that the job will run on
13
16
  runs-on: ${{ matrix.os }}
17
+ # Ruby 4.0 is still in preview. Treat its results as informational so a
18
+ # preview-only regression doesn't block merges. Drop this gate (or update
19
+ # the version literal) once Ruby 4.0 is released and we treat it as
20
+ # required.
21
+ continue-on-error: ${{ matrix.ruby == '4.0' }}
14
22
  strategy:
15
23
  matrix:
16
24
  os: [ubuntu-24.04]
17
25
  ruby:
18
26
  [
19
- "2.3",
20
- "2.4",
21
- "2.5",
22
- "2.6",
23
- "2.7",
24
- "3.0",
25
- "3.1",
26
27
  "3.2",
27
28
  "3.3",
28
29
  "3.4",
29
30
  "4.0",
30
31
  jruby,
31
32
  ]
32
- env:
33
- CC_TEST_REPORTER_ID: 20a1139ef1830b4f813a10a03d90e8aa179b5226f75e75c5a949b25756ebf558
34
33
 
35
34
  steps:
36
35
  # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
37
- - uses: actions/checkout@v6
36
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
38
37
 
39
38
  - name: Setup ruby
40
- uses: ruby/setup-ruby@v1
39
+ uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
41
40
  with:
42
41
  ruby-version: ${{ matrix.ruby }}
43
42
  bundler-cache: true
@@ -47,3 +46,36 @@ jobs:
47
46
 
48
47
  - name: Run rspec
49
48
  run: bundle exec rspec
49
+
50
+ lint:
51
+ runs-on: ubuntu-24.04
52
+
53
+ steps:
54
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
55
+
56
+ - name: Setup ruby
57
+ uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
58
+ with:
59
+ ruby-version: "3.3"
60
+ bundler-cache: true
61
+
62
+ - name: Run rubocop
63
+ run: bundle exec rubocop
64
+
65
+ - name: Validate RBS
66
+ run: bundle exec rbs -I sig validate
67
+
68
+ audit:
69
+ runs-on: ubuntu-24.04
70
+
71
+ steps:
72
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
73
+
74
+ - name: Setup ruby
75
+ uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1
76
+ with:
77
+ ruby-version: "3.3"
78
+ bundler-cache: true
79
+
80
+ - name: Run bundler-audit
81
+ run: bundle exec bundle-audit check --update
data/.hound.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ruby:
2
- config_file: .rubocop.yml
2
+ enabled: false
data/.rubocop.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
- TargetRubyVersion: 2.3
3
+ TargetRubyVersion: 3.2
4
4
 
5
5
  Style/StringLiterals:
6
6
  EnforcedStyle: double_quotes
@@ -40,3 +40,6 @@ Metrics/AbcSize:
40
40
 
41
41
  Style/TrailingCommaInArrayLiteral:
42
42
  Enabled: false
43
+
44
+ Naming/MethodParameterName:
45
+ MinNameLength: 2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,123 @@
1
1
  # HEAD
2
2
 
3
+ ## 4.2.0
4
+
5
+ ### Bug fixes
6
+
7
+ - The `Kernel` extension methods (`require "retriable/core_ext/kernel"`) are now
8
+ private, matching idiomatic `Kernel` helpers like `puts` and `rand`.
9
+ Previously `retriable` and `retriable_with_context` were public instance
10
+ methods, so they leaked onto every object's public API and could be invoked
11
+ with an explicit receiver (e.g. `"foo".retriable { ... }`). They remain
12
+ callable in the documented receiver-less form.
13
+ ([#146](https://github.com/kamui/retriable/pull/146))
14
+ - `Retriable.with_context` (and `Kernel#retriable_with_context`) now raises
15
+ `ArgumentError` when called without a block, matching `with_override`.
16
+ Previously a missing block was silently ignored: the call returned `nil` and
17
+ the intended block never ran, hiding a caller bug. Behavior change: code that
18
+ relied on the silent no-op will now raise.
19
+ - `Config#validate!` now validates the structure of each entry in `contexts`,
20
+ so configured contexts are checked on every `Retriable.retriable`/
21
+ `with_context` call rather than only when a given context is first used. A
22
+ context whose options contain an unknown key (including a nested `contexts`
23
+ key) now raises `ArgumentError, "<key> is not a valid option"`, matching the
24
+ `with_override` path. Non-Hash `contexts` and non-Hash per-context values
25
+ remain leniently treated as empty options (no behavior change). Option
26
+ _values_ are still validated lazily at retry time, unchanged.
27
+
28
+ ### Docs
29
+
30
+ - Document that `on_retry` receives `next_interval: nil` on the final rescued
31
+ attempt, when Retriable is about to give up because `tries` are exhausted.
32
+ `on_retry` still fires before `on_give_up` (unchanged behavior); the `nil`
33
+ contract is now called out in the `on_retry` documentation so handlers guard
34
+ arithmetic or logging on `next_interval`.
35
+
36
+ ### Performance
37
+
38
+ - `Config#initialize` no longer allocates a throwaway `ExponentialBackoff` (and
39
+ runs its redundant `validate!`) just to read default values. Defaults now live
40
+ in a frozen `ExponentialBackoff::DEFAULTS` constant, removing an allocation and
41
+ redundant validation from the `retriable` hot path.
42
+ ([#149](https://github.com/kamui/retriable/pull/149))
43
+
44
+ ## 4.1.1
45
+
46
+ ### Bug fixes
47
+
48
+ - `retry_if`, `on_retry`, and `on_give_up` are now validated to be callable
49
+ (respond to `#call`) or falsy. A non-callable truthy value raises
50
+ `ArgumentError` at configuration time instead of a later `NoMethodError` on a
51
+ retry path. ([#140](https://github.com/kamui/retriable/pull/140))
52
+
53
+ ### Internal
54
+
55
+ - Add RBS type signatures for the public API (`Retriable.configure`, `config`,
56
+ `retriable`, `with_override`, `with_context`, and `Retriable::Config`) and
57
+ validate them in CI with `rbs validate`.
58
+ ([#142](https://github.com/kamui/retriable/pull/142))
59
+ - Enforce a minimum test coverage floor and add a `bundler-audit` dependency
60
+ audit job to CI. ([#143](https://github.com/kamui/retriable/pull/143))
61
+ - Remove an unused `CC_TEST_REPORTER_ID` from the CI workflow.
62
+ ([#141](https://github.com/kamui/retriable/pull/141))
63
+
64
+ ## 4.1.0
65
+
66
+ ### Bug fixes
67
+
68
+ - A per-call or `with_context` `tries:` now clears an inherited `intervals:` from
69
+ global config or a context, matching the documented precedence. Previously
70
+ `Retriable.retriable(tries: 1)` was silently ignored when `intervals` was
71
+ configured, running `intervals.size + 1` times. Passing both `intervals:` and
72
+ `tries:` in the same call still lets `intervals:` win.
73
+
74
+ ## 4.0.0
75
+
76
+ **This is a major release with breaking changes. Please read carefully before upgrading.**
77
+
78
+ ### Breaking changes
79
+
80
+ - Removed `timeout:` option. The `timeout:` option has been removed from `Retriable.retriable`, `Retriable.configure`, and `Retriable.with_override`. It was a thin wrapper around Ruby's `Timeout.timeout`, which has well-documented safety issues: it interrupts execution at arbitrary lines and can corrupt internal state in libraries that are not interrupt-safe (mutexes, file handles, network sockets, allocator state). This was first raised against this gem in [#96](https://github.com/kamui/retriable/issues/96) in 2021; Retriable 3.8.0 deprecated the option, and 4.0 removes the footgun entirely. As a side effect, the historical bug where Retriable's own internal `Timeout::Error` was silently retried by default is no longer reachable, since Retriable no longer raises a timeout itself. User-raised `Timeout::Error` (for example, from a `Timeout.timeout` block you write inside the retried block) is still matched by the default `on: [StandardError]` because `Timeout::Error < RuntimeError < StandardError`. Passing `timeout:` to `Retriable.retriable` or `Retriable.with_override` now raises `ArgumentError`; setting `config.timeout` in `Retriable.configure` now raises `NoMethodError` because the configuration attribute has been removed. See the [4.0 migration section in the README](README.md#migration-from-3x-to-40) for replacement patterns.
81
+ - Minimum Ruby version is now 3.2. Support for Ruby 2.x, 3.0, and 3.1 has been dropped in Retriable 4.0. If you need Retriable on Ruby 2.3.0-3.1.x, the 3.8.x line (`~> 3.8`) remains available.
82
+
83
+ ### Features
84
+
85
+ - Add [`on_give_up`](README.md#callbacks) callback that runs when Retriable stops retrying after a rescued retriable exception. Receives `(exception, try, elapsed_time, next_interval, reason)`, where `reason` is `:tries_exhausted` or `:max_elapsed_time`. Does not fire for non-retriable exceptions or `retry_if` rejections. Pass `on_give_up: false` to suppress a configured handler for a single call.
86
+ - Accept a [`Set` of `Exception` classes](README.md#configuring-which-options-to-retry-with-on) as the `on:` option, in addition to a single class, an `Array`, or a `Hash`.
87
+
88
+ ### Internal
89
+
90
+ - Switched `Retriable.retriable`, `Retriable.with_context`, and the `Kernel` extension methods to Ruby 3.1+ anonymous block forwarding. No user-visible behavior change.
91
+
92
+ ## 3.8.0
93
+
94
+ ### Deprecations
95
+
96
+ - Deprecated the `timeout:` option ahead of its removal in Retriable 4.0. Non-nil timeout values supplied through `Retriable.configure`, `Retriable.retriable(...)`, or `Retriable.with_override(...)` now emit a deprecation warning while keeping the existing runtime behavior unchanged. On Ruby 2.7+ the warning is emitted via `Kernel.warn(..., category: :deprecated)`, so callers can silence it through the standard Ruby controls (`Warning[:deprecated] = false`, `ruby -W:no-deprecated`, or a custom `Warning.warn`). To keep the notice from drowning busy applications, it is emitted at most once per process; suppression via `Warning[:deprecated]` leaves the warner armed for the next call that re-enables the category. Prefer library-native timeout settings, or wrap the retried block in `Timeout.timeout(...)` directly if you still need that behavior. See the README migration guidance for details.
97
+
98
+ ## 3.7.0
99
+
100
+ - Feature: Opt-in unbounded retries via `tries: Float::INFINITY`. Requires a finite `max_elapsed_time` as a safety bound and is incompatible with custom `intervals:`. Both invalid configurations raise `ArgumentError` from `Config#validate!`.
101
+
102
+ ## 3.6.1
103
+
104
+ - Fix: Validate the `on:` option before retrying. Previously, passing a non-`Exception` value such as `Object`, `Kernel`, or a plain `Module` (which appear in every `Exception`'s ancestor chain) would silently retry process-critical exceptions like `SystemExit` and `Interrupt`. The `on:` option now requires an `Exception` subclass, an array of them, or a hash whose keys are such classes and whose values are `nil`, a `Regexp`, or an array of `Regexp`s. Invalid shapes raise `ArgumentError` before the block runs.
105
+ - Fix: Validate `with_override(contexts:)` shape before applying overrides. `contexts` may be `nil` or a hash, and each per-context override must be a hash.
106
+ - Docs: Document that `on_retry: false` disables a callback set in `Retriable.configure` for a single call.
107
+
108
+ ## 3.6.0
109
+
110
+ - Breaking: `Retriable.override` and `Retriable.reset_override` are removed and replaced by block-scoped `Retriable.with_override(opts) { ... }`. The new API requires a block, restores the previous override (or absence of override) when the block exits via `ensure`, and is thread-local — overrides set in one thread do not affect other threads, and child threads do not inherit them. Fibers within a thread still share the thread's active override. Nested `with_override` calls correctly restore the outer override on inner exit. See the README and `docs/testing.md` for migration and testing patterns. This replaces the override API introduced in 3.5.0.
111
+
112
+ ## 3.5.1
113
+
114
+ - Fix: Validate retry timing and count options before use to reject invalid retry configurations. `tries` must now be a positive integer unless a custom `intervals` array is provided.
115
+
116
+ ## 3.5.0
117
+
118
+ - Fix: Do not count skipped sleep intervals against `max_elapsed_time` when `sleep_disabled` is true.
119
+ - Add `override` and `reset_override` APIs to force retry settings over local call options when needed (for example, test short-circuiting).
120
+
3
121
  ## 3.4.1
4
122
 
5
123
  - Fix: Use `Process.clock_gettime(CLOCK_MONOTONIC)` for elapsed time tracking so retry timing is immune to wall-clock adjustments (NTP, manual changes).
data/Gemfile CHANGED
@@ -10,7 +10,10 @@ group :test do
10
10
  end
11
11
 
12
12
  group :development do
13
- gem "rubocop"
13
+ gem "bundler-audit", "~> 0.9"
14
+ gem "listen", "~> 3.1"
15
+ gem "rbs", "~> 4.0", platforms: :ruby
16
+ gem "rubocop", "~> 1.86"
14
17
  end
15
18
 
16
19
  group :development, :test do