semian 0.12.0 → 0.13.2

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,33 +1,35 @@
1
- $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
1
+ # frozen_string_literal: true
2
2
 
3
- require 'semian/platform'
3
+ $LOAD_PATH.unshift(File.expand_path("../../../lib", __FILE__))
4
+
5
+ require "semian/platform"
4
6
 
5
7
  unless Semian.sysv_semaphores_supported?
6
- File.write "Makefile", <<MAKEFILE
7
- all:
8
- clean:
9
- install:
10
- MAKEFILE
8
+ File.write("Makefile", <<~MAKEFILE)
9
+ all:
10
+ clean:
11
+ install:
12
+ MAKEFILE
11
13
  exit
12
14
  end
13
15
 
14
- require 'mkmf'
16
+ require "mkmf"
15
17
 
16
- abort 'openssl is missing. please install openssl.' unless find_header('openssl/sha.h')
17
- abort 'openssl is missing. please install openssl.' unless find_library('crypto', 'SHA1')
18
+ abort "openssl is missing. please install openssl." unless find_header("openssl/sha.h")
19
+ abort "openssl is missing. please install openssl." unless find_library("crypto", "SHA1")
18
20
 
19
- have_header 'sys/ipc.h'
20
- have_header 'sys/sem.h'
21
- have_header 'sys/types.h'
21
+ have_header "sys/ipc.h"
22
+ have_header "sys/sem.h"
23
+ have_header "sys/types.h"
22
24
 
23
- have_func 'rb_thread_blocking_region'
24
- have_func 'rb_thread_call_without_gvl'
25
+ have_func "rb_thread_blocking_region"
26
+ have_func "rb_thread_call_without_gvl"
25
27
 
26
28
  $CFLAGS = "-D_GNU_SOURCE -Werror -Wall "
27
- if ENV.key?('DEBUG')
28
- $CFLAGS << "-O0 -g -DDEBUG"
29
+ $CFLAGS += if ENV.key?("DEBUG")
30
+ "-O0 -g -DDEBUG"
29
31
  else
30
- $CFLAGS << "-O3"
32
+ "-O3"
31
33
  end
32
34
 
33
- create_makefile('semian/semian')
35
+ create_makefile("semian/semian")
@@ -1,9 +1,11 @@
1
- require 'semian'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian"
2
4
 
3
5
  module Semian
4
6
  module Adapter
5
7
  def semian_identifier
6
- raise NotImplementedError.new("Semian adapters must implement a `semian_identifier` method")
8
+ raise NotImplementedError, "Semian adapters must implement a `semian_identifier` method"
7
9
  end
8
10
 
9
11
  def semian_resource
@@ -31,6 +33,7 @@ module Semian
31
33
 
32
34
  def acquire_semian_resource(scope:, adapter:, &block)
33
35
  return yield if resource_already_acquired?
36
+
34
37
  semian_resource.acquire(scope: scope, adapter: adapter, resource: self) do
35
38
  mark_resource_as_acquired(&block)
36
39
  end
@@ -48,16 +51,17 @@ module Semian
48
51
 
49
52
  def semian_options
50
53
  return @semian_options if defined? @semian_options
54
+
51
55
  options = raw_semian_options
52
56
  @semian_options = options && options.map { |k, v| [k.to_sym, v] }.to_h
53
57
  end
54
58
 
55
59
  def raw_semian_options
56
- raise NotImplementedError.new("Semian adapters must implement a `raw_semian_options` method")
60
+ raise NotImplementedError, "Semian adapters must implement a `raw_semian_options` method"
57
61
  end
58
62
 
59
63
  def resource_exceptions
60
- raise NotImplementedError.new("Semian adapters must implement a `resource_exceptions` method")
64
+ raise NotImplementedError, "Semian adapters must implement a `resource_exceptions` method"
61
65
  end
62
66
 
63
67
  def resource_already_acquired?
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
- class CircuitBreaker #:nodoc:
4
+ class CircuitBreaker # :nodoc:
3
5
  extend Forwardable
4
6
 
5
7
  def_delegators :@state, :closed?, :open?, :half_open?
@@ -7,7 +9,9 @@ module Semian
7
9
  attr_reader :name, :half_open_resource_timeout, :error_timeout, :state, :last_error
8
10
 
9
11
  def initialize(name, exceptions:, success_threshold:, error_threshold:,
10
- error_timeout:, implementation:, half_open_resource_timeout: nil, error_threshold_timeout: nil)
12
+ error_timeout:, implementation:, half_open_resource_timeout: nil,
13
+ error_threshold_timeout: nil)
14
+
11
15
  @name = name.to_sym
12
16
  @success_count_threshold = success_threshold
13
17
  @error_count_threshold = error_threshold
@@ -25,6 +29,7 @@ module Semian
25
29
 
26
30
  def acquire(resource = nil, &block)
27
31
  return yield if disabled?
32
+
28
33
  transition_to_half_open if transition_to_half_open?
29
34
 
30
35
  raise OpenCircuitError unless request_allowed?
@@ -63,6 +68,7 @@ module Semian
63
68
 
64
69
  def mark_success
65
70
  return unless half_open?
71
+
66
72
  @successes.increment
67
73
  transition_to_close if success_threshold_reached?
68
74
  end
@@ -80,8 +86,7 @@ module Semian
80
86
  end
81
87
 
82
88
  def in_use?
83
- return false if error_timeout_expired?
84
- @errors.size > 0
89
+ !error_timeout_expired? && !@errors.empty?
85
90
  end
86
91
 
87
92
  private
@@ -117,6 +122,7 @@ module Semian
117
122
  def error_timeout_expired?
118
123
  last_error_time = @errors.last
119
124
  return false unless last_error_time
125
+
120
126
  Time.at(last_error_time) + @error_timeout < Time.now
121
127
  end
122
128
 
@@ -133,12 +139,12 @@ module Semian
133
139
  return if @state.nil? || new_state == @state.value
134
140
 
135
141
  str = "[#{self.class.name}] State transition from #{@state.value} to #{new_state}."
136
- str << " success_count=#{@successes.value} error_count=#{@errors.size}"
137
- str << " success_count_threshold=#{@success_count_threshold} error_count_threshold=#{@error_count_threshold}"
138
- str << " error_timeout=#{@error_timeout} error_last_at=\"#{@errors.last}\""
139
- str << " name=\"#{@name}\""
142
+ str += " success_count=#{@successes.value} error_count=#{@errors.size}"
143
+ str += " success_count_threshold=#{@success_count_threshold} error_count_threshold=#{@error_count_threshold}"
144
+ str += " error_timeout=#{@error_timeout} error_last_at=\"#{@errors.last}\""
145
+ str += " name=\"#{@name}\""
140
146
  if new_state == :open && @last_error
141
- str << " last_error_message=#{@last_error.message.inspect}"
147
+ str += " last_error_message=#{@last_error.message.inspect}"
142
148
  end
143
149
 
144
150
  Semian.logger.info(str)
@@ -149,7 +155,7 @@ module Semian
149
155
  end
150
156
 
151
157
  def disabled?
152
- ENV['SEMIAN_CIRCUIT_BREAKER_DISABLED'] || ENV['SEMIAN_DISABLED']
158
+ ENV["SEMIAN_CIRCUIT_BREAKER_DISABLED"] || ENV["SEMIAN_DISABLED"]
153
159
  end
154
160
 
155
161
  def maybe_with_half_open_resource_timeout(resource, &block)
data/lib/semian/grpc.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'semian/adapter'
2
- require 'grpc'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/adapter"
4
+ require "grpc"
3
5
 
4
6
  module GRPC
5
7
  GRPC::Unavailable.include(::Semian::AdapterError)
@@ -22,7 +24,6 @@ end
22
24
 
23
25
  module Semian
24
26
  module GRPC
25
- attr_reader :raw_semian_options
26
27
  include Semian::Adapter
27
28
 
28
29
  ResourceBusyError = ::GRPC::ResourceBusyError
@@ -40,6 +41,7 @@ module Semian
40
41
 
41
42
  def semian_configuration=(configuration)
42
43
  raise Semian::GRPC::SemianConfigurationChangedError unless @semian_configuration.nil?
44
+
43
45
  @semian_configuration = configuration
44
46
  end
45
47
 
@@ -52,10 +54,10 @@ module Semian
52
54
  @raw_semian_options ||= begin
53
55
  # If the host is empty, it's possible that the adapter was initialized
54
56
  # with the channel. Therefore, we look into the channel to find the host
55
- if @host.empty?
56
- host = @ch.target
57
+ host = if @host.empty?
58
+ @ch.target
57
59
  else
58
- host = @host
60
+ @host
59
61
  end
60
62
  @raw_semian_options = Semian::GRPC.retrieve_semian_configuration(host)
61
63
  @raw_semian_options = @raw_semian_options.dup unless @raw_semian_options.nil?
@@ -81,22 +83,42 @@ module Semian
81
83
 
82
84
  def request_response(*, **)
83
85
  return super if disabled?
84
- acquire_semian_resource(adapter: :grpc, scope: :request_response) { super }
86
+
87
+ acquire_semian_resource_grpc(scope: :request_response) { super }
85
88
  end
86
89
 
87
90
  def client_streamer(*, **)
88
91
  return super if disabled?
89
- acquire_semian_resource(adapter: :grpc, scope: :client_streamer) { super }
92
+
93
+ acquire_semian_resource_grpc(scope: :client_streamer) { super }
90
94
  end
91
95
 
92
96
  def server_streamer(*, **)
93
97
  return super if disabled?
94
- acquire_semian_resource(adapter: :grpc, scope: :server_streamer) { super }
98
+
99
+ acquire_semian_resource_grpc(scope: :server_streamer) { super }
95
100
  end
96
101
 
97
102
  def bidi_streamer(*, **)
98
103
  return super if disabled?
99
- acquire_semian_resource(adapter: :grpc, scope: :bidi_streamer) { super }
104
+
105
+ acquire_semian_resource_grpc(scope: :bidi_streamer) { super }
106
+ end
107
+
108
+ def acquire_semian_resource_grpc(scope:)
109
+ acquire_semian_resource(adapter: :grpc, scope: scope) do
110
+ result = yield
111
+ handle_operation(result, scope) if result.is_a?(::GRPC::ActiveCall::Operation)
112
+ result
113
+ end
114
+ end
115
+
116
+ def handle_operation(operation, scope)
117
+ execute = operation.singleton_method(:execute)
118
+ operation.instance_variable_set(:@semian, self)
119
+ operation.define_singleton_method(:execute) do
120
+ @semian.send(:acquire_semian_resource, **{ adapter: :grpc, scope: scope }) { execute.call }
121
+ end
100
122
  end
101
123
  end
102
124
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
4
  module Instrumentable
3
5
  def subscribe(name = rand, &block)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class LRUHash
2
4
  # This LRU (Least Recently Used) hash will allow
3
5
  # the cleaning of resources as time goes on.
@@ -120,10 +122,10 @@ class LRUHash
120
122
 
121
123
  def clear_unused_resources
122
124
  payload = {
123
- size: @table.size,
124
- examined: 0,
125
- cleared: 0,
126
- elapsed: nil,
125
+ size: @table.size,
126
+ examined: 0,
127
+ cleared: 0,
128
+ elapsed: nil,
127
129
  }
128
130
  timer_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
129
131
 
@@ -155,20 +157,19 @@ class LRUHash
155
157
  end
156
158
  end
157
159
 
158
- EXCEPTION_NEVER = {Exception => :never}.freeze
159
- EXCEPTION_IMMEDIATE = {Exception => :immediate}.freeze
160
+ EXCEPTION_NEVER = { Exception => :never }.freeze
161
+ EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze
160
162
  private_constant :EXCEPTION_NEVER
161
163
  private_constant :EXCEPTION_IMMEDIATE
162
164
 
163
- def try_synchronize
165
+ def try_synchronize(&block)
164
166
  Thread.handle_interrupt(EXCEPTION_NEVER) do
165
- begin
166
- return false unless @lock.try_lock
167
- Thread.handle_interrupt(EXCEPTION_IMMEDIATE) { yield }
168
- true
169
- ensure
170
- @lock.unlock if @lock.owned?
171
- end
167
+ return false unless @lock.try_lock
168
+
169
+ Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
170
+ true
171
+ ensure
172
+ @lock.unlock if @lock.owned?
172
173
  end
173
174
  end
174
175
  end
data/lib/semian/mysql2.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'semian/adapter'
2
- require 'mysql2'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/adapter"
4
+ require "mysql2"
3
5
 
4
6
  module Mysql2
5
7
  Mysql2::Error.include(::Semian::AdapterError)
@@ -32,13 +34,13 @@ module Semian
32
34
  CircuitOpenError = ::Mysql2::CircuitOpenError
33
35
  PingFailure = Class.new(::Mysql2::Error)
34
36
 
35
- DEFAULT_HOST = 'localhost'
37
+ DEFAULT_HOST = "localhost"
36
38
  DEFAULT_PORT = 3306
37
39
 
38
40
  QUERY_WHITELIST = Regexp.union(
39
- /\A(?:\/\*.*?\*\/)?\s*ROLLBACK/i,
40
- /\A(?:\/\*.*?\*\/)?\s*COMMIT/i,
41
- /\A(?:\/\*.*?\*\/)?\s*RELEASE\s+SAVEPOINT/i,
41
+ %r{\A(?:/\*.*?\*/)?\s*ROLLBACK}i,
42
+ %r{\A(?:/\*.*?\*/)?\s*COMMIT}i,
43
+ %r{\A(?:/\*.*?\*/)?\s*RELEASE\s+SAVEPOINT}i,
42
44
  )
43
45
 
44
46
  # The naked methods are exposed as `raw_query` and `raw_connect` for instrumentation purpose
@@ -55,7 +57,8 @@ module Semian
55
57
 
56
58
  def semian_identifier
57
59
  @semian_identifier ||= begin
58
- unless name = semian_options && semian_options[:name]
60
+ name = semian_options && semian_options[:name]
61
+ unless name
59
62
  host = query_options[:host] || DEFAULT_HOST
60
63
  port = query_options[:port] || DEFAULT_PORT
61
64
  name = "#{host}:#{port}"
@@ -68,7 +71,7 @@ module Semian
68
71
  result = nil
69
72
  acquire_semian_resource(adapter: :mysql, scope: :ping) do
70
73
  result = raw_ping
71
- raise PingFailure.new(result.to_s) unless result
74
+ raise PingFailure, result.to_s unless result
72
75
  end
73
76
  result
74
77
  rescue ResourceBusyError, CircuitOpenError, PingFailure
@@ -113,6 +116,7 @@ module Semian
113
116
  # data that is not recognized as a valid encoding, in which case we just
114
117
  # return false.
115
118
  return false unless sql.valid_encoding?
119
+
116
120
  raise
117
121
  end
118
122
 
@@ -132,7 +136,7 @@ module Semian
132
136
 
133
137
  def raw_semian_options
134
138
  return query_options[:semian] if query_options.key?(:semian)
135
- return query_options['semian'.freeze] if query_options.key?('semian'.freeze)
139
+ return query_options["semian"] if query_options.key?("semian")
136
140
  end
137
141
  end
138
142
  end
@@ -1,5 +1,7 @@
1
- require 'semian/adapter'
2
- require 'net/http'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/adapter"
4
+ require "net/http"
3
5
 
4
6
  module Net
5
7
  ProtocolError.include(::Semian::AdapterError)
@@ -40,10 +42,11 @@ module Semian
40
42
  ::Net::ProtocolError,
41
43
  ::EOFError,
42
44
  ::IOError,
43
- ::SystemCallError, # includes ::Errno::EINVAL, ::Errno::ECONNRESET, ::Errno::ECONNREFUSED, ::Errno::ETIMEDOUT, and more
45
+ ::SystemCallError, # includes ::Errno::EINVAL, ::Errno::ECONNRESET,
46
+ # ::Errno::ECONNREFUSED, ::Errno::ETIMEDOUT, and more
44
47
  ].freeze # Net::HTTP can throw many different errors, this tries to capture most of them
45
48
 
46
- module ClassMethods
49
+ module ClassMethods
47
50
  def new(*args, semian: true)
48
51
  http = super(*args)
49
52
  http.instance_variable_set(:@semian_enabled, semian)
@@ -57,6 +60,7 @@ module Semian
57
60
 
58
61
  def semian_configuration=(configuration)
59
62
  raise Semian::NetHTTP::SemianConfigurationChangedError unless @semian_configuration.nil?
63
+
60
64
  @semian_configuration = configuration
61
65
  end
62
66
 
@@ -88,11 +92,13 @@ module Semian
88
92
 
89
93
  def connect
90
94
  return super if disabled?
95
+
91
96
  acquire_semian_resource(adapter: :http, scope: :connection) { super }
92
97
  end
93
98
 
94
99
  def transport_request(*)
95
100
  return super if disabled?
101
+
96
102
  acquire_semian_resource(adapter: :http, scope: :query) do
97
103
  handle_error_responses(super)
98
104
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
4
  extend self
3
5
 
@@ -11,6 +13,6 @@ module Semian
11
13
  end
12
14
 
13
15
  def disabled?
14
- ENV['SEMIAN_SEMAPHORES_DISABLED'] || ENV['SEMIAN_DISABLED']
16
+ ENV["SEMIAN_SEMAPHORES_DISABLED"] || ENV["SEMIAN_DISABLED"]
15
17
  end
16
18
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Semian
2
4
  class ProtectedResource
3
5
  extend Forwardable
4
6
 
5
7
  def_delegators :@bulkhead, :destroy, :count, :semid, :tickets, :registered_workers
6
8
  def_delegators :@circuit_breaker, :reset, :mark_failed, :mark_success, :request_allowed?,
7
- :open?, :closed?, :half_open?
9
+ :open?, :closed?, :half_open?
8
10
 
9
11
  attr_reader :bulkhead, :circuit_breaker, :name
10
12
  attr_accessor :updated_at
@@ -17,8 +19,8 @@ module Semian
17
19
  end
18
20
 
19
21
  def destroy
20
- @bulkhead.destroy unless @bulkhead.nil?
21
- @circuit_breaker.destroy unless @circuit_breaker.nil?
22
+ @bulkhead&.destroy
23
+ @circuit_breaker&.destroy
22
24
  end
23
25
 
24
26
  def acquire(timeout: nil, scope: nil, adapter: nil, resource: nil)
data/lib/semian/rails.rb CHANGED
@@ -1,9 +1,36 @@
1
- require 'active_record/connection_adapters/abstract_adapter'
1
+ # frozen_string_literal: true
2
2
 
3
- class ActiveRecord::ConnectionAdapters::AbstractAdapter
4
- def semian_resource
5
- # support for https://github.com/rails/rails/commit/d86fd6415c0dfce6fadb77e74696cf728e5eb76b
6
- connection = instance_variable_defined?(:@raw_connection) ? @raw_connection : @connection
7
- connection.semian_resource
3
+ require "active_record/connection_adapters/abstract_adapter"
4
+
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
31
+ end
32
+ end
8
33
  end
9
34
  end
35
+
36
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Semian::Rails)
data/lib/semian/redis.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'semian/adapter'
2
- require 'redis'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/adapter"
4
+ require "redis"
3
5
 
4
6
  class Redis
5
7
  Redis::BaseConnectionError.include(::Semian::AdapterError)
@@ -17,7 +19,7 @@ class Redis
17
19
  end
18
20
 
19
21
  class ConnectionError < Redis::BaseConnectionError
20
- # A Connection Reset is a fast failure and we don't want to track these errors in
22
+ # A Connection Reset is a fast failure and we don't want to track these errors in
21
23
  # semian
22
24
  def marks_semian_circuits?
23
25
  message != "Connection lost (ECONNRESET)"
@@ -90,12 +92,11 @@ module Semian
90
92
 
91
93
  def connect
92
94
  acquire_semian_resource(adapter: :redis, scope: :connection) do
93
- begin
94
- raw_connect
95
- rescue SocketError, RuntimeError => e
96
- raise ResolveError.new(semian_identifier) if dns_resolve_failure?(e.cause || e)
97
- raise
98
- end
95
+ raw_connect
96
+ rescue SocketError, RuntimeError => e
97
+ raise ResolveError, semian_identifier if dns_resolve_failure?(e.cause || e)
98
+
99
+ raise
99
100
  end
100
101
  end
101
102
 
@@ -107,7 +108,7 @@ module Semian
107
108
 
108
109
  begin
109
110
  connection.timeout = temp_timeout if connected?
110
- options[:timeout] = Float(temp_timeout),
111
+ options[:timeout] = Float(temp_timeout)
111
112
  options[:connect_timeout] = Float(temp_timeout)
112
113
  options[:read_timeout] = Float(temp_timeout)
113
114
  options[:write_timeout] = Float(temp_timeout)
@@ -133,17 +134,18 @@ module Semian
133
134
 
134
135
  def raw_semian_options
135
136
  return options[:semian] if options.key?(:semian)
136
- return options['semian'.freeze] if options.key?('semian'.freeze)
137
+ return options["semian"] if options.key?("semian")
137
138
  end
138
139
 
139
140
  def raise_if_out_of_memory(reply)
140
141
  return unless reply.is_a?(::Redis::CommandError)
141
- return unless reply.message.start_with?("OOM ")
142
- raise ::Redis::OutOfMemoryError.new(reply.message)
142
+ return unless reply.message =~ /OOM command not allowed when used memory > 'maxmemory'/
143
+
144
+ raise ::Redis::OutOfMemoryError, reply.message
143
145
  end
144
146
 
145
147
  def dns_resolve_failure?(e)
146
- e.to_s.match?(/(can't resolve)|(name or service not known)|(nodename nor servname provided, or not known)|(failure in name resolution)/i)
148
+ e.to_s.match?(/(can't resolve)|(name or service not known)|(nodename nor servname provided, or not known)|(failure in name resolution)/i) # rubocop:disable Layout/LineLength
147
149
  end
148
150
  end
149
151
  end
@@ -1,5 +1,7 @@
1
- require 'semian/adapter'
2
- require 'redis-client'
1
+ # frozen_string_literal: true
2
+
3
+ require "semian/adapter"
4
+ require "redis-client"
3
5
 
4
6
  class RedisClient
5
7
  ConnectionError.include(::Semian::AdapterError)
@@ -104,7 +106,7 @@ module Semian
104
106
  include RedisClientCommon
105
107
  define_method(:semian_resource, Semian::Adapter.instance_method(:semian_resource))
106
108
  define_method(:clear_semian_resource, Semian::Adapter.instance_method(:clear_semian_resource))
107
- end
109
+ end
108
110
  end
109
111
 
110
112
  RedisClient.prepend(Semian::RedisClient)
@@ -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