semian 0.13.1 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78f1c9a991cd16ae1da354babc364364cf1aac75f07b1fb3d694f75c94f33411
4
- data.tar.gz: 51585c1ccf8aa6f02c45b1da9da58753e91ce45a92f99c3880c5fb46c6b82aa5
3
+ metadata.gz: a7b62deafc4e8de524ae8aec32a17e3a1065d70206a5ead2ef6298da3b1c38ed
4
+ data.tar.gz: 3f6b18aa473410c0ad8d476931417fa69595328fd748a2edb75a333709b901cd
5
5
  SHA512:
6
- metadata.gz: 6b8f18a662e05dbedb5dec96ed1c740a40d1a644a098d01e0b82440aa6a877b9f3d67611cb38293699fb2a19bd4cf7aa9b0fa02c03babaa9063856d8cfabcd25
7
- data.tar.gz: 32546169e572cacd1cb85b63dd8b01164ba4eb15858394c9163d9de3d2ffdb258418f2dac7ebcb51e7ad8bd6ff592973c81f7758e8085a855b31011ce13c47e2
6
+ metadata.gz: c064829103c0c4f8915f6c072d43872b9a6dc011987e6a81f5efa8931052cc84b758df9bc4dd74f4f90c0501accbaa3e09ca3212af6a8a3e7056ce1f28a28e22
7
+ data.tar.gz: 124128fc2a5791317ea5a04b32c84e9b3cd394e843a74599c5ecf044cc6c89eec656384675b88e9fd73e95038dfb1e8a35b8e613034114e264b59e754a8eec0c
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
data/lib/semian/rails.rb CHANGED
@@ -2,14 +2,35 @@
2
2
 
3
3
  require "active_record/connection_adapters/abstract_adapter"
4
4
 
5
- module ActiveRecord
6
- module ConnectionAdapters
7
- class AbstractAdapter
8
- def semian_resource
9
- # support for https://github.com/rails/rails/commit/d86fd6415c0dfce6fadb77e74696cf728e5eb76b
10
- connection = instance_variable_defined?(:@raw_connection) ? @raw_connection : @connection
11
- connection.semian_resource
5
+ module Semian
6
+ module Rails
7
+ def semian_resource
8
+ @semian_resource ||= client_connection.semian_resource
9
+ end
10
+
11
+ def reconnect
12
+ @semian_resource = nil
13
+ super
14
+ end
15
+
16
+ private
17
+
18
+ # client_connection is an instance of a Mysql2::Client
19
+ #
20
+ # The conditionals here support multiple Rails versions.
21
+ # - valid_raw_connection is for 7.1.x and above
22
+ # - @raw_connection is for 7.0.x
23
+ # - @connection is for versions below 6.1.x and below
24
+ def client_connection
25
+ if respond_to?(:valid_raw_connection)
26
+ valid_raw_connection
27
+ elsif instance_variable_defined?(:@raw_connection)
28
+ @raw_connection
29
+ else
30
+ @connection
12
31
  end
13
32
  end
14
33
  end
15
34
  end
35
+
36
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Semian::Rails)
@@ -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.1"
4
+ VERSION = "0.14.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.1
4
+ version: 0.14.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-16 00:00:00.000000000 Z
13
+ date: 2022-09-07 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,239 +0,0 @@
1
- # Unreleased
2
-
3
- # v0.13.1
4
-
5
- * Fix: Raise `Redis::OutOfMemoryError` for messages that match `OOM command not allowed when used memory > 'maxmemory'` rather than checking `start_with?("OOM ")`. (#367)
6
-
7
- # v0.13.0
8
-
9
- * Refactor: Replace Time.now with CLOCK_MONOTONIC in MockServer (#318)
10
- * Fix: Circuit not open for GRPC::ActiveCall::Operation failures (#348)
11
-
12
- # v0.12.0
13
-
14
- * Feature: Add support for the `redis-client` gem (#314)
15
-
16
- # v0.11.8
17
-
18
- * Feature: Add error_threshold_timeout configuration parameter (#299)
19
-
20
- # v0.11.7
21
-
22
- * Fix: ECONNRESET won't trigger circuit open for redis (#306)
23
-
24
- # v0.11.6
25
-
26
- * Fix: pass disable flag by patching new singleton method (#303)
27
-
28
- # v0.11.5
29
-
30
- * Feature: Add disable flag to http adapter (#301)
31
-
32
- # v0.11.4
33
-
34
- * Fix: Add `extern` to global variable declarations for gcc 10 (#288)
35
-
36
- # v0.11.3
37
-
38
- * Feature: Log last error message on circuit breaker state transition (#285)
39
- * Fix: Update README and docs to resolve common misconception about error_threshold (#283)
40
-
41
- # v0.11.2
42
-
43
- * Fix: Remove `MySQL client is not connected` error from mysql2 adapter
44
-
45
- # v0.11.1
46
-
47
- * Feature: Add `Semian.namespace` to globally prefix all the semaphore names. (#280)
48
-
49
- # v0.11.0
50
-
51
- * Feature: Add `Semian.default_permissions` to globally change the default semaphore permissions. (#279)
52
-
53
- # v0.10.6
54
-
55
- * Fix: Match whitelisted SQL queries when Marginalia is prepended (#276)
56
-
57
- # v0.10.5
58
-
59
- * Fix: Compatibility with GC.compact
60
-
61
- # v0.10.4
62
-
63
- * Fix: Revert the changes in v0.10.3. (#270)
64
-
65
- # v0.10.3
66
-
67
- * Fix: Positional/Keyword arguments deprecations warning for Ruby 2.7 in the grpc adapter. (#269)
68
-
69
- # v0.10.2
70
-
71
- * Fix: Positional/Keyword arguments deprecations warning for Ruby 2.7.
72
-
73
- # v0.10.1
74
-
75
- * Fix: thread safety bug on Ruby 2.7. (#263)
76
-
77
- # v0.10.0
78
-
79
- * Feature: Support half open resource timeout for redis.
80
-
81
- # v0.9.1
82
-
83
- * Fix: Compatibility with MRI 2.3
84
-
85
- # v0.9.0
86
-
87
- * Feature: Add a LRU to garbage collect old resources. (#193)
88
-
89
- # v0.8.9
90
- * Fix: Recursion issue in MySQL2 adapter causing circuits breakers to stay open much longer than they should. (#250)
91
- * Fix: Better handle DNS resolutions exceptions in Redis adapter. (#230)
92
-
93
- # v0.8.8
94
- * Feature: Introduce the GRPC adapter (#200)
95
-
96
- # v0.8.7
97
- * Fix: Instrument success for `acquire_circuit_breaker` (#209)
98
-
99
- # v0.8.6
100
- * Feature: If an error instance responds to `#marks_semian_circuits?` don't mark the circuit if it returns false (#210)
101
-
102
- # v0.8.5
103
- * Fix: Redis adapter using hiredis is resilient to DNS resolution failures (#205)
104
-
105
- # v0.8.4
106
- * 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)
107
- * Feature: Add the cause of the last error when a circuit opens (#197)
108
- * Fix: Reset successes when transitioning to the half open state (#192)
109
-
110
- # v0.8.1
111
-
112
- * 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
113
- is half open.
114
-
115
- # v0.8.0
116
-
117
- * Feature: Introduce `half_open_resource_timeout` which changes the resource timeout when the circuit is in a half-open state (#188)
118
-
119
- # v0.7.8
120
-
121
- * Feature: More informative error messages when initializing Semian with missing
122
- arguments (#182)
123
- * Fix: Redis adapter is now resilient to DNS resolution failures (#184)
124
-
125
- # v0.7.5
126
-
127
- * Fix: Repaired compatibility with dependent Redis library
128
-
129
- # v0.7.4
130
-
131
- * Fix: Protect internal semaphore when adjusting resource count (#164)
132
- * Feature: Use prepend when monkey-patching Net::HTTP. (#157)
133
- * Feature: Include time spend waiting for bulkhead in notification (#154)
134
-
135
- # v0.7.1
136
-
137
- * Feature: Add the behaviour to enable open circuiting on 5xxs conditionally (#149)
138
- * Refactor: Configurable hosts for Semian's development dependencies (#152)
139
-
140
- # v0.7.0
141
-
142
- This change introduced a series of changes to support a new "dynamic quota" ticket
143
- allocation strategy. This code primarily affects bulkheads (protected resources).
144
-
145
- Rather than statically setting a ticket count, workers (in their own process) now register
146
- themselves. By specifying 'quota' instead of 'tickets', the bulkhead threshold will now be
147
- computed dynamically as a ratio of the number of registered workers, eliminating the need to
148
- continuously readjust ticket counts, and supporting environments with non-uniform worker
149
- distribution between machines.
150
-
151
- * Feature: Support quota based allocation strategy (#120)
152
- * Feature: Add ability to manually unregister workers (#130)
153
- * Feature: Add ability to clear resources from adapters and unregister all resources (#134)
154
- * Feature: Allow sysV IPC key to be accessed in ruby (#136)
155
- * Feature: Expose registered worker count to ruby (#137)
156
- * Refactor: Allow registered worker count to be accessed through bulkhead (#138)
157
- * Bug fix: Register all workers (#128)
158
- * Bug fix: Lazy instantiate redis clien on first I/O (#132)
159
- * Bug fix: New mysql error (#131)
160
- * Bug fix: Prevent race conditions when unregistering (#141)
161
- * Refactor/Feature: Break coupling between resource and circuit breaker (#123)
162
- * Refactor: Use generic max_sem_val (#117)
163
- * Refactor: Fix header syntax (#118)
164
- * Refactor: Always acquire semaphore without_gvl (#121)
165
- * Thread-safety for circuit breakers by default (#150)
166
- * Fix bug where calling name on a protected resource without a semaphore would fail (#151)
167
-
168
- # v0.6.2
169
-
170
- * Refactor: Refactor semian ticket management into its own files (#116)
171
- * Refactor: Create sem_meta_lock and sem_meta_unlock (#115)
172
- * Refactor: Refactor semaphore operations (#114)
173
-
174
- # v0.6.1
175
-
176
- * Refactor: Generate a unique semaphore key by including size of semaphore set
177
- * Refactor: Refactor semian\_resource related C functions
178
- * Fix: Don't require sudo for travis (#110)
179
- * Refactor: Refactor semian.c includes and types into header files
180
- * Fix: Use glob instead of git for gemspec file list
181
- * Fix: Fix travis CI for ruby 2.3.0 installing rainbows
182
- * Refactor: Switch to enumerated type for tracking semaphore indices
183
- * Docs: readme: explain co-operation between cbs and bulkheads
184
- * Docs: readme: add section about server limits
185
-
186
- # v0.6.0
187
-
188
- * Feature: Load semian/rails automatically if necessary
189
- * Feature: Implement AR::AbstractAdapter#semian\_resource
190
-
191
- # v0.5.4
192
-
193
- * Fix: Also let "Too many connections" be a first class conn error
194
-
195
- # v0.5.3
196
-
197
- * Fix: mysql: protect pings
198
- * Fix: mysql: match more lost conn queries
199
-
200
- # v0.5.2
201
-
202
- * Fix: Make request\_allowed? thread safe
203
- * Fix: Fix CI connect errors on HTTP requests by using 127.0.0.1 for host
204
-
205
- # v0.5.1
206
-
207
- * Fix: Assert Resource#initialize\_semaphore contract on Resource init
208
- * Fix: Lock on older thin version for pre MRI 2.2 compatibility
209
-
210
- # v0.5.0
211
-
212
- * Fix: Only issue unsupported or disabled semaphores warnings when the first resource is instanciated
213
- * Refactor: Cleanup requires
214
- * Maintenance: Use published version of the toxiproxy gem
215
- * Fix: Fix minitest deprecation warnings
216
- * Maintenance: Update bundler on travis
217
- * Maintenance: Update supported MRI versions on travis
218
-
219
- # v0.4.3
220
-
221
- * Fix: Fix lazy aliasing of Redis#semian\_resource
222
- * Fix: Workaround rubocop parser limitations
223
-
224
- # v0.4.2
225
-
226
- * Fix: Fix for TimeoutError is deprecated in Ruby 2.3.0
227
- * Feature: Include Ruby 2.3 in Travis builds
228
-
229
- # v0.4.1
230
- * Fix: resource: cast float ticket count to fixnum #75
231
-
232
- # v0.4.0
233
-
234
- * Feature: net/http: add adapter for net/http #58
235
- * Refactor: circuit_breaker: split circuit breaker into three data structures to allow for
236
- alternative implementations in the future #62
237
- * Fix: mysql: don't prevent rollbacks on transactions #60
238
- * Fix: core: fix initialization bug when the resource is accessed before the options
239
- are set #65