semian 0.26.6 → 0.27.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 +4 -4
- data/README.md +29 -0
- data/lib/semian/activerecord_adapter.rb +125 -0
- data/lib/semian/activerecord_postgresql_adapter.rb +51 -0
- data/lib/semian/activerecord_trilogy_adapter.rb +9 -84
- data/lib/semian/redis/v5.rb +13 -0
- data/lib/semian/redis.rb +12 -1
- data/lib/semian/redis_client.rb +15 -0
- data/lib/semian/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc25bcc8e0291e3f53d1ecb6ac19e56b375ce0c16974d16c20b9a847b6d2104d
|
|
4
|
+
data.tar.gz: 8c4ab8f6259e8118fa94801b28392738a05403d346941738f68bea258bc41f37
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f0936f08aa93d042241bece483742cc03d9e50ebaf27a363aec1973026d989ee3c6c6067de13f9016a46b5a227fb40ac2136746c8da25d33895f5a4312da510
|
|
7
|
+
data.tar.gz: 6cada0bbab474810b4bc12617e2d6e323034e6b088cebfa0d41352f0f1c8e522b4fc37d2e9dde77328c1ac5a7fc76e34e76b94f313313da9363049a72fb83859
|
data/README.md
CHANGED
|
@@ -73,6 +73,7 @@ version is the version of the public gem with the same name:
|
|
|
73
73
|
- [`semian/redis`][redis-semian-adapter] (~> 3.2.1)
|
|
74
74
|
- [`semian/net_http`][nethttp-semian-adapter]
|
|
75
75
|
- [`semian/activerecord_trilogy_adapter`][activerecord-trilogy-semian-adapter]
|
|
76
|
+
- [`semian/activerecord_postgresql_adapter`][activerecord-postgresql-semian-adapter]
|
|
76
77
|
- [`semian-postgres`][postgres-semian-adapter]
|
|
77
78
|
|
|
78
79
|
### Creating Adapters
|
|
@@ -154,6 +155,33 @@ client = Redis.new(semian: {
|
|
|
154
155
|
})
|
|
155
156
|
```
|
|
156
157
|
|
|
158
|
+
##### Redis Out-of-Memory Errors
|
|
159
|
+
|
|
160
|
+
By default, Redis Out-of-Memory (OOM) errors will open the circuit breaker. This can be
|
|
161
|
+
problematic because it prevents read operations and commands that could free up memory
|
|
162
|
+
(like `DEL`, `LPOP`, etc.) from executing, hindering Redis recovery.
|
|
163
|
+
|
|
164
|
+
To allow OOM errors to fail fast without opening the circuit, set `open_circuit_on_oom: false`:
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
client = Redis.new(semian: {
|
|
168
|
+
name: "inventory",
|
|
169
|
+
open_circuit_on_oom: false # OOM errors won't open the circuit
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This also works with `RedisClient`:
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
client = RedisClient.config(
|
|
177
|
+
host: "localhost",
|
|
178
|
+
semian: {
|
|
179
|
+
name: "inventory",
|
|
180
|
+
open_circuit_on_oom: false
|
|
181
|
+
}
|
|
182
|
+
).new_client
|
|
183
|
+
```
|
|
184
|
+
|
|
157
185
|
#### Configuration Validation
|
|
158
186
|
|
|
159
187
|
Semian now provides a flag to specify log-based and exception-based configuration validation. To
|
|
@@ -1027,6 +1055,7 @@ $ bundle install
|
|
|
1027
1055
|
[postgres-semian-adapter]: https://github.com/mschoenlaub/semian-postgres
|
|
1028
1056
|
[redis-semian-adapter]: lib/semian/redis.rb
|
|
1029
1057
|
[activerecord-trilogy-semian-adapter]: lib/semian/activerecord_trilogy_adapter.rb
|
|
1058
|
+
[activerecord-postgres-semian-adapter]: lib/semian/activerecord_postgres_adapter.rb
|
|
1030
1059
|
[semian-adapter]: lib/semian/adapter.rb
|
|
1031
1060
|
[nethttp-semian-adapter]: lib/semian/net_http.rb
|
|
1032
1061
|
[nethttp-default-errors]: lib/semian/net_http.rb#L35-L45
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "semian/adapter"
|
|
4
|
+
require "active_record"
|
|
5
|
+
|
|
6
|
+
module Semian
|
|
7
|
+
module ActiveRecordAdapter
|
|
8
|
+
QUERY_ALLOWLIST = %r{\A(?:/\*.*?\*/)?\s*(ROLLBACK|COMMIT|RELEASE\s+SAVEPOINT)}i
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def query_allowlisted?(sql, *)
|
|
12
|
+
# COMMIT, ROLLBACK
|
|
13
|
+
tx_command_statement = sql.end_with?("T", "K")
|
|
14
|
+
|
|
15
|
+
# RELEASE SAVEPOINT. Nesting past _3 levels won't get bypassed.
|
|
16
|
+
# Active Record does not send trailing spaces or `;`, so we are in the realm of hand crafted queries here.
|
|
17
|
+
savepoint_statement = sql.end_with?("_1", "_2")
|
|
18
|
+
unclear = sql.end_with?(" ", ";")
|
|
19
|
+
|
|
20
|
+
if !tx_command_statement && !savepoint_statement && !unclear
|
|
21
|
+
false
|
|
22
|
+
else
|
|
23
|
+
QUERY_ALLOWLIST.match?(sql)
|
|
24
|
+
end
|
|
25
|
+
rescue ArgumentError
|
|
26
|
+
return false unless sql.valid_encoding?
|
|
27
|
+
|
|
28
|
+
raise
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
def included(base)
|
|
34
|
+
base.extend(ClassMethods)
|
|
35
|
+
base.class_eval do
|
|
36
|
+
attr_reader(:raw_semian_options, :semian_identifier)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(*options)
|
|
42
|
+
*, config = options
|
|
43
|
+
config = config.dup
|
|
44
|
+
@raw_semian_options = config.delete(:semian)
|
|
45
|
+
@semian_identifier = begin
|
|
46
|
+
name = semian_options && semian_options[:name]
|
|
47
|
+
unless name
|
|
48
|
+
host = config[:host] || "localhost"
|
|
49
|
+
port = config[:port] || semian_adapter_default_port
|
|
50
|
+
name = "#{host}:#{port}"
|
|
51
|
+
end
|
|
52
|
+
:"#{semian_adapter_identifier_prefix}_#{name}"
|
|
53
|
+
end
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if ActiveRecord.version >= Gem::Version.new("8.2.a")
|
|
58
|
+
def execute_intent(intent)
|
|
59
|
+
return super if self.class.query_allowlisted?(intent.processed_sql)
|
|
60
|
+
|
|
61
|
+
acquire_semian_resource(adapter: semian_adapter_name, scope: :query) do
|
|
62
|
+
super
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
def raw_execute(sql, *args, **kwargs, &block)
|
|
67
|
+
if self.class.query_allowlisted?(sql)
|
|
68
|
+
super
|
|
69
|
+
else
|
|
70
|
+
acquire_semian_resource(adapter: semian_adapter_name, scope: :query) do
|
|
71
|
+
super(sql, *args, **kwargs, &block)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def active?
|
|
78
|
+
acquire_semian_resource(adapter: semian_adapter_name, scope: :ping) do
|
|
79
|
+
super
|
|
80
|
+
end
|
|
81
|
+
rescue resource_busy_error_class, circuit_open_error_class
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def with_resource_timeout
|
|
86
|
+
raise NotImplementedError, "#{self.class} must implement a `with_resource_timeout` method"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def resource_exceptions
|
|
92
|
+
[
|
|
93
|
+
ActiveRecord::AdapterTimeout,
|
|
94
|
+
ActiveRecord::ConnectionFailed,
|
|
95
|
+
ActiveRecord::ConnectionNotEstablished,
|
|
96
|
+
]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def resource_busy_error_class
|
|
100
|
+
self.class::ResourceBusyError
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def circuit_open_error_class
|
|
104
|
+
self.class::CircuitOpenError
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def connect(*args)
|
|
108
|
+
acquire_semian_resource(adapter: semian_adapter_name, scope: :connection) do
|
|
109
|
+
super
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def semian_adapter_name
|
|
114
|
+
raise NotImplementedError, "#{self.class} must implement an `semian_adapter_name` method"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def semian_adapter_default_port
|
|
118
|
+
raise NotImplementedError, "#{self.class} must implement an `semian_adapter_default_port` method"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def semian_adapter_identifier_prefix
|
|
122
|
+
raise NotImplementedError, "#{self.class} must implement an `semian_adapter_identifier_prefix` method"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "semian/activerecord_adapter"
|
|
4
|
+
require "active_record/connection_adapters/postgresql_adapter"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module ConnectionAdapters
|
|
8
|
+
class PostgreSQLAdapter
|
|
9
|
+
ActiveRecord::ActiveRecordError.include(::Semian::AdapterError)
|
|
10
|
+
|
|
11
|
+
class SemianError < ConnectionNotEstablished
|
|
12
|
+
def initialize(semian_identifier, *args)
|
|
13
|
+
super(*args)
|
|
14
|
+
@semian_identifier = semian_identifier
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
ResourceBusyError = Class.new(SemianError)
|
|
19
|
+
CircuitOpenError = Class.new(SemianError)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module Semian
|
|
25
|
+
module ActiveRecordPostgreSQLAdapter
|
|
26
|
+
include Semian::Adapter
|
|
27
|
+
include Semian::ActiveRecordAdapter
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
def prepended(base)
|
|
31
|
+
base.extend(Semian::ActiveRecordAdapter::ClassMethods)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def with_resource_timeout(_temp_timeout)
|
|
36
|
+
# Resource timeouts aren't possible with PostgreSQL because there is no
|
|
37
|
+
# IO level timeout configuration, so we just yield.
|
|
38
|
+
yield
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def semian_adapter_name = :postgresql_adapter
|
|
44
|
+
|
|
45
|
+
def semian_adapter_default_port = 5432
|
|
46
|
+
|
|
47
|
+
def semian_adapter_identifier_prefix = :postgresql
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Semian::ActiveRecordPostgreSQLAdapter)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "semian/
|
|
4
|
-
require "active_record"
|
|
3
|
+
require "semian/activerecord_adapter"
|
|
5
4
|
require "active_record/connection_adapters/trilogy_adapter"
|
|
6
5
|
|
|
7
6
|
module ActiveRecord
|
|
@@ -25,84 +24,18 @@ end
|
|
|
25
24
|
module Semian
|
|
26
25
|
module ActiveRecordTrilogyAdapter
|
|
27
26
|
include Semian::Adapter
|
|
27
|
+
include Semian::ActiveRecordAdapter
|
|
28
28
|
|
|
29
|
-
ResourceBusyError = ::ActiveRecord::ConnectionAdapters::TrilogyAdapter::ResourceBusyError
|
|
30
|
-
CircuitOpenError = ::ActiveRecord::ConnectionAdapters::TrilogyAdapter::CircuitOpenError
|
|
31
|
-
|
|
32
|
-
QUERY_ALLOWLIST = %r{\A(?:/\*.*?\*/)?\s*(ROLLBACK|COMMIT|RELEASE\s+SAVEPOINT)}i
|
|
33
|
-
|
|
34
|
-
# The common case here is NOT to have transaction management statements, therefore
|
|
35
|
-
# we are exploiting the fact that Active Record will use COMMIT/ROLLBACK as
|
|
36
|
-
# the suffix of the command string and
|
|
37
|
-
# name savepoints by level of nesting as `active_record_1` ... n.
|
|
38
|
-
#
|
|
39
|
-
# Since looking at the last characters in a string using `end_with?` is a LOT cheaper than
|
|
40
|
-
# running a regex, we are returning early if the last characters of
|
|
41
|
-
# the SQL statements are NOT the last characters of the known transaction
|
|
42
|
-
# control statements.
|
|
43
29
|
class << self
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
tx_command_statement = sql.end_with?("T") || sql.end_with?("K")
|
|
47
|
-
|
|
48
|
-
# RELEASE SAVEPOINT. Nesting past _3 levels won't get bypassed.
|
|
49
|
-
# Active Record does not send trailing spaces or `;`, so we are in the realm of hand crafted queries here.
|
|
50
|
-
savepoint_statement = sql.end_with?("_1") || sql.end_with?("_2")
|
|
51
|
-
unclear = sql.end_with?(" ") || sql.end_with?(";")
|
|
52
|
-
|
|
53
|
-
if !tx_command_statement && !savepoint_statement && !unclear
|
|
54
|
-
false
|
|
55
|
-
else
|
|
56
|
-
QUERY_ALLOWLIST.match?(sql)
|
|
57
|
-
end
|
|
58
|
-
rescue ArgumentError
|
|
59
|
-
return false unless sql.valid_encoding?
|
|
60
|
-
|
|
61
|
-
raise
|
|
30
|
+
def prepended(base)
|
|
31
|
+
base.extend(Semian::ActiveRecordAdapter::ClassMethods)
|
|
62
32
|
end
|
|
63
33
|
end
|
|
64
34
|
|
|
65
|
-
attr_reader :raw_semian_options, :semian_identifier
|
|
66
|
-
|
|
67
|
-
def initialize(*options)
|
|
68
|
-
*, config = options
|
|
69
|
-
config = config.dup
|
|
70
|
-
@raw_semian_options = config.delete(:semian)
|
|
71
|
-
@semian_identifier = begin
|
|
72
|
-
name = semian_options && semian_options[:name]
|
|
73
|
-
unless name
|
|
74
|
-
host = config[:host] || "localhost"
|
|
75
|
-
port = config[:port] || 3306
|
|
76
|
-
name = "#{host}:#{port}"
|
|
77
|
-
end
|
|
78
|
-
:"mysql_#{name}"
|
|
79
|
-
end
|
|
80
|
-
super
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def raw_execute(sql, *)
|
|
84
|
-
if Semian::ActiveRecordTrilogyAdapter.query_allowlisted?(sql)
|
|
85
|
-
super
|
|
86
|
-
else
|
|
87
|
-
acquire_semian_resource(adapter: :trilogy_adapter, scope: :query) do
|
|
88
|
-
super
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
ruby2_keywords :raw_execute
|
|
93
|
-
|
|
94
|
-
def active?
|
|
95
|
-
acquire_semian_resource(adapter: :trilogy_adapter, scope: :ping) do
|
|
96
|
-
super
|
|
97
|
-
end
|
|
98
|
-
rescue ResourceBusyError, CircuitOpenError
|
|
99
|
-
false
|
|
100
|
-
end
|
|
101
|
-
|
|
102
35
|
def with_resource_timeout(temp_timeout)
|
|
103
36
|
if @raw_connection.nil?
|
|
104
37
|
prev_read_timeout = @config[:read_timeout] || 0
|
|
105
|
-
@config.merge!(read_timeout: temp_timeout)
|
|
38
|
+
@config.merge!(read_timeout: temp_timeout)
|
|
106
39
|
else
|
|
107
40
|
prev_read_timeout = @raw_connection.read_timeout
|
|
108
41
|
@raw_connection.read_timeout = temp_timeout
|
|
@@ -115,19 +48,11 @@ module Semian
|
|
|
115
48
|
|
|
116
49
|
private
|
|
117
50
|
|
|
118
|
-
def
|
|
119
|
-
[
|
|
120
|
-
ActiveRecord::AdapterTimeout,
|
|
121
|
-
ActiveRecord::ConnectionFailed,
|
|
122
|
-
ActiveRecord::ConnectionNotEstablished,
|
|
123
|
-
]
|
|
124
|
-
end
|
|
51
|
+
def semian_adapter_name = :trilogy_adapter
|
|
125
52
|
|
|
126
|
-
def
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
end
|
|
130
|
-
end
|
|
53
|
+
def semian_adapter_default_port = 3306
|
|
54
|
+
|
|
55
|
+
def semian_adapter_identifier_prefix = :mysql
|
|
131
56
|
end
|
|
132
57
|
end
|
|
133
58
|
|
data/lib/semian/redis/v5.rb
CHANGED
|
@@ -5,6 +5,16 @@ require "semian/redis_client"
|
|
|
5
5
|
class Redis
|
|
6
6
|
BaseConnectionError.include(::Semian::AdapterError)
|
|
7
7
|
OutOfMemoryError.include(::Semian::AdapterError)
|
|
8
|
+
OutOfMemoryError.class_eval do
|
|
9
|
+
attr_accessor :semian_open_circuit_on_oom
|
|
10
|
+
|
|
11
|
+
# By default, OOM errors open circuits (backward compatible behavior).
|
|
12
|
+
# Set `open_circuit_on_oom: false` to disable this if you want reads/deletes
|
|
13
|
+
# to continue working when Redis is OOM, allowing it to recover.
|
|
14
|
+
def marks_semian_circuits?
|
|
15
|
+
@semian_open_circuit_on_oom != false
|
|
16
|
+
end
|
|
17
|
+
end
|
|
8
18
|
|
|
9
19
|
class ReadOnlyError < Redis::BaseConnectionError
|
|
10
20
|
# A ReadOnlyError is a fast failure and we don't want to track these errors so that we can reconnect
|
|
@@ -47,6 +57,9 @@ module Semian
|
|
|
47
57
|
if redis_error < ::Semian::AdapterError
|
|
48
58
|
redis_error = redis_error.new(error.message)
|
|
49
59
|
redis_error.semian_identifier = error.semian_identifier
|
|
60
|
+
if error.respond_to?(:semian_open_circuit_on_oom) && redis_error.respond_to?(:semian_open_circuit_on_oom=)
|
|
61
|
+
redis_error.semian_open_circuit_on_oom = error.semian_open_circuit_on_oom
|
|
62
|
+
end
|
|
50
63
|
end
|
|
51
64
|
raise redis_error, error.message, error.backtrace
|
|
52
65
|
end
|
data/lib/semian/redis.rb
CHANGED
|
@@ -23,6 +23,15 @@ class Redis
|
|
|
23
23
|
|
|
24
24
|
class OutOfMemoryError < Redis::CommandError
|
|
25
25
|
include ::Semian::AdapterError
|
|
26
|
+
|
|
27
|
+
attr_accessor :semian_open_circuit_on_oom
|
|
28
|
+
|
|
29
|
+
# By default, OOM errors open circuits (backward compatible behavior).
|
|
30
|
+
# Set `open_circuit_on_oom: false` to disable this if you want reads/deletes
|
|
31
|
+
# to continue working when Redis is OOM, allowing it to recover.
|
|
32
|
+
def marks_semian_circuits?
|
|
33
|
+
@semian_open_circuit_on_oom != false
|
|
34
|
+
end
|
|
26
35
|
end
|
|
27
36
|
|
|
28
37
|
class ConnectionError < Redis::BaseConnectionError
|
|
@@ -159,7 +168,9 @@ module Semian
|
|
|
159
168
|
return unless reply.is_a?(::Redis::CommandError)
|
|
160
169
|
return unless reply.message =~ /OOM command not allowed when used memory > 'maxmemory'/
|
|
161
170
|
|
|
162
|
-
|
|
171
|
+
error = ::Redis::OutOfMemoryError.new(reply.message)
|
|
172
|
+
error.semian_open_circuit_on_oom = semian_options&.fetch(:open_circuit_on_oom, true)
|
|
173
|
+
raise error
|
|
163
174
|
end
|
|
164
175
|
|
|
165
176
|
def dns_resolve_failure?(e)
|
data/lib/semian/redis_client.rb
CHANGED
|
@@ -13,6 +13,17 @@ class RedisClient
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
OutOfMemoryError.include(::Semian::AdapterError)
|
|
16
|
+
OutOfMemoryError.class_eval do
|
|
17
|
+
attr_accessor :semian_open_circuit_on_oom
|
|
18
|
+
|
|
19
|
+
# By default, OOM errors open circuits (backward compatible behavior).
|
|
20
|
+
# Set `open_circuit_on_oom: false` to disable this if you want reads/dequeues
|
|
21
|
+
# to continue working when Redis is OOM, allowing it to recover.
|
|
22
|
+
# This is considered a fast failure.
|
|
23
|
+
def marks_semian_circuits?
|
|
24
|
+
@semian_open_circuit_on_oom != false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
16
27
|
|
|
17
28
|
class ReadOnlyError < RedisClient::ConnectionError
|
|
18
29
|
# A ReadOnlyError is a fast failure and we don't want to track these errors so that we can reconnect
|
|
@@ -110,6 +121,10 @@ module Semian
|
|
|
110
121
|
super do |connection|
|
|
111
122
|
acquire_semian_resource(adapter: :redis_client, scope: :query) do
|
|
112
123
|
yield connection
|
|
124
|
+
rescue ::RedisClient::OutOfMemoryError => error
|
|
125
|
+
error.semian_identifier = semian_identifier
|
|
126
|
+
error.semian_open_circuit_on_oom = semian_options&.fetch(:open_circuit_on_oom, true)
|
|
127
|
+
raise
|
|
113
128
|
end
|
|
114
129
|
end
|
|
115
130
|
else
|
data/lib/semian/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.27.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Francis
|
|
@@ -47,6 +47,8 @@ files:
|
|
|
47
47
|
- ext/semian/tickets.h
|
|
48
48
|
- ext/semian/types.h
|
|
49
49
|
- lib/semian.rb
|
|
50
|
+
- lib/semian/activerecord_adapter.rb
|
|
51
|
+
- lib/semian/activerecord_postgresql_adapter.rb
|
|
50
52
|
- lib/semian/activerecord_trilogy_adapter.rb
|
|
51
53
|
- lib/semian/adapter.rb
|
|
52
54
|
- lib/semian/circuit_breaker.rb
|
|
@@ -92,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
92
94
|
- !ruby/object:Gem::Version
|
|
93
95
|
version: '0'
|
|
94
96
|
requirements: []
|
|
95
|
-
rubygems_version:
|
|
97
|
+
rubygems_version: 4.0.4
|
|
96
98
|
specification_version: 4
|
|
97
99
|
summary: Bulkheading for Ruby with SysV semaphores
|
|
98
100
|
test_files: []
|