semian 0.11.9 → 0.13.1

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.
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
- class Resource #:nodoc:
3
- attr_reader :tickets, :name
4
+ class Resource # :nodoc:
5
+ attr_reader :name
4
6
 
5
7
  class << Semian::Resource
6
8
  # Ensure that there can only be one resource of a given type
@@ -55,7 +57,7 @@ module Semian
55
57
  end
56
58
 
57
59
  def key
58
- '0x00000000'
60
+ "0x00000000"
59
61
  end
60
62
 
61
63
  def in_use?
@@ -1,8 +1,10 @@
1
- require 'thread'
1
+ # frozen_string_literal: true
2
+
3
+ require "thread"
2
4
 
3
5
  module Semian
4
6
  module Simple
5
- class Integer #:nodoc:
7
+ class Integer # :nodoc:
6
8
  attr_accessor :value
7
9
 
8
10
  def initialize
@@ -1,11 +1,13 @@
1
- require 'thread'
1
+ # frozen_string_literal: true
2
+
3
+ require "thread"
2
4
 
3
5
  module Semian
4
6
  module Simple
5
- class SlidingWindow #:nodoc:
7
+ class SlidingWindow # :nodoc:
6
8
  extend Forwardable
7
9
 
8
- def_delegators :@window, :size, :last
10
+ def_delegators :@window, :size, :last, :empty?
9
11
  attr_reader :max_size
10
12
 
11
13
  # A sliding window is a structure that stores the most @max_size recent timestamps
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
4
  module Simple
3
- class State #:nodoc:
5
+ class State # :nodoc:
4
6
  def initialize
5
7
  reset
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
4
  # This class acts as a replacement for `ProtectedResource` when
3
5
  # the semian configuration of an `Adapter` is missing or explicitly disabled
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
- VERSION = '0.11.9'
4
+ VERSION = "0.13.1"
3
5
  end
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,13 @@ 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
202
+ end
203
+
204
+ def destroy_all_resources
205
+ resources.values.each(&:destroy)
206
+ resources.clear
191
207
  end
192
208
 
193
209
  # Unregister will not destroy the semian resource, but it will
@@ -199,17 +215,16 @@ module Semian
199
215
  # Also clears any semian_resources
200
216
  # in use by any semian adapters if the weak reference is still alive.
201
217
  def unregister(name)
202
- if resource = resources.delete(name)
203
- resource.bulkhead.unregister_worker if resource.bulkhead
218
+ resource = resources.delete(name)
219
+ if resource
220
+ resource.bulkhead&.unregister_worker
204
221
  consumers_for_resource = consumers.delete(name) || []
205
222
  consumers_for_resource.each do |consumer|
206
- begin
207
- if consumer.weakref_alive?
208
- consumer.clear_semian_resource
209
- end
210
- rescue WeakRef::RefError
211
- next
223
+ if consumer.weakref_alive?
224
+ consumer.clear_semian_resource
212
225
  end
226
+ rescue WeakRef::RefError
227
+ next
213
228
  end
214
229
  end
215
230
  end
@@ -238,6 +253,7 @@ module Semian
238
253
 
239
254
  def thread_safe?
240
255
  return @thread_safe if defined?(@thread_safe)
256
+
241
257
  @thread_safe = true
242
258
  end
243
259
 
@@ -250,6 +266,7 @@ module Semian
250
266
  def create_circuit_breaker(name, **options)
251
267
  circuit_breaker = options.fetch(:circuit_breaker, true)
252
268
  return unless circuit_breaker
269
+
253
270
  require_keys!([:success_threshold, :error_threshold, :error_timeout], options)
254
271
 
255
272
  exceptions = options[:exceptions] || []
@@ -272,8 +289,8 @@ module Semian
272
289
  unless options[:thread_safety_disabled].nil?
273
290
  logger.info(
274
291
  "NOTE: thread_safety_disabled will be replaced by a global setting" \
275
- "Semian is thread safe by default. It is possible" \
276
- "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=",
277
294
  )
278
295
  end
279
296
 
@@ -287,7 +304,11 @@ module Semian
287
304
 
288
305
  permissions = options[:permissions] || default_permissions
289
306
  timeout = options[:timeout] || 0
290
- 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)
291
312
  end
292
313
 
293
314
  def require_keys!(required, options)
@@ -299,13 +320,13 @@ module Semian
299
320
  end
300
321
 
301
322
  if Semian.semaphores_enabled?
302
- require 'semian/semian'
323
+ require "semian/semian"
303
324
  else
304
325
  Semian::MAX_TICKETS = 0
305
326
  end
306
327
 
307
328
  if defined? ActiveSupport
308
- ActiveSupport.on_load :active_record do
309
- require 'semian/rails'
329
+ ActiveSupport.on_load(:active_record) do
330
+ require "semian/rails"
310
331
  end
311
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.11.9
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Francis
@@ -10,199 +10,20 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-03-01 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: webrick
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: '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'
127
- - !ruby/object:Gem::Dependency
128
- name: toxiproxy
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - "~>"
132
- - !ruby/object:Gem::Version
133
- version: 1.0.0
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - "~>"
139
- - !ruby/object:Gem::Version
140
- version: 1.0.0
141
- - !ruby/object:Gem::Dependency
142
- name: grpc
143
- requirement: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - ">="
146
- - !ruby/object:Gem::Version
147
- version: '0'
148
- type: :development
149
- prerelease: false
150
- version_requirements: !ruby/object:Gem::Requirement
151
- requirements:
152
- - - ">="
153
- - !ruby/object:Gem::Version
154
- version: '0'
155
- - !ruby/object:Gem::Dependency
156
- name: mocha
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: memory_profiler
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: benchmark-memory
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'
13
+ date: 2022-08-16 00:00:00.000000000 Z
14
+ dependencies: []
197
15
  description: |2
198
16
  A Ruby C extention that is used to control access to shared resources
199
17
  across process boundaries with SysV semaphores.
200
- email: scott.francis@shopify.com
18
+ email: opensource@shopify.com
201
19
  executables: []
202
20
  extensions:
203
21
  - ext/semian/extconf.rb
204
22
  extra_rdoc_files: []
205
23
  files:
24
+ - CHANGELOG.md
25
+ - LICENSE.md
26
+ - README.md
206
27
  - ext/semian/extconf.rb
207
28
  - ext/semian/resource.c
208
29
  - ext/semian/resource.h
@@ -225,6 +46,7 @@ files:
225
46
  - lib/semian/protected_resource.rb
226
47
  - lib/semian/rails.rb
227
48
  - lib/semian/redis.rb
49
+ - lib/semian/redis_client.rb
228
50
  - lib/semian/resource.rb
229
51
  - lib/semian/simple_integer.rb
230
52
  - lib/semian/simple_sliding_window.rb
@@ -236,6 +58,9 @@ licenses:
236
58
  - MIT
237
59
  metadata:
238
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
239
64
  post_install_message:
240
65
  rdoc_options: []
241
66
  require_paths:
@@ -251,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
76
  - !ruby/object:Gem::Version
252
77
  version: '0'
253
78
  requirements: []
254
- rubygems_version: 3.2.20
79
+ rubygems_version: 3.3.3
255
80
  signing_key:
256
81
  specification_version: 4
257
82
  summary: Bulkheading for Ruby with SysV semaphores