semian 0.28.2 → 0.28.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c31bef07157ffec7aeb634db462f832595897cf1fd562771fca73021e1757274
4
- data.tar.gz: e8d8f487a8696445beff26e6924b2672b247f57c959141be8825f2bec10969e7
3
+ metadata.gz: 8fa1376f607286da6a30b6db227b4b27281228308c9c68724b356189cc97d2fb
4
+ data.tar.gz: 05161e0480da351f89ee3c3fe40cc9d4527a20e64f7830fdf671f92057675bb5
5
5
  SHA512:
6
- metadata.gz: a213874d4a487b36b672b2ddc5a6de6dc4959fb291931c93f0e365cb709de9af1e04756ae314d40a4d74ea6b50a96527aecab1ce77aee692f423ca5f1c17236d
7
- data.tar.gz: 8995c32426a6f817367ba642c7b780cdf367089b86105485a31f4ca001448ecbb3295844373ebe369de65f271abd83b9afbe0b1ab5ebdd175fc90dfe8c5fed3c
6
+ metadata.gz: 22d2074bf889aae268ea568f4a95f43b8e27f7b02ff24f4bf4afdcddba98bdf01e9090b166bc1b0124667bce39f57f19b5933415a309779e86fe448d5b2f7a36
7
+ data.tar.gz: 0b7a495a4e7a0bf71fa87b7422c6076c0580b3e368c23d1418d1e8c92745d2ba5acf951a049ade3e2b780a30273ad08fcb30747df2de36d5535e5a002866a952
data/README.md CHANGED
@@ -83,7 +83,8 @@ To create a Semian adapter you must implement the following methods:
83
83
  1. [`include Semian::Adapter`][semian-adapter]. Use the helpers to wrap the
84
84
  resource. This takes care of situations such as monitoring, nested resources,
85
85
  unsupported platforms, creating the Semian resource if it doesn't already
86
- exist and so on.
86
+ exist and so on. Include it in an object that represents a single resource,
87
+ typically one connection — see [Thread Safety](#thread-safety).
87
88
  2. `#semian_identifier`. This is responsible for returning a symbol that
88
89
  represents every unique resource, for example `redis_master` or
89
90
  `mysql_shard_1`. This is usually assembled from a `name` attribute on the
@@ -214,6 +215,27 @@ Semian's circuit breaker implementation is thread-safe by default as of
214
215
  `v0.7.0`. If you'd like to disable it for performance reasons, pass
215
216
  `thread_safety_disabled: true` to the resource options.
216
217
 
218
+ An adapter instance represents one resource. Once that resource has been
219
+ acquired, Semian treats further access through the same instance as part of the
220
+ same session: nested or overlapping calls do not re-enter the circuit breaker
221
+ and do not take a second bulkhead ticket, so a circuit that opens elsewhere in
222
+ the process cannot interrupt a session that is already in flight and
223
+ succeeding. Every adapter that ships with Semian has this shape — the mixin is
224
+ included in a connection object, and the session is that connection's unit of
225
+ work.
226
+
227
+ This is likely to give unexpected results if the adapter instance is shared
228
+ process-wide, such as by a singleton. While any call is in flight, calls made
229
+ through the same instance from other threads are treated as part of that
230
+ session, so they are not fast-failed when the circuit has opened since that
231
+ first acquire, and they cannot contribute failures. Where calls overlap
232
+ continuously, that keeps the circuit closed while the resource is failing.
233
+ Consider introducing a "session" object as the adapterized wrapper around the
234
+ singleton instead, created per unit of work — per request, say. Circuit breaker
235
+ and bulkhead state is keyed by `semian_identifier` and held in a process-wide
236
+ registry, so short-lived adapter instances that share an identifier all share
237
+ one circuit.
238
+
217
239
  Bulkheads should be disabled (pass `bulkhead: false`) in a threaded environment
218
240
  (e.g. Puma or Sidekiq), but can safely be enabled in non-threaded environments
219
241
  (e.g. Resque and Unicorn). As described in this document, circuit breakers alone
@@ -58,8 +58,26 @@ module Semian
58
58
  def execute_intent(intent)
59
59
  return super if self.class.query_allowlisted?(intent.processed_sql)
60
60
 
61
+ result = nil
62
+ delivered_error = nil
63
+
61
64
  acquire_semian_resource(adapter: semian_adapter_name, scope: :query) do
62
- super
65
+ result = super
66
+
67
+ # In Rails 8.2 execute_intent no longer raises errors. Instead, they are stored on the intent
68
+ # and handled later by the caller to better enable asynchronous execution. However, we need to raise
69
+ # any errors here to trip the circuit breaker. Then we can swallow the error and return the result for
70
+ # Rails to continue with.
71
+ if intent.respond_to?(:error)
72
+ delivered_error = intent.error
73
+ raise delivered_error if delivered_error
74
+ end
75
+ end
76
+ rescue => error
77
+ if error.equal?(delivered_error)
78
+ result
79
+ else
80
+ raise
63
81
  end
64
82
  end
65
83
  else
@@ -7,6 +7,7 @@ module ActiveRecord
7
7
  module ConnectionAdapters
8
8
  class PostgreSQLAdapter
9
9
  ActiveRecord::ActiveRecordError.include(::Semian::AdapterError)
10
+ ::PG::ConnectionBad.include(::Semian::AdapterError)
10
11
 
11
12
  class SemianError < ConnectionNotEstablished
12
13
  def initialize(semian_identifier, *args)
@@ -40,6 +41,10 @@ module Semian
40
41
 
41
42
  private
42
43
 
44
+ def resource_exceptions
45
+ super + [::PG::ConnectionBad]
46
+ end
47
+
43
48
  def semian_adapter_name = :postgresql_adapter
44
49
 
45
50
  def semian_adapter_default_port = 5432
@@ -79,11 +79,10 @@ module Semian
79
79
  end
80
80
 
81
81
  def mark_resource_as_acquired
82
- previous = @resource_acquired
83
82
  @resource_acquired = true
84
83
  yield
85
84
  ensure
86
- @resource_acquired = previous
85
+ @resource_acquired = false
87
86
  end
88
87
  end
89
88
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Semian
4
- VERSION = "0.28.2"
4
+ VERSION = "0.28.4"
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.28.2
4
+ version: 0.28.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Francis
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  - !ruby/object:Gem::Version
101
101
  version: '0'
102
102
  requirements: []
103
- rubygems_version: 4.0.11
103
+ rubygems_version: 4.0.19
104
104
  specification_version: 4
105
105
  summary: Bulkheading for Ruby with SysV semaphores
106
106
  test_files: []