semian 0.13.2 → 0.15.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: 540294c5a9ecdfdcbafcdc1485afd1314a94fd869501bc6795ee327606d3e799
4
- data.tar.gz: 5855959232d25ea3c2da1f7ca7096c18afb15161ac8116e8f1ece9792fd456e4
3
+ metadata.gz: 9610bcda3bdfb95c885c6c31c4a2450a4c31824f877ad38e7ca3c34c4fd57d6c
4
+ data.tar.gz: d748c2da29ba2ca844bc74354591196a6645a915d725fea07ab743d0b6343bf2
5
5
  SHA512:
6
- metadata.gz: c7549cd0c6dc515733612fcd7b200c23467104c5616ff9501b65a554712e0449d07d8d2d479b45962cffb87c8e6cd2fc82d695a1d9f399a5724b3b4c241c59a8
7
- data.tar.gz: cf31ff975016b22e101db10813d73ab8288584657c9f7319ef222790dcd052d3ab45caedcca2639140d2199be87d1f790f0c82edf918d388c669f9be68b467f2
6
+ metadata.gz: bf3e8a28916019f60f64ce668cd919e4b59e3ebcb50e397266363b7f43d093cbefd06bb41b9816351b9435484b5948eaf5c45e5408d677d76c0ac879ae98b21e
7
+ data.tar.gz: b387b82d92712aba64d47e0a8ac33abc9789dba435e88e0020de6eae46881938fcdba5f16da39cbc3930e8a8e9b4bdacf3688388c9d328be25845915b341a5ce
data/README.md CHANGED
@@ -531,7 +531,7 @@ provides an easy way to get the semaphore key:
531
531
 
532
532
  ```
533
533
  irb> require 'semian'
534
- irb> puts Semian::Resource.new(:your_resource_name, tickets:1).key # do this from a dev machine
534
+ irb> puts Semian::Resource.new(:your_resource_name, tickets: 42).key # do this from a dev machine
535
535
  "0x48af51ea"
536
536
  ```
537
537
 
@@ -553,8 +553,8 @@ otime = Thu Mar 30 15:06:16 2017
553
553
  ctime = Mon Mar 13 20:25:36 2017
554
554
  semnum value ncount zcount pid
555
555
  0 1 0 0 48
556
- 1 25 0 0 48
557
- 2 25 0 0 27
556
+ 1 42 0 0 48
557
+ 2 42 0 0 27
558
558
  3 31 0 0 48
559
559
  ```
560
560
 
data/lib/semian/mysql2.rb CHANGED
@@ -43,16 +43,18 @@ module Semian
43
43
  %r{\A(?:/\*.*?\*/)?\s*RELEASE\s+SAVEPOINT}i,
44
44
  )
45
45
 
46
- # The naked methods are exposed as `raw_query` and `raw_connect` for instrumentation purpose
47
- def self.included(base)
48
- base.send(:alias_method, :raw_query, :query)
49
- base.send(:remove_method, :query)
46
+ class << self
47
+ # The naked methods are exposed as `raw_query` and `raw_connect` for instrumentation purpose
48
+ def included(base)
49
+ base.send(:alias_method, :raw_query, :query)
50
+ base.send(:remove_method, :query)
50
51
 
51
- base.send(:alias_method, :raw_connect, :connect)
52
- base.send(:remove_method, :connect)
52
+ base.send(:alias_method, :raw_connect, :connect)
53
+ base.send(:remove_method, :connect)
53
54
 
54
- base.send(:alias_method, :raw_ping, :ping)
55
- base.send(:remove_method, :ping)
55
+ base.send(:alias_method, :raw_ping, :ping)
56
+ base.send(:remove_method, :ping)
57
+ end
56
58
  end
57
59
 
58
60
  def semian_identifier
@@ -68,6 +70,8 @@ module Semian
68
70
  end
69
71
 
70
72
  def ping
73
+ return false if closed?
74
+
71
75
  result = nil
72
76
  acquire_semian_resource(adapter: :mysql, scope: :ping) do
73
77
  result = raw_ping
data/lib/semian/rails.rb CHANGED
@@ -4,6 +4,23 @@ require "active_record/connection_adapters/abstract_adapter"
4
4
 
5
5
  module Semian
6
6
  module Rails
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # Translate ConnectionNotEstablished errors to their original
11
+ # cause if applicable. When we have a CircuitOpenErorr we don't
12
+ # want the Active Record error, but rather the original cause.
13
+ def new_client(config)
14
+ super
15
+ rescue ActiveRecord::ConnectionNotEstablished => e
16
+ if e.cause.is_a?(Mysql2::CircuitOpenError)
17
+ raise e.cause
18
+ else
19
+ raise
20
+ end
21
+ end
22
+ end
23
+
7
24
  def semian_resource
8
25
  @semian_resource ||= client_connection.semian_resource
9
26
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/redis_client"
4
+
5
+ class Redis
6
+ BaseConnectionError.include(::Semian::AdapterError)
7
+ OutOfMemoryError.include(::Semian::AdapterError)
8
+
9
+ class SemianError < BaseConnectionError
10
+ def initialize(semian_identifier, *args)
11
+ super(*args)
12
+ @semian_identifier = semian_identifier
13
+ end
14
+ end
15
+
16
+ ResourceBusyError = Class.new(SemianError)
17
+ CircuitOpenError = Class.new(SemianError)
18
+
19
+ Client::ERROR_MAPPING.merge!(
20
+ RedisClient::CircuitOpenError => Redis::CircuitOpenError,
21
+ RedisClient::ResourceBusyError => Redis::ResourceBusyError,
22
+ )
23
+ end
24
+
25
+ module Semian
26
+ module RedisV5
27
+ def semian_resource
28
+ _client.semian_resource
29
+ end
30
+
31
+ def semian_identifier
32
+ _client.semian_identifier
33
+ end
34
+ end
35
+
36
+ module RedisV5Client
37
+ private
38
+
39
+ def translate_error!(error)
40
+ redis_error = translate_error_class(error.class)
41
+ if redis_error < ::Semian::AdapterError
42
+ redis_error = redis_error.new(error.message)
43
+ redis_error.semian_identifier = semian_identifier
44
+ end
45
+ raise redis_error, error.message, error.backtrace
46
+ end
47
+ end
48
+ end
49
+
50
+ ::Redis.prepend(Semian::RedisV5)
51
+ ::Redis::Client.prepend(Semian::RedisV5Client)
data/lib/semian/redis.rb CHANGED
@@ -3,6 +3,12 @@
3
3
  require "semian/adapter"
4
4
  require "redis"
5
5
 
6
+ if Redis::VERSION >= "5"
7
+ gem "redis", ">= 5.0.3"
8
+ require "semian/redis/v5"
9
+ return
10
+ end
11
+
6
12
  class Redis
7
13
  Redis::BaseConnectionError.include(::Semian::AdapterError)
8
14
  ::Errno::EINVAL.include(::Semian::AdapterError)
@@ -58,20 +64,22 @@ class Redis
58
64
  end
59
65
 
60
66
  module Semian
61
- module Redis
67
+ module RedisV4
62
68
  include Semian::Adapter
63
69
 
64
70
  ResourceBusyError = ::Redis::ResourceBusyError
65
71
  CircuitOpenError = ::Redis::CircuitOpenError
66
72
  ResolveError = ::Redis::ResolveError
67
73
 
68
- # The naked methods are exposed as `raw_query` and `raw_connect` for instrumentation purpose
69
- def self.included(base)
70
- base.send(:alias_method, :raw_io, :io)
71
- base.send(:remove_method, :io)
74
+ class << self
75
+ # The naked methods are exposed as `raw_query` and `raw_connect` for instrumentation purpose
76
+ def included(base)
77
+ base.send(:alias_method, :raw_io, :io)
78
+ base.send(:remove_method, :io)
72
79
 
73
- base.send(:alias_method, :raw_connect, :connect)
74
- base.send(:remove_method, :connect)
80
+ base.send(:alias_method, :raw_connect, :connect)
81
+ base.send(:remove_method, :connect)
82
+ end
75
83
  end
76
84
 
77
85
  def semian_identifier
@@ -150,4 +158,4 @@ module Semian
150
158
  end
151
159
  end
152
160
 
153
- ::Redis::Client.include(Semian::Redis)
161
+ ::Redis::Client.include(Semian::RedisV4)
@@ -5,6 +5,14 @@ require "redis-client"
5
5
 
6
6
  class RedisClient
7
7
  ConnectionError.include(::Semian::AdapterError)
8
+ ConnectionError.class_eval do
9
+ # A Connection Reset is a fast failure and we don't want to track these errors in semian
10
+ def marks_semian_circuits?
11
+ !message.include?("Connection reset by peer")
12
+ end
13
+ end
14
+
15
+ OutOfMemoryError.include(::Semian::AdapterError)
8
16
 
9
17
  class SemianError < ConnectionError
10
18
  def initialize(semian_identifier, *args)
@@ -72,7 +80,7 @@ module Semian
72
80
  end
73
81
 
74
82
  module RedisClient
75
- EXCEPTIONS = [::RedisClient::ConnectionError]
83
+ EXCEPTIONS = [::RedisClient::ConnectionError, ::RedisClient::OutOfMemoryError]
76
84
 
77
85
  include Semian::Adapter
78
86
  include RedisClientCommon
@@ -110,4 +118,4 @@ module Semian
110
118
  end
111
119
 
112
120
  RedisClient.prepend(Semian::RedisClient)
113
- RedisClient::Pooled.prepend(Semian::RedisClient)
121
+ RedisClient::Pooled.prepend(Semian::RedisClientPool)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Semian
4
- VERSION = "0.13.2"
4
+ VERSION = "0.15.0"
5
5
  end
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.13.2
4
+ version: 0.15.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-08-19 00:00:00.000000000 Z
13
+ date: 2022-09-12 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
@@ -21,7 +21,6 @@ extensions:
21
21
  - ext/semian/extconf.rb
22
22
  extra_rdoc_files: []
23
23
  files:
24
- - CHANGELOG.md
25
24
  - LICENSE.md
26
25
  - README.md
27
26
  - ext/semian/extconf.rb
@@ -46,6 +45,7 @@ files:
46
45
  - lib/semian/protected_resource.rb
47
46
  - lib/semian/rails.rb
48
47
  - lib/semian/redis.rb
48
+ - lib/semian/redis/v5.rb
49
49
  - lib/semian/redis_client.rb
50
50
  - lib/semian/resource.rb
51
51
  - lib/semian/simple_integer.rb
@@ -60,6 +60,8 @@ metadata:
60
60
  allowed_push_host: https://rubygems.org
61
61
  bug_tracker_uri: https://github.com/Shopify/semian/issues
62
62
  changelog_uri: https://github.com/Shopify/semian/blob/master/CHANGELOG.md
63
+ documentation_uri: https://github.com/Shopify/semian
64
+ homepage_uri: https://github.com/Shopify/semian
63
65
  source_code_uri: https://github.com/Shopify/semian
64
66
  post_install_message:
65
67
  rdoc_options: []
data/CHANGELOG.md DELETED
@@ -1,243 +0,0 @@
1
- # Unreleased
2
-
3
- # v0.13.2
4
-
5
- * Fix: Update AbstractAdapter patch to accomodate recent Rails changes. (#364)
6
-
7
- # v0.13.1
8
-
9
- * Fix: Raise `Redis::OutOfMemoryError` for messages that match `OOM command not allowed when used memory > 'maxmemory'` rather than checking `start_with?("OOM ")`. (#367)
10
-
11
- # v0.13.0
12
-
13
- * Refactor: Replace Time.now with CLOCK_MONOTONIC in MockServer (#318)
14
- * Fix: Circuit not open for GRPC::ActiveCall::Operation failures (#348)
15
-
16
- # v0.12.0
17
-
18
- * Feature: Add support for the `redis-client` gem (#314)
19
-
20
- # v0.11.8
21
-
22
- * Feature: Add error_threshold_timeout configuration parameter (#299)
23
-
24
- # v0.11.7
25
-
26
- * Fix: ECONNRESET won't trigger circuit open for redis (#306)
27
-
28
- # v0.11.6
29
-
30
- * Fix: pass disable flag by patching new singleton method (#303)
31
-
32
- # v0.11.5
33
-
34
- * Feature: Add disable flag to http adapter (#301)
35
-
36
- # v0.11.4
37
-
38
- * Fix: Add `extern` to global variable declarations for gcc 10 (#288)
39
-
40
- # v0.11.3
41
-
42
- * Feature: Log last error message on circuit breaker state transition (#285)
43
- * Fix: Update README and docs to resolve common misconception about error_threshold (#283)
44
-
45
- # v0.11.2
46
-
47
- * Fix: Remove `MySQL client is not connected` error from mysql2 adapter
48
-
49
- # v0.11.1
50
-
51
- * Feature: Add `Semian.namespace` to globally prefix all the semaphore names. (#280)
52
-
53
- # v0.11.0
54
-
55
- * Feature: Add `Semian.default_permissions` to globally change the default semaphore permissions. (#279)
56
-
57
- # v0.10.6
58
-
59
- * Fix: Match whitelisted SQL queries when Marginalia is prepended (#276)
60
-
61
- # v0.10.5
62
-
63
- * Fix: Compatibility with GC.compact
64
-
65
- # v0.10.4
66
-
67
- * Fix: Revert the changes in v0.10.3. (#270)
68
-
69
- # v0.10.3
70
-
71
- * Fix: Positional/Keyword arguments deprecations warning for Ruby 2.7 in the grpc adapter. (#269)
72
-
73
- # v0.10.2
74
-
75
- * Fix: Positional/Keyword arguments deprecations warning for Ruby 2.7.
76
-
77
- # v0.10.1
78
-
79
- * Fix: thread safety bug on Ruby 2.7. (#263)
80
-
81
- # v0.10.0
82
-
83
- * Feature: Support half open resource timeout for redis.
84
-
85
- # v0.9.1
86
-
87
- * Fix: Compatibility with MRI 2.3
88
-
89
- # v0.9.0
90
-
91
- * Feature: Add a LRU to garbage collect old resources. (#193)
92
-
93
- # v0.8.9
94
- * Fix: Recursion issue in MySQL2 adapter causing circuits breakers to stay open much longer than they should. (#250)
95
- * Fix: Better handle DNS resolutions exceptions in Redis adapter. (#230)
96
-
97
- # v0.8.8
98
- * Feature: Introduce the GRPC adapter (#200)
99
-
100
- # v0.8.7
101
- * Fix: Instrument success for `acquire_circuit_breaker` (#209)
102
-
103
- # v0.8.6
104
- * Feature: If an error instance responds to `#marks_semian_circuits?` don't mark the circuit if it returns false (#210)
105
-
106
- # v0.8.5
107
- * Fix: Redis adapter using hiredis is resilient to DNS resolution failures (#205)
108
-
109
- # v0.8.4
110
- * Feature: Introduce `half_open_resource_timeout` which changes the resource timeout when the circuit is in a half-open state for the Net::HTTP adapter. (#198)
111
- * Feature: Add the cause of the last error when a circuit opens (#197)
112
- * Fix: Reset successes when transitioning to the half open state (#192)
113
-
114
- # v0.8.1
115
-
116
- * Fix: Expose `half_open?` when the circuit state has not transitioned but will. This allows consumers further up the stack to know if the circuit
117
- is half open.
118
-
119
- # v0.8.0
120
-
121
- * Feature: Introduce `half_open_resource_timeout` which changes the resource timeout when the circuit is in a half-open state (#188)
122
-
123
- # v0.7.8
124
-
125
- * Feature: More informative error messages when initializing Semian with missing
126
- arguments (#182)
127
- * Fix: Redis adapter is now resilient to DNS resolution failures (#184)
128
-
129
- # v0.7.5
130
-
131
- * Fix: Repaired compatibility with dependent Redis library
132
-
133
- # v0.7.4
134
-
135
- * Fix: Protect internal semaphore when adjusting resource count (#164)
136
- * Feature: Use prepend when monkey-patching Net::HTTP. (#157)
137
- * Feature: Include time spend waiting for bulkhead in notification (#154)
138
-
139
- # v0.7.1
140
-
141
- * Feature: Add the behaviour to enable open circuiting on 5xxs conditionally (#149)
142
- * Refactor: Configurable hosts for Semian's development dependencies (#152)
143
-
144
- # v0.7.0
145
-
146
- This change introduced a series of changes to support a new "dynamic quota" ticket
147
- allocation strategy. This code primarily affects bulkheads (protected resources).
148
-
149
- Rather than statically setting a ticket count, workers (in their own process) now register
150
- themselves. By specifying 'quota' instead of 'tickets', the bulkhead threshold will now be
151
- computed dynamically as a ratio of the number of registered workers, eliminating the need to
152
- continuously readjust ticket counts, and supporting environments with non-uniform worker
153
- distribution between machines.
154
-
155
- * Feature: Support quota based allocation strategy (#120)
156
- * Feature: Add ability to manually unregister workers (#130)
157
- * Feature: Add ability to clear resources from adapters and unregister all resources (#134)
158
- * Feature: Allow sysV IPC key to be accessed in ruby (#136)
159
- * Feature: Expose registered worker count to ruby (#137)
160
- * Refactor: Allow registered worker count to be accessed through bulkhead (#138)
161
- * Bug fix: Register all workers (#128)
162
- * Bug fix: Lazy instantiate redis clien on first I/O (#132)
163
- * Bug fix: New mysql error (#131)
164
- * Bug fix: Prevent race conditions when unregistering (#141)
165
- * Refactor/Feature: Break coupling between resource and circuit breaker (#123)
166
- * Refactor: Use generic max_sem_val (#117)
167
- * Refactor: Fix header syntax (#118)
168
- * Refactor: Always acquire semaphore without_gvl (#121)
169
- * Thread-safety for circuit breakers by default (#150)
170
- * Fix bug where calling name on a protected resource without a semaphore would fail (#151)
171
-
172
- # v0.6.2
173
-
174
- * Refactor: Refactor semian ticket management into its own files (#116)
175
- * Refactor: Create sem_meta_lock and sem_meta_unlock (#115)
176
- * Refactor: Refactor semaphore operations (#114)
177
-
178
- # v0.6.1
179
-
180
- * Refactor: Generate a unique semaphore key by including size of semaphore set
181
- * Refactor: Refactor semian\_resource related C functions
182
- * Fix: Don't require sudo for travis (#110)
183
- * Refactor: Refactor semian.c includes and types into header files
184
- * Fix: Use glob instead of git for gemspec file list
185
- * Fix: Fix travis CI for ruby 2.3.0 installing rainbows
186
- * Refactor: Switch to enumerated type for tracking semaphore indices
187
- * Docs: readme: explain co-operation between cbs and bulkheads
188
- * Docs: readme: add section about server limits
189
-
190
- # v0.6.0
191
-
192
- * Feature: Load semian/rails automatically if necessary
193
- * Feature: Implement AR::AbstractAdapter#semian\_resource
194
-
195
- # v0.5.4
196
-
197
- * Fix: Also let "Too many connections" be a first class conn error
198
-
199
- # v0.5.3
200
-
201
- * Fix: mysql: protect pings
202
- * Fix: mysql: match more lost conn queries
203
-
204
- # v0.5.2
205
-
206
- * Fix: Make request\_allowed? thread safe
207
- * Fix: Fix CI connect errors on HTTP requests by using 127.0.0.1 for host
208
-
209
- # v0.5.1
210
-
211
- * Fix: Assert Resource#initialize\_semaphore contract on Resource init
212
- * Fix: Lock on older thin version for pre MRI 2.2 compatibility
213
-
214
- # v0.5.0
215
-
216
- * Fix: Only issue unsupported or disabled semaphores warnings when the first resource is instanciated
217
- * Refactor: Cleanup requires
218
- * Maintenance: Use published version of the toxiproxy gem
219
- * Fix: Fix minitest deprecation warnings
220
- * Maintenance: Update bundler on travis
221
- * Maintenance: Update supported MRI versions on travis
222
-
223
- # v0.4.3
224
-
225
- * Fix: Fix lazy aliasing of Redis#semian\_resource
226
- * Fix: Workaround rubocop parser limitations
227
-
228
- # v0.4.2
229
-
230
- * Fix: Fix for TimeoutError is deprecated in Ruby 2.3.0
231
- * Feature: Include Ruby 2.3 in Travis builds
232
-
233
- # v0.4.1
234
- * Fix: resource: cast float ticket count to fixnum #75
235
-
236
- # v0.4.0
237
-
238
- * Feature: net/http: add adapter for net/http #58
239
- * Refactor: circuit_breaker: split circuit breaker into three data structures to allow for
240
- alternative implementations in the future #62
241
- * Fix: mysql: don't prevent rollbacks on transactions #60
242
- * Fix: core: fix initialization bug when the resource is accessed before the options
243
- are set #65