standard_circuit 0.5.0 → 0.6.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: 1c26b42239426b6e97f01c017a4dead949a827d1f4d3e0cd991493c5292d127a
4
- data.tar.gz: 2689f5e66f85ea012dd3d84f2a17fdf9700fa7938c862ba35a2f5d4f651f4951
3
+ metadata.gz: 195e01d912e93d7bf158cafd091aab7ab27571994e9d4c2953d0a39b76c92d71
4
+ data.tar.gz: 880f2b881ada6a92660c8c26c1c2b49abf2ea283411606a7131c9cf1af8bd75f
5
5
  SHA512:
6
- metadata.gz: fa4ac99fa63f03cd2790084476189a8d0ecc6d3d993b4ceaf5c1aa7d5a06a2fe2b5dcb64f8a5165b230c7a700ae30e2a7385c68301e7e0c7937f64f5216da6a0
7
- data.tar.gz: 0addb3ca191eeb7cf62fe15a297c8997b62e716ca5bf48f9eea1ffbd5493ad429edf994df0b91bf62c89a035e15062ec3b0445460a4304c7a4569a40194ea31c
6
+ metadata.gz: 4706259801d563a2b60183691ad7c4ae935face858318e358d4e3bd5459c4b2eee097da52c8cb4748c7726883455f96a1416a23cde8b0123d172207d2f64b373
7
+ data.tar.gz: 05f1578d83f4bdbc34d310350570322bf4cd357d24d50e07874bed2e34019d33bb3cf0f396e49cf9a598797700aef34d3182b98c730d4a25e737f3f083ad6e80
data/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0] - 2026-10-22
11
+
12
+ ### Fixed
13
+
14
+ - **Zero-argument fallback lambdas no longer crash when the circuit opens.**
15
+ A fallback is called with the error (or `nil` when forced open), so a
16
+ `fallback: -> { ... }` raised `ArgumentError` at exactly the moment the
17
+ circuit opened, the case the fallback exists for. Such lambdas are now called
18
+ without the argument. Fallbacks that take the error, and procs, are
19
+ unchanged. Zero-arity `Method` fallbacks are accepted the same way.
20
+
21
+ ### Changed
22
+
23
+ - **Requires Rails 8.1** (`railties`, `actionmailer`, `actionpack` `>= 8.1`,
24
+ was `>= 8.0`). Every consumer app runs 8.1; 8.0 was never exercised in CI.
25
+
10
26
  ## [0.5.0] - 2026-09-24
11
27
 
12
28
  **Breaking.** Removes everything 0.4 deprecated. Behaviour of everything that remains is unchanged, including 0.4.2's `mailer_retry` (exhaustion reports, then re-raises so the job dead-letters).
data/README.md CHANGED
@@ -54,8 +54,17 @@ end
54
54
  StandardCircuit.run(:stripe) do
55
55
  Stripe::PaymentIntent.create(amount:, currency:)
56
56
  end
57
+
58
+ # with a fallback, returned instead of raising while the circuit is open
59
+ StandardCircuit.run(:analytics, fallback: -> { nil }) do
60
+ Analytics.track(event)
61
+ end
57
62
  ```
58
63
 
64
+ A fallback may take the error (`->(error) { ... }`: the error the block raised,
65
+ or `nil` once the circuit is open, since the block then never runs) or take
66
+ nothing (`-> { ... }`, or a zero-arity `method(...)`); all are called correctly.
67
+
59
68
  ## Error taxonomies
60
69
 
61
70
  `tracked_errors` decide what counts toward tripping a circuit; `skipped_errors` are re-raised without counting (and win over `tracked_errors` when a class matches both). `StandardCircuit::ErrorTaxonomies::<Adapter>.tracked` combines `NetworkErrors.defaults` with the adapter's server-side errors for `Stripe`, `Smtp`, `Aws`, `Faraday`, and `Postmark`; `StandardCircuit::AdapterErrors::<Adapter>.caller_errors` lists the adapter's caller-side (4xx-style) errors.
@@ -12,6 +12,7 @@ module StandardCircuit
12
12
  end
13
13
 
14
14
  def run(name, fallback: nil, &block)
15
+ fallback = accept_error_argument(fallback)
15
16
  forced = @forced_states[name.to_sym]
16
17
  return run_forced_open(name, fallback) if forced == :open
17
18
  return yield if forced == :closed
@@ -73,6 +74,20 @@ module StandardCircuit
73
74
 
74
75
  private
75
76
 
77
+ # A fallback is called with one argument: the error, or nil when the
78
+ # circuit is forced open. A zero-argument lambda (`-> { ... }`, the
79
+ # natural way to write "return this instead") raises ArgumentError on that
80
+ # call, so the fallback would crash at exactly the moment the circuit
81
+ # opens. Accept it, and a zero-arity Method (`fallback: method(:degraded)`),
82
+ # by calling it without the argument. Procs, and callables that take the
83
+ # error, are passed through unchanged.
84
+ def accept_error_argument(fallback)
85
+ strict = fallback.is_a?(Method) || (fallback.is_a?(Proc) && fallback.lambda?)
86
+ return fallback unless strict && fallback.arity.zero?
87
+
88
+ ->(_error) { fallback.call }
89
+ end
90
+
76
91
  def execute(name, fallback, &block)
77
92
  started_at = monotonic_now
78
93
  light = light_for(name)
@@ -1,3 +1,3 @@
1
1
  module StandardCircuit
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_circuit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim
@@ -57,42 +57,42 @@ dependencies:
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '8.0'
60
+ version: '8.1'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '8.0'
67
+ version: '8.1'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: actionmailer
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '8.0'
74
+ version: '8.1'
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: '8.0'
81
+ version: '8.1'
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: actionpack
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
- version: '8.0'
88
+ version: '8.1'
89
89
  type: :runtime
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
- version: '8.0'
95
+ version: '8.1'
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: brakeman
98
98
  requirement: !ruby/object:Gem::Requirement
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  - !ruby/object:Gem::Version
202
202
  version: '0'
203
203
  requirements: []
204
- rubygems_version: 4.0.3
204
+ rubygems_version: 4.0.10
205
205
  specification_version: 4
206
206
  summary: Circuit breaker primitives for Rails apps, built on stoplight.
207
207
  test_files: []