sorbet_typed-short_circuit 0.1.0 → 1.0.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 +4 -4
- data/.cz.yaml +20 -0
- data/.pre-commit-config.yaml +8 -0
- data/CHANGELOG.md +27 -0
- data/lib/sorbet_typed/short_circuit/circuit_breaker/untyped_call.rb +5 -5
- data/lib/sorbet_typed/short_circuit/circuit_breaker.rb +14 -0
- data/lib/sorbet_typed/short_circuit/signals/shorted.rb +6 -0
- data/lib/sorbet_typed/short_circuit/version.rb +1 -1
- data/lib/sorbet_typed/short_circuit.rb +34 -19
- data/rbi/sorbet_typed/short_circuit/circuit_breaker.rbi +20 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef54af7b2d2c19ddea4ad8032de8dc0bac9f0897be33326492baf17c84b116da
|
|
4
|
+
data.tar.gz: 2abb0ab9abe6c95c38ceb991b754b0964f89d6f658145075b4a2afa5dcd00f4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b2d8c8940ff7ea7ef5dc94570005de6b5b57496dc0f60a3b40989e60671de0c0dc59e9cace3339ec6d12d10a353090e46ac71fbe037e2f27ee7c41be83adc5a
|
|
7
|
+
data.tar.gz: 518dc424888b0c2dde66b010fd2019736f8e7cca0619c1abb798a3739ad5b3df8af8c2b9842de2da7db9261de5d542e80b444c1a4be002c3740f0891d22f0c00
|
data/.cz.yaml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
commitizen:
|
|
3
|
+
allowed_prefixes:
|
|
4
|
+
- fixup!
|
|
5
|
+
- squash!
|
|
6
|
+
- Merge
|
|
7
|
+
- Revert
|
|
8
|
+
- '[WIP]'
|
|
9
|
+
annotated_tag: true
|
|
10
|
+
name: cz_conventional_commits
|
|
11
|
+
pre_bump_hooks:
|
|
12
|
+
- mise x -- bundle install
|
|
13
|
+
- mise run update
|
|
14
|
+
- mise run format
|
|
15
|
+
tag_format: v$version
|
|
16
|
+
update_changelog_on_bump: true
|
|
17
|
+
version: 1.0.0
|
|
18
|
+
version_files:
|
|
19
|
+
- lib/sorbet_typed/short_circuit/version.rb
|
|
20
|
+
version_scheme: semver2
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## v1.0.0 (2025-11-07)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **CircuitBreaker**: allow public usage in signatures
|
|
6
|
+
- **interface**: add specs and update interfaces
|
|
7
|
+
- **renovate**: update CI matrix on lockFileMaintenance
|
|
8
|
+
- **ci**: trigger renovate pipeline on default branch
|
|
9
|
+
- **mise**: change default task output to "replacing"
|
|
10
|
+
- **mise**: execute typecheck when running lint task
|
|
11
|
+
- **renovate**: remove manual usage dependency declaration, as renovate seems to know it now
|
|
12
|
+
- initial commit
|
|
13
|
+
|
|
14
|
+
### Fix
|
|
15
|
+
|
|
16
|
+
- **ci**: adjust job rules
|
|
17
|
+
- **sorbet**: robust tapioca dsl update/verification + removal of unused DSL RBIs
|
|
18
|
+
- **sorbet**: exclude local gem from RBI generation
|
|
19
|
+
- **renovate**: group ci ruby version matrix upgrades
|
|
20
|
+
- **ci**: run ruby version matrix validation only for merge request events
|
|
21
|
+
- **ci**: generate ruby version matrix only for versions with valid docker images
|
|
22
|
+
- **appraisals**: make appraisal gem versions always deterministic by tracking lock files and update them via renovate
|
|
23
|
+
lockFileMaintenance
|
|
24
|
+
- **coverage**: explicitly track all relevant ruby files, even if they don't get required
|
|
25
|
+
- **ci**: make pipeline jobs interruptible by default to support canceling redundant pipelines
|
|
26
|
+
- **coverage**: enable coverage in CI and exclude temporary, untested code from coverage
|
|
27
|
+
- **rubocop**: make it pass by disabling offenses on temporary code
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# typed: false # rubocop:disable Sorbet/HasSigil -- type for this gets defined by rbi/sorbet_typed/short_circuit/circuit_breaker.rbi
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# HACK: monkey patching the circuit breaker to have an untyped call method. It's
|
|
5
|
-
# signatures get provided by rbi/sorbet_typed/short_circuit/circuit_breaker.rbi
|
|
6
|
-
# to support overloads.
|
|
7
|
-
|
|
8
4
|
module SorbetTyped
|
|
9
5
|
class ShortCircuit
|
|
10
|
-
|
|
6
|
+
# HACK: monkey patching the circuit breaker to have an untyped call method. It's
|
|
7
|
+
# signatures get provided by rbi/sorbet_typed/short_circuit/circuit_breaker.rbi
|
|
8
|
+
# to support overloads.
|
|
9
|
+
# -- documentation comment exists on the main implementation of this class
|
|
10
|
+
class CircuitBreaker
|
|
11
11
|
def call(result)
|
|
12
12
|
case result
|
|
13
13
|
when SorbetTyped::ShortCircuit::Signals::Shorted
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
module SorbetTyped
|
|
5
5
|
class ShortCircuit
|
|
6
|
+
# Module to be used in type signatures to allow passing CircuitBreaker
|
|
7
|
+
# instances around. This module is publicly available, in contrast to the
|
|
8
|
+
# CircuitBreaker class.
|
|
9
|
+
module CircuitBreakerType
|
|
10
|
+
extend T::Generic
|
|
11
|
+
extend T::Helpers
|
|
12
|
+
|
|
13
|
+
sealed!
|
|
14
|
+
|
|
15
|
+
ShortedResult = type_member
|
|
16
|
+
end
|
|
17
|
+
|
|
6
18
|
# Callable implementing the logic to fail fast if the input is a Shorted
|
|
7
19
|
# signal. To be used like Dry::Monads `yield foo` syntax.
|
|
8
20
|
#
|
|
@@ -11,6 +23,8 @@ module SorbetTyped
|
|
|
11
23
|
extend T::Sig
|
|
12
24
|
extend T::Generic
|
|
13
25
|
|
|
26
|
+
include CircuitBreakerType
|
|
27
|
+
|
|
14
28
|
ShortedResult = type_member
|
|
15
29
|
|
|
16
30
|
private
|
|
@@ -24,6 +24,7 @@ module SorbetTyped
|
|
|
24
24
|
# and other low level ruby stuff.
|
|
25
25
|
########################################################################
|
|
26
26
|
sig { params(klass: ::T::Class[::T.anything]).returns(::T::Boolean) }
|
|
27
|
+
# :reek:UtilityFunction -- because the class inherits from BasicObject, self.class cannot be used
|
|
27
28
|
def is_a?(klass)
|
|
28
29
|
klass == Shorted
|
|
29
30
|
end
|
|
@@ -44,6 +45,11 @@ module SorbetTyped
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
sig { params(method_name: ::Symbol, _include_all: ::T::Boolean).returns(::T::Boolean) }
|
|
48
|
+
# :reek:BooleanParameter -- mirroring the respond_to? implementation
|
|
49
|
+
# from Object
|
|
50
|
+
#
|
|
51
|
+
# :reek:UtilityFunction -- this object responds to only one method. It's
|
|
52
|
+
# ok to not get it from instance state.
|
|
47
53
|
def respond_to?(method_name, _include_all = false) # rubocop:disable Style/OptionalBooleanParameter -- mirroring the respond_to? implementation from Object
|
|
48
54
|
method_name == :payload
|
|
49
55
|
end
|
|
@@ -91,25 +91,21 @@ module SorbetTyped
|
|
|
91
91
|
self.short_circuited = false
|
|
92
92
|
yield(CircuitBreaker[ShortedResult].new(circuit_id: object_id))
|
|
93
93
|
rescue Errors::CircuitShorted => exception
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
# cannot be ensured at runtime. Type-safety is still ensured, because the
|
|
110
|
-
# error and circuit breaker classes are private and can neither be
|
|
111
|
-
# instantiated, thrown or rescued (coding "normally").
|
|
112
|
-
T.cast(exception, Errors::CircuitShorted[SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult]]).signal
|
|
94
|
+
handle_shorted_circuit(
|
|
95
|
+
shorted_exception:
|
|
96
|
+
# NOTE: sorbet is only able to detect
|
|
97
|
+
# `SorbetTyped::ShortCircuit::CircuitShortedError[T.anything]` in this
|
|
98
|
+
# rescue. But because it must come from `CircuitBreaker[ShortedResult]`,
|
|
99
|
+
# it will also always be
|
|
100
|
+
# `CircuitShortedError[SorbetTyped::ShortCircuit::Shorted[ShortedResult]]`.
|
|
101
|
+
# So we tell that to sorbet.
|
|
102
|
+
#
|
|
103
|
+
# Unfortunately, because sorbet erases generic types at runtime, this
|
|
104
|
+
# cannot be ensured at runtime. Type-safety is still ensured, because the
|
|
105
|
+
# error and circuit breaker classes are private and can neither be
|
|
106
|
+
# instantiated, thrown or rescued (coding "normally").
|
|
107
|
+
T.cast(exception, Errors::CircuitShorted[SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult]])
|
|
108
|
+
)
|
|
113
109
|
end
|
|
114
110
|
|
|
115
111
|
sig do
|
|
@@ -143,5 +139,24 @@ module SorbetTyped
|
|
|
143
139
|
end
|
|
144
140
|
|
|
145
141
|
# TODO: #success? method
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
sig do
|
|
146
|
+
params(
|
|
147
|
+
shorted_exception: Errors::CircuitShorted[SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult]]
|
|
148
|
+
).
|
|
149
|
+
returns(Signals::Shorted[ShortedResult])
|
|
150
|
+
end
|
|
151
|
+
def handle_shorted_circuit(shorted_exception:)
|
|
152
|
+
# This ensures, the circuit can only be broken by a circuit shorted
|
|
153
|
+
# exception raised in it's own circuit breaker. Everything else is
|
|
154
|
+
# re-raised.
|
|
155
|
+
raise shorted_exception unless shorted_exception.circuit_id == object_id
|
|
156
|
+
|
|
157
|
+
self.short_circuited = true
|
|
158
|
+
|
|
159
|
+
shorted_exception.signal
|
|
160
|
+
end
|
|
146
161
|
end
|
|
147
162
|
end
|
|
@@ -2,12 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
module SorbetTyped
|
|
4
4
|
class ShortCircuit
|
|
5
|
+
module CircuitBreakerType
|
|
6
|
+
# NOTE: providing overloads here, because the possible input and output
|
|
7
|
+
# cases cannot be fully modeled using a single signature within the actual
|
|
8
|
+
# class.
|
|
9
|
+
sig { params(result: SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult]).returns(T.noreturn) }
|
|
10
|
+
sig do
|
|
11
|
+
|
|
12
|
+
type_parameters(:SuccessType).
|
|
13
|
+
params(
|
|
14
|
+
result: T.any(
|
|
15
|
+
SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult],
|
|
16
|
+
T.all(T.type_parameter(:SuccessType), Object)
|
|
17
|
+
)
|
|
18
|
+
).
|
|
19
|
+
returns(T.all(T.type_parameter(:SuccessType), Object))
|
|
20
|
+
end
|
|
21
|
+
def call(result); end
|
|
22
|
+
end
|
|
23
|
+
|
|
5
24
|
class CircuitBreaker
|
|
6
25
|
# NOTE: providing overloads here, because the possible input and output
|
|
7
26
|
# cases cannot be fully modeled using a single signature within the actual
|
|
8
27
|
# class.
|
|
9
28
|
sig { params(result: SorbetTyped::ShortCircuit::Signals::Shorted[ShortedResult]).returns(T.noreturn) }
|
|
10
29
|
sig do
|
|
30
|
+
|
|
11
31
|
type_parameters(:SuccessType).
|
|
12
32
|
params(
|
|
13
33
|
result: T.any(
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sorbet_typed-short_circuit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Richard Kramer
|
|
@@ -36,7 +36,10 @@ executables: []
|
|
|
36
36
|
extensions: []
|
|
37
37
|
extra_rdoc_files: []
|
|
38
38
|
files:
|
|
39
|
+
- ".cz.yaml"
|
|
40
|
+
- ".pre-commit-config.yaml"
|
|
39
41
|
- ".shellcheckrc.tmp"
|
|
42
|
+
- CHANGELOG.md
|
|
40
43
|
- COPYING
|
|
41
44
|
- README.md
|
|
42
45
|
- lib/sorbet_typed/short_circuit.rb
|