semian 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/semian.rb CHANGED
@@ -1,19 +1,21 @@
1
- require 'forwardable'
2
- require 'logger'
3
- require 'weakref'
4
- require 'thread'
5
-
6
- require 'semian/version'
7
- require 'semian/instrumentable'
8
- require 'semian/platform'
9
- require 'semian/resource'
10
- require 'semian/circuit_breaker'
11
- require 'semian/protected_resource'
12
- require 'semian/unprotected_resource'
13
- require 'semian/simple_sliding_window'
14
- require 'semian/simple_integer'
15
- require 'semian/simple_state'
16
- require 'semian/lru_hash'
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "logger"
5
+ require "weakref"
6
+ require "thread"
7
+
8
+ require "semian/version"
9
+ require "semian/instrumentable"
10
+ require "semian/platform"
11
+ require "semian/resource"
12
+ require "semian/circuit_breaker"
13
+ require "semian/protected_resource"
14
+ require "semian/unprotected_resource"
15
+ require "semian/simple_sliding_window"
16
+ require "semian/simple_integer"
17
+ require "semian/simple_state"
18
+ require "semian/lru_hash"
17
19
 
18
20
  #
19
21
  # === Overview
@@ -56,9 +58,17 @@ require 'semian/lru_hash'
56
58
  #
57
59
  # ===== Registering a resource
58
60
  #
59
- # Semian.register(:mysql_shard0, tickets: 10, timeout: 0.5, error_threshold: 3, error_timeout: 10, success_threshold: 2)
61
+ # Semian.register(
62
+ # :mysql_shard0,
63
+ # tickets: 10,
64
+ # timeout: 0.5,
65
+ # error_threshold: 3,
66
+ # error_timeout: 10,
67
+ # success_threshold: 2,
68
+ # )
60
69
  #
61
- # This registers a new resource called <code>:mysql_shard0</code> that has 10 tickets and a default timeout of 500 milliseconds.
70
+ # This registers a new resource called <code>:mysql_shard0</code> that has 10 tickets and
71
+ # a default timeout of 500 milliseconds.
62
72
  #
63
73
  # After 3 failures in the span of 10 seconds the circuit will be open.
64
74
  # After an additional 10 seconds it will transition to half-open.
@@ -70,8 +80,8 @@ require 'semian/lru_hash'
70
80
  # # Perform a MySQL query here
71
81
  # end
72
82
  #
73
- # This acquires a ticket for the <code>:mysql_shard0</code> resource. If we use the example above, the ticket count would
74
- # be lowered to 9 when block is executed, then raised to 10 when the block completes.
83
+ # This acquires a ticket for the <code>:mysql_shard0</code> resource. If we use the example above,
84
+ # the ticket count would be lowered to 9 when block is executed, then raised to 10 when the block completes.
75
85
  #
76
86
  # ===== Overriding the default timeout
77
87
  #
@@ -79,7 +89,8 @@ require 'semian/lru_hash'
79
89
  # # Perform a MySQL query here
80
90
  # end
81
91
  #
82
- # This is the same as the previous example, but overrides the timeout from the default value of 500 milliseconds to 1 second.
92
+ # This is the same as the previous example, but overrides the timeout
93
+ # from the default value of 500 milliseconds to 1 second.
83
94
  module Semian
84
95
  extend self
85
96
  extend Instrumentable
@@ -91,12 +102,14 @@ module Semian
91
102
  OpenCircuitError = Class.new(BaseError)
92
103
 
93
104
  attr_accessor :maximum_lru_size, :minimum_lru_time, :default_permissions, :namespace
105
+
94
106
  self.maximum_lru_size = 500
95
107
  self.minimum_lru_time = 300
96
108
  self.default_permissions = 0660
97
109
 
98
110
  def issue_disabled_semaphores_warning
99
111
  return if defined?(@warning_issued)
112
+
100
113
  @warning_issued = true
101
114
  if !sysv_semaphores_supported?
102
115
  logger.info("Semian sysv semaphores are not supported on #{RUBY_PLATFORM} - all operations will no-op")
@@ -119,7 +132,7 @@ module Semian
119
132
 
120
133
  attr_accessor :logger
121
134
 
122
- self.logger = Logger.new(STDERR)
135
+ self.logger = Logger.new($stderr)
123
136
 
124
137
  # Registers a resource.
125
138
  #
@@ -161,7 +174,7 @@ module Semian
161
174
  bulkhead = create_bulkhead(name, **options)
162
175
 
163
176
  if circuit_breaker.nil? && bulkhead.nil?
164
- raise ArgumentError, 'Both bulkhead and circuitbreaker cannot be disabled.'
177
+ raise ArgumentError, "Both bulkhead and circuitbreaker cannot be disabled."
165
178
  end
166
179
 
167
180
  resources[name] = ProtectedResource.new(name, bulkhead, circuit_breaker)
@@ -170,11 +183,10 @@ module Semian
170
183
  def retrieve_or_register(name, **args)
171
184
  # If consumer who retrieved / registered by a Semian::Adapter, keep track
172
185
  # of who the consumer was so that we can clear the resource reference if needed.
173
- if consumer = args.delete(:consumer)
174
- if consumer.class.include?(Semian::Adapter)
175
- consumers[name] ||= []
176
- consumers[name] << WeakRef.new(consumer)
177
- end
186
+ consumer = args.delete(:consumer)
187
+ if consumer&.class&.include?(Semian::Adapter)
188
+ consumers[name] ||= []
189
+ consumers[name] << WeakRef.new(consumer)
178
190
  end
179
191
  self[name] || register(name, **args)
180
192
  end
@@ -185,9 +197,8 @@ module Semian
185
197
  end
186
198
 
187
199
  def destroy(name)
188
- if resource = resources.delete(name)
189
- resource.destroy
190
- end
200
+ resource = resources.delete(name)
201
+ resource&.destroy
191
202
  end
192
203
 
193
204
  def destroy_all_resources
@@ -204,17 +215,16 @@ module Semian
204
215
  # Also clears any semian_resources
205
216
  # in use by any semian adapters if the weak reference is still alive.
206
217
  def unregister(name)
207
- if resource = resources.delete(name)
208
- resource.bulkhead.unregister_worker if resource.bulkhead
218
+ resource = resources.delete(name)
219
+ if resource
220
+ resource.bulkhead&.unregister_worker
209
221
  consumers_for_resource = consumers.delete(name) || []
210
222
  consumers_for_resource.each do |consumer|
211
- begin
212
- if consumer.weakref_alive?
213
- consumer.clear_semian_resource
214
- end
215
- rescue WeakRef::RefError
216
- next
223
+ if consumer.weakref_alive?
224
+ consumer.clear_semian_resource
217
225
  end
226
+ rescue WeakRef::RefError
227
+ next
218
228
  end
219
229
  end
220
230
  end
@@ -243,6 +253,7 @@ module Semian
243
253
 
244
254
  def thread_safe?
245
255
  return @thread_safe if defined?(@thread_safe)
256
+
246
257
  @thread_safe = true
247
258
  end
248
259
 
@@ -255,6 +266,7 @@ module Semian
255
266
  def create_circuit_breaker(name, **options)
256
267
  circuit_breaker = options.fetch(:circuit_breaker, true)
257
268
  return unless circuit_breaker
269
+
258
270
  require_keys!([:success_threshold, :error_threshold, :error_timeout], options)
259
271
 
260
272
  exceptions = options[:exceptions] || []
@@ -277,8 +289,8 @@ module Semian
277
289
  unless options[:thread_safety_disabled].nil?
278
290
  logger.info(
279
291
  "NOTE: thread_safety_disabled will be replaced by a global setting" \
280
- "Semian is thread safe by default. It is possible" \
281
- "to modify the value by using Semian.thread_safe=",
292
+ "Semian is thread safe by default. It is possible" \
293
+ "to modify the value by using Semian.thread_safe=",
282
294
  )
283
295
  end
284
296
 
@@ -292,7 +304,11 @@ module Semian
292
304
 
293
305
  permissions = options[:permissions] || default_permissions
294
306
  timeout = options[:timeout] || 0
295
- Resource.new(name, tickets: options[:tickets], quota: options[:quota], permissions: permissions, timeout: timeout)
307
+ ::Semian::Resource.new(name,
308
+ tickets: options[:tickets],
309
+ quota: options[:quota],
310
+ permissions: permissions,
311
+ timeout: timeout)
296
312
  end
297
313
 
298
314
  def require_keys!(required, options)
@@ -304,13 +320,13 @@ module Semian
304
320
  end
305
321
 
306
322
  if Semian.semaphores_enabled?
307
- require 'semian/semian'
323
+ require "semian/semian"
308
324
  else
309
325
  Semian::MAX_TICKETS = 0
310
326
  end
311
327
 
312
328
  if defined? ActiveSupport
313
- ActiveSupport.on_load :active_record do
314
- require 'semian/rails'
329
+ ActiveSupport.on_load(:active_record) do
330
+ require "semian/rails"
315
331
  end
316
332
  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.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Francis
@@ -10,213 +10,20 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-04-29 00:00:00.000000000 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: rake-compiler
17
- requirement: !ruby/object:Gem::Requirement
18
- requirements:
19
- - - ">="
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- version: '0'
29
- - !ruby/object:Gem::Dependency
30
- name: rake
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- type: :development
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
43
- - !ruby/object:Gem::Dependency
44
- name: timecop
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '0'
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: '0'
57
- - !ruby/object:Gem::Dependency
58
- name: minitest
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: '0'
64
- type: :development
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- version: '0'
71
- - !ruby/object:Gem::Dependency
72
- name: pry-byebug
73
- requirement: !ruby/object:Gem::Requirement
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- type: :development
79
- prerelease: false
80
- version_requirements: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- - !ruby/object:Gem::Dependency
86
- name: mysql2
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: '0'
92
- type: :development
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: '0'
99
- - !ruby/object:Gem::Dependency
100
- name: redis
101
- requirement: !ruby/object:Gem::Requirement
102
- requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- version: '0'
106
- type: :development
107
- prerelease: false
108
- version_requirements: !ruby/object:Gem::Requirement
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: '0'
113
- - !ruby/object:Gem::Dependency
114
- name: redis-client
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: 0.2.0
120
- type: :development
121
- prerelease: false
122
- version_requirements: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- version: 0.2.0
127
- - !ruby/object:Gem::Dependency
128
- name: webrick
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - ">="
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: '0'
141
- - !ruby/object:Gem::Dependency
142
- name: toxiproxy
143
- requirement: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - "~>"
146
- - !ruby/object:Gem::Version
147
- version: 1.0.0
148
- type: :development
149
- prerelease: false
150
- version_requirements: !ruby/object:Gem::Requirement
151
- requirements:
152
- - - "~>"
153
- - !ruby/object:Gem::Version
154
- version: 1.0.0
155
- - !ruby/object:Gem::Dependency
156
- name: grpc
157
- requirement: !ruby/object:Gem::Requirement
158
- requirements:
159
- - - ">="
160
- - !ruby/object:Gem::Version
161
- version: '0'
162
- type: :development
163
- prerelease: false
164
- version_requirements: !ruby/object:Gem::Requirement
165
- requirements:
166
- - - ">="
167
- - !ruby/object:Gem::Version
168
- version: '0'
169
- - !ruby/object:Gem::Dependency
170
- name: mocha
171
- requirement: !ruby/object:Gem::Requirement
172
- requirements:
173
- - - ">="
174
- - !ruby/object:Gem::Version
175
- version: '0'
176
- type: :development
177
- prerelease: false
178
- version_requirements: !ruby/object:Gem::Requirement
179
- requirements:
180
- - - ">="
181
- - !ruby/object:Gem::Version
182
- version: '0'
183
- - !ruby/object:Gem::Dependency
184
- name: memory_profiler
185
- requirement: !ruby/object:Gem::Requirement
186
- requirements:
187
- - - ">="
188
- - !ruby/object:Gem::Version
189
- version: '0'
190
- type: :development
191
- prerelease: false
192
- version_requirements: !ruby/object:Gem::Requirement
193
- requirements:
194
- - - ">="
195
- - !ruby/object:Gem::Version
196
- version: '0'
197
- - !ruby/object:Gem::Dependency
198
- name: benchmark-memory
199
- requirement: !ruby/object:Gem::Requirement
200
- requirements:
201
- - - ">="
202
- - !ruby/object:Gem::Version
203
- version: '0'
204
- type: :development
205
- prerelease: false
206
- version_requirements: !ruby/object:Gem::Requirement
207
- requirements:
208
- - - ">="
209
- - !ruby/object:Gem::Version
210
- version: '0'
13
+ date: 2022-06-27 00:00:00.000000000 Z
14
+ dependencies: []
211
15
  description: |2
212
16
  A Ruby C extention that is used to control access to shared resources
213
17
  across process boundaries with SysV semaphores.
214
- email: scott.francis@shopify.com
18
+ email: opensource@shopify.com
215
19
  executables: []
216
20
  extensions:
217
21
  - ext/semian/extconf.rb
218
22
  extra_rdoc_files: []
219
23
  files:
24
+ - CHANGELOG.md
25
+ - LICENSE.md
26
+ - README.md
220
27
  - ext/semian/extconf.rb
221
28
  - ext/semian/resource.c
222
29
  - ext/semian/resource.h
@@ -251,6 +58,9 @@ licenses:
251
58
  - MIT
252
59
  metadata:
253
60
  allowed_push_host: https://rubygems.org
61
+ bug_tracker_uri: https://github.com/Shopify/semian/issues
62
+ changelog_uri: https://github.com/Shopify/semian/blob/master/CHANGELOG.md
63
+ source_code_uri: https://github.com/Shopify/semian
254
64
  post_install_message:
255
65
  rdoc_options: []
256
66
  require_paths:
@@ -266,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
76
  - !ruby/object:Gem::Version
267
77
  version: '0'
268
78
  requirements: []
269
- rubygems_version: 3.2.20
79
+ rubygems_version: 3.3.3
270
80
  signing_key:
271
81
  specification_version: 4
272
82
  summary: Bulkheading for Ruby with SysV semaphores