semian 0.15.0 → 0.16.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/README.md +28 -10
- data/ext/semian/resource.c +2 -2
- data/ext/semian/sysv_semaphores.h +5 -1
- data/lib/semian/circuit_breaker.rb +14 -3
- data/lib/semian/version.rb +1 -1
- data/lib/semian.rb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03aa7b6a715e0990279468f71a5bacbd03b94f983c16083570a09dc46c69d325
|
4
|
+
data.tar.gz: 1b53f85622bfa3868585ea8836df867a37da5b4142b769ad8b968d9865c001c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7f481a7a77c6d91574500e2a636eb6bd9721e61be5c8740265f58ac90895525ed9b34750b7dbb23d97360a3449a7a990994d870c8a9730e8d06350afda7c7de
|
7
|
+
data.tar.gz: 216189dea6814080db529843164dd02235541127ce9058ff803cc3843842220e87340b45a73109a2004d6205194b166b0cbcbf55e46601a5bf5f00c75cb5678c
|
data/README.md
CHANGED
@@ -211,7 +211,7 @@ calculate and adjust ticket counts.
|
|
211
211
|
|
212
212
|
**Note**:
|
213
213
|
|
214
|
-
- You must pass **exactly** one of
|
214
|
+
- You must pass **exactly** one of options: `tickets` or `quota`.
|
215
215
|
- Tickets available will be the ceiling of the quota ratio to the number of workers
|
216
216
|
- So, with one worker, there will always be a minimum of 1 ticket
|
217
217
|
- Workers in different processes will automatically unregister when the process exits.
|
@@ -236,7 +236,7 @@ SEMIAN_PARAMETERS = { tickets: 1,
|
|
236
236
|
error_timeout: 10 }
|
237
237
|
Semian::NetHTTP.semian_configuration = proc do |host, port|
|
238
238
|
# Let's make it only active for github.com
|
239
|
-
if host == "github.com" && port ==
|
239
|
+
if host == "github.com" && port.to_i == 80
|
240
240
|
SEMIAN_PARAMETERS.merge(name: "github.com_80")
|
241
241
|
else
|
242
242
|
nil
|
@@ -282,19 +282,22 @@ Semian::NetHTTP.exceptions += [::OpenSSL::SSL::SSLError]
|
|
282
282
|
Semian::NetHTTP.reset_exceptions
|
283
283
|
# assert_equal(Semian::NetHTTP.exceptions, Semian::NetHTTP::DEFAULT_ERRORS)
|
284
284
|
```
|
285
|
+
|
285
286
|
##### Mark Unsuccessful Responses as Failures
|
286
|
-
|
287
|
+
|
288
|
+
Unsuccessful responses (e.g. 5xx responses) do not raise exceptions,
|
289
|
+
and as such are not marked as failures by default.
|
290
|
+
The `open_circuit_server_errors` Semian configuration parameter may be set to enable this behaviour,
|
291
|
+
to mark unsuccessful responses as failures as seen below:
|
287
292
|
|
288
293
|
```ruby
|
289
294
|
SEMIAN_PARAMETERS = { tickets: 1,
|
290
295
|
success_threshold: 1,
|
291
296
|
error_threshold: 3,
|
292
297
|
error_timeout: 10,
|
293
|
-
open_circuit_server_errors: true}
|
298
|
+
open_circuit_server_errors: true }
|
294
299
|
```
|
295
300
|
|
296
|
-
|
297
|
-
|
298
301
|
# Understanding Semian
|
299
302
|
|
300
303
|
Semian is a library with heuristics for failing fast. This section will explain
|
@@ -415,7 +418,7 @@ response time. This is the problem Semian solves by failing fast.
|
|
415
418
|
|
416
419
|
## How does Semian work?
|
417
420
|
|
418
|
-
Semian consists of two parts:
|
421
|
+
Semian consists of two parts: **Circuit breaker** and **Bulkheading**. To understand
|
419
422
|
Semian, and especially how to configure it, we must understand these patterns
|
420
423
|
and their implementation.
|
421
424
|
|
@@ -453,6 +456,8 @@ There are four configuration parameters for circuit breakers in Semian:
|
|
453
456
|
* **error_threshold_timeout**. The amount of time in seconds that error_threshold errors must occur to open the circuit. Defaults to error_timeout seconds if not set.
|
454
457
|
* **error_timeout**. The amount of time in seconds until trying to query the resource
|
455
458
|
again.
|
459
|
+
* **error_threshold_timeout_enabled**. If set to false it will disable the time window for evicting old exceptions. `error_timeout` is still used and will reset
|
460
|
+
the circuit. Defaults to `true` if not set.
|
456
461
|
* **success_threshold**. The amount of successes on the circuit until closing it
|
457
462
|
again, that is to start accepting all requests to the circuit.
|
458
463
|
* **half_open_resource_timeout**. Timeout for the resource in seconds when the circuit is half-open (supported for MySQL, Net::HTTP and Redis).
|
@@ -754,11 +759,13 @@ non-IO.
|
|
754
759
|
|
755
760
|
# Developing Semian
|
756
761
|
|
757
|
-
Semian requires a Linux environment
|
758
|
-
|
759
|
-
|
762
|
+
Semian requires a Linux environment for **Bulkheading**.
|
763
|
+
We provide a [docker-compose](https://docs.docker.com/compose/) file
|
764
|
+
that runs MySQL, Redis, Toxiproxy and Ruby in containers.
|
765
|
+
Use the steps below to work on Semian from a Mac OS environment.
|
760
766
|
|
761
767
|
## Prerequisites :
|
768
|
+
|
762
769
|
```bash
|
763
770
|
# install docker-for-desktop
|
764
771
|
$ brew cask install docker
|
@@ -819,6 +826,17 @@ $ cd semian
|
|
819
826
|
$ bundle exec rake test:parallel TEST_WORKERS=5 TEST_WORKER_NUM=1
|
820
827
|
```
|
821
828
|
|
829
|
+
### Debug
|
830
|
+
|
831
|
+
Build a semian native extension with debug information.
|
832
|
+
|
833
|
+
```shell
|
834
|
+
$ bundle exec rake clean --trace
|
835
|
+
$ export DEBUG=1
|
836
|
+
$ bundle exec rake build
|
837
|
+
$ bundle install
|
838
|
+
```
|
839
|
+
|
822
840
|
[hystrix]: https://github.com/Netflix/Hystrix
|
823
841
|
[release-it]: https://pragprog.com/titles/mnee2/release-it-second-edition/
|
824
842
|
[shopify]: http://www.shopify.com/
|
data/ext/semian/resource.c
CHANGED
@@ -273,10 +273,10 @@ static void
|
|
273
273
|
check_tickets_xor_quota_arg(VALUE tickets, VALUE quota)
|
274
274
|
{
|
275
275
|
if (tickets == Qnil && quota == Qnil) {
|
276
|
-
rb_raise(rb_eArgError, "Semian configuration require either the :
|
276
|
+
rb_raise(rb_eArgError, "Semian configuration require either the :tickets or :quota parameter, you provided neither");
|
277
277
|
}
|
278
278
|
if (tickets != Qnil && quota != Qnil) {
|
279
|
-
rb_raise(rb_eArgError, "Semian configuration require either the :
|
279
|
+
rb_raise(rb_eArgError, "Semian configuration require either the :tickets or :quota parameter, you provided both");
|
280
280
|
}
|
281
281
|
}
|
282
282
|
|
@@ -10,6 +10,9 @@ and functions associated directly weth semops.
|
|
10
10
|
#include <errno.h>
|
11
11
|
#include <stdio.h>
|
12
12
|
#include <string.h>
|
13
|
+
#ifdef DEBUG
|
14
|
+
#include <unistd.h>
|
15
|
+
#endif
|
13
16
|
|
14
17
|
#include <openssl/sha.h>
|
15
18
|
#include <ruby.h>
|
@@ -110,7 +113,8 @@ acquire_semaphore_without_gvl(void *p);
|
|
110
113
|
static inline void
|
111
114
|
print_sem_vals(int sem_id)
|
112
115
|
{
|
113
|
-
printf("lock %d, tickets: %d configured: %d, registered workers %d\n",
|
116
|
+
printf("[pid=%d][semian] semaphore values lock: %d, tickets: %d configured: %d, registered workers: %d\n",
|
117
|
+
getpid(),
|
114
118
|
get_sem_val(sem_id, SI_SEM_LOCK),
|
115
119
|
get_sem_val(sem_id, SI_SEM_TICKETS),
|
116
120
|
get_sem_val(sem_id, SI_SEM_CONFIGURED_TICKETS),
|
@@ -6,16 +6,24 @@ module Semian
|
|
6
6
|
|
7
7
|
def_delegators :@state, :closed?, :open?, :half_open?
|
8
8
|
|
9
|
-
attr_reader
|
9
|
+
attr_reader(
|
10
|
+
:name,
|
11
|
+
:half_open_resource_timeout,
|
12
|
+
:error_timeout,
|
13
|
+
:state,
|
14
|
+
:last_error,
|
15
|
+
:error_threshold_timeout_enabled,
|
16
|
+
)
|
10
17
|
|
11
18
|
def initialize(name, exceptions:, success_threshold:, error_threshold:,
|
12
19
|
error_timeout:, implementation:, half_open_resource_timeout: nil,
|
13
|
-
error_threshold_timeout: nil)
|
20
|
+
error_threshold_timeout: nil, error_threshold_timeout_enabled: true)
|
14
21
|
|
15
22
|
@name = name.to_sym
|
16
23
|
@success_count_threshold = success_threshold
|
17
24
|
@error_count_threshold = error_threshold
|
18
25
|
@error_threshold_timeout = error_threshold_timeout || error_timeout
|
26
|
+
@error_threshold_timeout_enabled = error_threshold_timeout_enabled.nil? ? true : error_threshold_timeout_enabled
|
19
27
|
@error_timeout = error_timeout
|
20
28
|
@exceptions = exceptions
|
21
29
|
@half_open_resource_timeout = half_open_resource_timeout
|
@@ -131,7 +139,10 @@ module Semian
|
|
131
139
|
end
|
132
140
|
|
133
141
|
def push_time(window, time: Time.now)
|
134
|
-
|
142
|
+
if error_threshold_timeout_enabled
|
143
|
+
window.reject! { |err_time| err_time + @error_threshold_timeout < time.to_i }
|
144
|
+
end
|
145
|
+
|
135
146
|
window << time.to_i
|
136
147
|
end
|
137
148
|
|
data/lib/semian/version.rb
CHANGED
data/lib/semian.rb
CHANGED
@@ -276,6 +276,11 @@ module Semian
|
|
276
276
|
error_threshold: options[:error_threshold],
|
277
277
|
error_threshold_timeout: options[:error_threshold_timeout],
|
278
278
|
error_timeout: options[:error_timeout],
|
279
|
+
error_threshold_timeout_enabled: if options[:error_threshold_timeout_enabled].nil?
|
280
|
+
true
|
281
|
+
else
|
282
|
+
options[:error_threshold_timeout_enabled]
|
283
|
+
end,
|
279
284
|
exceptions: Array(exceptions) + [::Semian::BaseError],
|
280
285
|
half_open_resource_timeout: options[:half_open_resource_timeout],
|
281
286
|
implementation: implementation(**options),
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Francis
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-10-05 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: |2
|
16
16
|
A Ruby C extention that is used to control access to shared resources
|