breakers 0.7.1 → 1.0.1
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/.github/workflows/rspec.yml +27 -0
- data/CHANGELOG.md +9 -0
- data/README.md +13 -12
- data/breakers.gemspec +2 -1
- data/lib/breakers/client.rb +3 -2
- data/lib/breakers/service.rb +2 -2
- data/lib/breakers/uptime_middleware.rb +13 -5
- data/lib/breakers/version.rb +1 -1
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1471486e4b71db051dc6b073a4f5f98cd3a2bb6a10b51a3da6d12d24b1bba5f6
|
4
|
+
data.tar.gz: d7703097ccb4bb819a32c80c28cfabc6563520ffd7552961546873243ab2f125
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b99274dd003feb7f3b362950844eca5f9b194b9a30b0959dfdf8003e4163752dc0400cf69d868069a816089467c6d529788de5b4024186fe1c52f0e70db43ebf
|
7
|
+
data.tar.gz: a112b8f32680017e9c98fbd55b122aa2ab30bc33a1a950e9e2c9236ca4d294df4b96338012dab8e4f23e5e0fb89dba04768b37ee43b9eff0e34a1bebb4e78a4a
|
@@ -0,0 +1,27 @@
|
|
1
|
+
name: Run RSpec Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
pull_request:
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- name: Checkout code
|
15
|
+
uses: actions/checkout@v3
|
16
|
+
|
17
|
+
- name: Set up Ruby
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: '3.3.6'
|
21
|
+
bundler-cache: true
|
22
|
+
|
23
|
+
- name: Install dependencies
|
24
|
+
run: bundle install
|
25
|
+
|
26
|
+
- name: Run RSpec tests
|
27
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [1.0] - 2025-03-24
|
4
|
+
### Added
|
5
|
+
- Support matching by service name (#40)
|
6
|
+
|
7
|
+
## [1.0.1] - 2025-06-05
|
8
|
+
### Added
|
9
|
+
- Allows forced outages to persist until explicitly ended, using `bundle exec rake breakers:end_forced_outage service="VAOS"`, for example.
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Or install it yourself as:
|
|
26
26
|
```ruby
|
27
27
|
service = Breakers::Service.new(
|
28
28
|
name: 'messaging',
|
29
|
-
request_matcher: proc { |request_env| request_env.url.host =~ /.*messaging\.va\.gov/ }
|
29
|
+
request_matcher: proc { |breakers_service, request_env, request_service_name| request_env.url.host =~ /.*messaging\.va\.gov/ }
|
30
30
|
)
|
31
31
|
|
32
32
|
client = Breakers::Client.new(redis_connection: redis, services: [service])
|
@@ -57,7 +57,7 @@ are defined like this:
|
|
57
57
|
```ruby
|
58
58
|
service = Breakers::Service.new(
|
59
59
|
name: 'messaging',
|
60
|
-
request_matcher: proc { |request_env|
|
60
|
+
request_matcher: proc { |breakers_service, request_env, request_service_name| breakers_service.name == request_service_name },
|
61
61
|
seconds_before_retry: 60,
|
62
62
|
error_threshold: 50
|
63
63
|
)
|
@@ -142,17 +142,14 @@ It's ok for your plugin to implement only part of this interface.
|
|
142
142
|
|
143
143
|
### Forcing an Outage
|
144
144
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
145
|
+
You can test an outage by faking or forcing an outage using:
|
146
|
+
```
|
147
|
+
Breakers::Outage#begin_forced_outage!
|
148
|
+
```
|
149
|
+
Once an forced outage is started, you must manually stop it using:
|
150
|
+
```
|
151
|
+
Breakers::Outage#end_forced_outage!
|
152
152
|
```
|
153
|
-
|
154
|
-
Unlike with outages detected by the middleware, forced outages are not periodically tested to see if they have completed and must be
|
155
|
-
manually ended with a call to `end_forced_outage!`.
|
156
153
|
|
157
154
|
### Changing the Outage Response
|
158
155
|
|
@@ -177,6 +174,10 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
177
174
|
|
178
175
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
179
176
|
|
177
|
+
**NOTE** If you have not previously signed in to Rubygems, you'll be prompted to:
|
178
|
+
* create and/or sign in to your account via your terminal
|
179
|
+
* (if you aren't already an owner) have an owner add you with `gem owner breakers --add <your_email@email.com>`
|
180
|
+
|
180
181
|
## Contributing
|
181
182
|
|
182
183
|
Bug reports and pull requests are welcome on GitHub at https://github.com/department-of-veterans-affairs/breakers.
|
data/breakers.gemspec
CHANGED
@@ -22,11 +22,12 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
|
+
spec.add_dependency 'base64', '~> 0.2'
|
25
26
|
spec.add_dependency 'faraday', ['>= 1.2.0', '< 3.0']
|
26
27
|
spec.add_dependency 'multi_json', '~> 1.0'
|
27
28
|
|
28
29
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
29
|
-
spec.add_development_dependency 'byebug', '~>
|
30
|
+
spec.add_development_dependency 'byebug', '~> 11.1'
|
30
31
|
spec.add_development_dependency 'fakeredis', '~> 0.6.0'
|
31
32
|
spec.add_development_dependency 'rake', '~> 12.0'
|
32
33
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/breakers/client.rb
CHANGED
@@ -23,10 +23,11 @@ module Breakers
|
|
23
23
|
# Given a request environment, return the service that should handle it.
|
24
24
|
#
|
25
25
|
# @param request_env [Faraday::Env] the request environment
|
26
|
+
# @param service_name [String] the service name
|
26
27
|
# @return [Breakers::Service] the service object
|
27
|
-
def service_for_request(request_env:)
|
28
|
+
def service_for_request(request_env:, service_name:)
|
28
29
|
@services.find do |service|
|
29
|
-
service.handles_request?(request_env: request_env)
|
30
|
+
service.handles_request?(request_env: request_env, service_name: service_name)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
data/lib/breakers/service.rb
CHANGED
@@ -33,8 +33,8 @@ module Breakers
|
|
33
33
|
#
|
34
34
|
# @param request_env [Faraday::Env] the request environment
|
35
35
|
# @return [Boolean] should the service handle the request
|
36
|
-
def handles_request?(request_env:)
|
37
|
-
@configuration[:request_matcher].call(request_env)
|
36
|
+
def handles_request?(request_env:, service_name:)
|
37
|
+
@configuration[:request_matcher].call(self, request_env, service_name)
|
38
38
|
end
|
39
39
|
|
40
40
|
# Get the seconds before retry parameter
|
@@ -4,16 +4,21 @@ require 'multi_json'
|
|
4
4
|
module Breakers
|
5
5
|
# The faraday middleware
|
6
6
|
class UptimeMiddleware < Faraday::Middleware
|
7
|
-
def initialize(app)
|
7
|
+
def initialize(app, args = nil)
|
8
|
+
@service_name = args&.dig(:service_name)
|
8
9
|
super(app)
|
9
10
|
end
|
10
11
|
|
12
|
+
def service_name
|
13
|
+
@service_name
|
14
|
+
end
|
15
|
+
|
11
16
|
def call(request_env)
|
12
17
|
if Breakers.disabled?
|
13
18
|
return @app.call(request_env)
|
14
19
|
end
|
15
20
|
|
16
|
-
service = Breakers.client.service_for_request(request_env: request_env)
|
21
|
+
service = Breakers.client.service_for_request(request_env: request_env, service_name: @service_name)
|
17
22
|
|
18
23
|
if !service
|
19
24
|
return @app.call(request_env)
|
@@ -21,13 +26,15 @@ module Breakers
|
|
21
26
|
|
22
27
|
latest_outage = service.latest_outage
|
23
28
|
|
24
|
-
if latest_outage && !latest_outage
|
25
|
-
if latest_outage.ready_for_retest?(wait_seconds: service.seconds_before_retry)
|
29
|
+
if !latest_outage.nil? && !latest_outage&.ended?
|
30
|
+
if latest_outage.ready_for_retest?(wait_seconds: service.seconds_before_retry) && !latest_outage.forced?
|
31
|
+
# No outage detected, proceed with the request
|
26
32
|
handle_request(service: service, request_env: request_env, current_outage: latest_outage)
|
27
33
|
else
|
28
34
|
outage_response(outage: latest_outage, service: service)
|
29
35
|
end
|
30
36
|
else
|
37
|
+
# No outage detected, proceed with the request
|
31
38
|
handle_request(service: service, request_env: request_env)
|
32
39
|
end
|
33
40
|
end
|
@@ -40,9 +47,10 @@ module Breakers
|
|
40
47
|
end
|
41
48
|
if Breakers.outage_response[:type] == :status_code
|
42
49
|
Faraday::Response.new.tap do |response|
|
50
|
+
forced = outage.forced? ? '[FORCED] ' : ''
|
43
51
|
response.finish(
|
44
52
|
status: Breakers.outage_response[:status_code],
|
45
|
-
body: "Outage detected on #{service.name} beginning at #{outage.start_time.to_i}",
|
53
|
+
body: "#{forced}Outage detected on #{service.name} beginning at #{outage.start_time.to_i}",
|
46
54
|
response_headers: {}
|
47
55
|
)
|
48
56
|
end
|
data/lib/breakers/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: breakers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aubrey Holland
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: base64
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.2'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: faraday
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,14 +78,14 @@ dependencies:
|
|
64
78
|
requirements:
|
65
79
|
- - "~>"
|
66
80
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
81
|
+
version: '11.1'
|
68
82
|
type: :development
|
69
83
|
prerelease: false
|
70
84
|
version_requirements: !ruby/object:Gem::Requirement
|
71
85
|
requirements:
|
72
86
|
- - "~>"
|
73
87
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
88
|
+
version: '11.1'
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: fakeredis
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -179,10 +193,12 @@ extensions: []
|
|
179
193
|
extra_rdoc_files: []
|
180
194
|
files:
|
181
195
|
- ".github/workflows/codeql.yml"
|
196
|
+
- ".github/workflows/rspec.yml"
|
182
197
|
- ".gitignore"
|
183
198
|
- ".rspec"
|
184
199
|
- ".rubocop.yml"
|
185
200
|
- ".travis.yml"
|
201
|
+
- CHANGELOG.md
|
186
202
|
- CONTRIBUTING.md
|
187
203
|
- Gemfile
|
188
204
|
- LICENSE.md
|
@@ -217,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
233
|
- !ruby/object:Gem::Version
|
218
234
|
version: '0'
|
219
235
|
requirements: []
|
220
|
-
rubygems_version: 3.
|
236
|
+
rubygems_version: 3.5.11
|
221
237
|
signing_key:
|
222
238
|
specification_version: 4
|
223
239
|
summary: Handle outages to backend systems with a Faraday middleware
|