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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9610bcda3bdfb95c885c6c31c4a2450a4c31824f877ad38e7ca3c34c4fd57d6c
4
- data.tar.gz: d748c2da29ba2ca844bc74354591196a6645a915d725fea07ab743d0b6343bf2
3
+ metadata.gz: 03aa7b6a715e0990279468f71a5bacbd03b94f983c16083570a09dc46c69d325
4
+ data.tar.gz: 1b53f85622bfa3868585ea8836df867a37da5b4142b769ad8b968d9865c001c2
5
5
  SHA512:
6
- metadata.gz: bf3e8a28916019f60f64ce668cd919e4b59e3ebcb50e397266363b7f43d093cbefd06bb41b9816351b9435484b5948eaf5c45e5408d677d76c0ac879ae98b21e
7
- data.tar.gz: b387b82d92712aba64d47e0a8ac33abc9789dba435e88e0020de6eae46881938fcdba5f16da39cbc3930e8a8e9b4bdacf3688388c9d328be25845915b341a5ce
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 ticket or quota.
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 == "80"
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
- Unsuccessful responses (e.g. 5xx responses) do not raise exceptions, and as such are not marked as failures by default. The `open_circuit_server_errors` Semian configuration parameter may be set to enable this behaviour, to mark unsuccessful responses as failures as seen below:
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: circuit breaker and bulkheading. To understand
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. We provide a [docker-compose](https://docs.docker.com/compose/) file
758
- that runs MySQL, Redis, Toxiproxy and Ruby in containers. Use
759
- the steps below to work on Semian from a Mac OS environment.
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/
@@ -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 :ticket or :quota parameter, you provided neither");
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 :ticket or :quota parameter, you provided both");
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 :name, :half_open_resource_timeout, :error_timeout, :state, :last_error
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
- window.reject! { |err_time| err_time + @error_threshold_timeout < time.to_i }
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Semian
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
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.15.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-09-12 00:00:00.000000000 Z
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