active_record_proxy_adapters 0.6.3 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7164f319b8f041904c1facab957684b94aa2d650fef45edd7ac6d2aff670963f
4
- data.tar.gz: b2cdab2c0eedfd52db0cf9eeddc42671946dbbde5bf678cc2bb11ec4bf159d48
3
+ metadata.gz: eaa34c675630f13046dbc7170773fca75998eecef0b6e4990ce53110bdfdecef
4
+ data.tar.gz: 92c024345625535b4f3bfcb241b898e3a26c09836a5f3c6dac61749c913aef85
5
5
  SHA512:
6
- metadata.gz: 9501637dd67b12563f6d74cb2c3992de64696aeefc35d812d2e1ec3fdaddf0f8deb459f220d4317f9b8272bc1a3051110910d277bea8fa2a33403dc6cac09815
7
- data.tar.gz: a5e0f73f012a2738cb915bc5522252e213c9e1ba1449df3d223f186dcb383bfbb439e29dec01d780b4ba975a4dbec7ad221399aa48ac3ea32c5a633e83cca55f
6
+ metadata.gz: 76493c2922eb8f725410bc69223b9bc9dd121cece620e188a73b941ea7b8ef549108ffea8d3c1c38ddee2ed5686b6160284f87665ea431e41f4a32bccc80472a
7
+ data.tar.gz: 24c3cf701b469e364a5206ace80d3e8a609fddcd1839337069f0b0f7bbbf27f6c35940d7642a5f717b6030bf776afa988912fb8306b0e8b5d4d2e7fe5bde0ff4
data/README.md CHANGED
@@ -150,6 +150,25 @@ ActiveRecordProxyAdapters.configure do |config|
150
150
  end
151
151
  ```
152
152
 
153
+ ### Configuring multiple connections
154
+ General settings are automatically applied to the `primary` database by default.
155
+
156
+ If your application has multiple databases that need separate proxy settings, you can use the `database` block for individual database settings.
157
+
158
+ ```ruby
159
+ ActiveRecordProxyAdapters.configure do |config|
160
+ config.database :primary do |primary_config|
161
+ primary_config.proxy_delay = 2.seconds
162
+ end
163
+
164
+ config.database :secondary do |secondary_config|
165
+ secondary_config.proxy_delay = 5.seconds
166
+ end
167
+ end
168
+ ```
169
+
170
+ With those settings, any model that `connects_to database: { writing: :primary }` will have a 2-second delay, and any model that `connects_to database: { writing: :secondary }` will have a 5-second delay.
171
+
153
172
  ## Logging
154
173
 
155
174
  ```ruby
@@ -157,8 +176,8 @@ end
157
176
  require "active_record_proxy_adapters/log_subscriber"
158
177
 
159
178
  ActiveRecordProxyAdapters.configure do |config|
160
- config.log_subscriber_primary_prefix = "My primary tag" # defaults to "#{adapter_name} Primary", i.e "PostgreSQL Primary"
161
- config.log_subscriber_replica_prefix = "My replica tag" # defaults to "#{adapter_name} Replica", i.e "PostgreSQL Replica"
179
+ config.log_subscriber_primary_prefix = "My primary tag" # defaults to ActiveRecord configuration name", i.e "primary"
180
+ config.log_subscriber_replica_prefix = "My replica tag" # defaults to ActiveRecord configuration name", i.e "primary_replica"
162
181
  end
163
182
 
164
183
  # You may want to remove duplicate logs
@@ -7,12 +7,8 @@ module ActiveRecordProxyAdapters
7
7
  include SynchronizableConfiguration
8
8
 
9
9
  # Sets the cache store to use for caching SQL statements.
10
- #
11
- # @param store [ActiveSupport::Cache::Store] The cache store to use for caching SQL statements.
12
- # Defaults to ActiveSupport::Cache::NullStore, which does not cache anything.
13
- # Thread safe.
10
+ # Defaults to {ActiveSupport::Cache::NullStore}, which does not cache anything.
14
11
  # @return [ActiveSupport::Cache::Store] The cache store to use for caching SQL statements.
15
- # Defaults to ActiveSupport::Cache::NullStore, which does not cache anything.
16
12
  # Thread safe.
17
13
  attr_reader :store
18
14
 
@@ -51,5 +47,9 @@ module ActiveRecordProxyAdapters
51
47
  def bust
52
48
  store.delete_matched("#{key_prefix}*")
53
49
  end
50
+
51
+ private
52
+
53
+ attr_reader :lock
54
54
  end
55
55
  end
@@ -1,32 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/integer/time"
4
- require "active_record_proxy_adapters/synchronizable_configuration"
5
3
  require "active_record_proxy_adapters/cache_configuration"
6
4
  require "active_record_proxy_adapters/context"
5
+ require "active_record_proxy_adapters/database_configuration"
6
+ require "active_record_proxy_adapters/synchronizable_configuration"
7
+ require "active_support/core_ext/integer/time"
7
8
 
8
9
  module ActiveRecordProxyAdapters
9
10
  # Provides a global configuration object to configure how the proxy should behave.
10
11
  class Configuration
11
12
  include SynchronizableConfiguration
12
13
 
13
- PROXY_DELAY = 2.seconds.freeze
14
- CHECKOUT_TIMEOUT = 2.seconds.freeze
15
- LOG_SUBSCRIBER_PRIMARY_PREFIX = proc { |event| "#{event.payload[:connection].class::ADAPTER_NAME} Primary" }.freeze
16
- LOG_SUBSCRIBER_REPLICA_PREFIX = proc { |event| "#{event.payload[:connection].class::ADAPTER_NAME} Replica" }.freeze
17
-
18
- # @return [ActiveSupport::Duration] How long the proxy should reroute all read requests to the primary database
19
- # since the latest write. Defaults to PROXY_DELAY. Thread safe.
20
- attr_reader :proxy_delay
21
- # @return [ActiveSupport::Duration] How long the proxy should wait for a connection from the replica pool.
22
- # Defaults to CHECKOUT_TIMEOUT. Thread safe.
23
- attr_reader :checkout_timeout
24
-
25
- # @return [Proc] Prefix for the log subscriber when the primary database is used. Thread safe.
26
- attr_reader :log_subscriber_primary_prefix
27
-
28
- # @return [Proc] Prefix for the log subscriber when the replica database is used. Thread safe.
29
- attr_reader :log_subscriber_replica_prefix
14
+ DEFAULT_DATABASE_NAME = :primary
30
15
 
31
16
  # @return [Class] The context that is used to store the current request's state.
32
17
  attr_reader :context_store
@@ -34,46 +19,48 @@ module ActiveRecordProxyAdapters
34
19
  def initialize
35
20
  @lock = Monitor.new
36
21
 
37
- self.proxy_delay = PROXY_DELAY
38
- self.checkout_timeout = CHECKOUT_TIMEOUT
39
- self.log_subscriber_primary_prefix = LOG_SUBSCRIBER_PRIMARY_PREFIX
40
- self.log_subscriber_replica_prefix = LOG_SUBSCRIBER_REPLICA_PREFIX
41
- self.cache_configuration = CacheConfiguration.new(@lock)
42
- self.context_store = ActiveRecordProxyAdapters::Context
22
+ self.cache_configuration = CacheConfiguration.new(@lock)
23
+ self.context_store = ActiveRecordProxyAdapters::Context
24
+ @database_configurations = {}
43
25
  end
44
26
 
45
27
  def log_subscriber_primary_prefix=(prefix)
46
- prefix_proc = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
28
+ default_database_config.log_subscriber_primary_prefix = prefix
29
+ end
47
30
 
48
- synchronize_update(:log_subscriber_primary_prefix, from: @log_subscriber_primary_prefix, to: prefix_proc) do
49
- @log_subscriber_primary_prefix = prefix_proc
50
- end
31
+ def log_subscriber_primary_prefix
32
+ default_database_config.log_subscriber_primary_prefix
51
33
  end
52
34
 
53
35
  def log_subscriber_replica_prefix=(prefix)
54
- prefix_proc = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
36
+ default_database_config.log_subscriber_replica_prefix = prefix
37
+ end
55
38
 
56
- synchronize_update(:log_subscriber_replica_prefix, from: @log_subscriber_replica_prefix, to: prefix_proc) do
57
- @log_subscriber_replica_prefix = prefix_proc
58
- end
39
+ def log_subscriber_replica_prefix
40
+ default_database_config.log_subscriber_replica_prefix
41
+ end
42
+
43
+ def proxy_delay
44
+ default_database_config.proxy_delay
59
45
  end
60
46
 
61
47
  def proxy_delay=(proxy_delay)
62
- synchronize_update(:proxy_delay, from: @proxy_delay, to: proxy_delay) do
63
- @proxy_delay = proxy_delay
64
- end
48
+ default_database_config.proxy_delay = proxy_delay
49
+ end
50
+
51
+ def checkout_timeout
52
+ default_database_config.checkout_timeout
65
53
  end
66
54
 
67
55
  def checkout_timeout=(checkout_timeout)
68
- synchronize_update(:checkout_timeout, from: @checkout_timeout, to: checkout_timeout) do
69
- @checkout_timeout = checkout_timeout
70
- end
56
+ default_database_config.checkout_timeout = checkout_timeout
71
57
  end
72
58
 
73
- def context_store=(context_store)
74
- synchronize_update(:context_store, from: @context_store, to: context_store) do
75
- @context_store = context_store
76
- end
59
+ def database(database_name)
60
+ key = database_name.to_s
61
+ lock.synchronize { @database_configurations[key] ||= DatabaseConfiguration.new }
62
+
63
+ block_given? ? yield(database_configurations[key]) : database_configurations[key]
77
64
  end
78
65
 
79
66
  def cache
@@ -82,13 +69,22 @@ module ActiveRecordProxyAdapters
82
69
 
83
70
  private
84
71
 
85
- # @return [CacheConfiguration] The cache configuration for the proxy adapters.
86
- attr_reader :cache_configuration
72
+ attr_reader :cache_configuration, :database_configurations, :lock
73
+
74
+ def default_database_config
75
+ database(DEFAULT_DATABASE_NAME)
76
+ end
87
77
 
88
78
  def cache_configuration=(cache_configuration)
89
79
  synchronize_update(:cache_configuration, from: @cache_configuration, to: cache_configuration) do
90
80
  @cache_configuration = cache_configuration
91
81
  end
92
82
  end
83
+
84
+ def context_store=(context_store)
85
+ synchronize_update(:context_store, from: @context_store, to: context_store) do
86
+ @context_store = context_store
87
+ end
88
+ end
93
89
  end
94
90
  end
@@ -16,19 +16,23 @@ module ActiveRecordProxyAdapters
16
16
  end
17
17
 
18
18
  def recent_write_to_primary?(connection_name)
19
- now - self[connection_name] < proxy_delay
19
+ now - self[connection_name.to_s] < proxy_delay(connection_name)
20
20
  end
21
21
 
22
22
  def update_for(connection_name)
23
- self[connection_name] = now
23
+ self[connection_name.to_s] = now
24
24
  end
25
25
 
26
26
  def [](connection_name)
27
- timestamp_registry[connection_name] || 0
27
+ timestamp_registry[connection_name.to_s] || 0
28
28
  end
29
29
 
30
30
  def []=(connection_name, timestamp)
31
- timestamp_registry[connection_name] = timestamp
31
+ timestamp_registry[connection_name.to_s] = timestamp
32
+ end
33
+
34
+ def to_h
35
+ timestamp_registry.dup
32
36
  end
33
37
 
34
38
  private
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/integer/time"
4
+ require "active_record_proxy_adapters/synchronizable_configuration"
5
+ require "active_record_proxy_adapters/cache_configuration"
6
+ require "active_record_proxy_adapters/context"
7
+
8
+ module ActiveRecordProxyAdapters
9
+ # Provides a global configuration object to configure how the proxy should behave.
10
+ class DatabaseConfiguration
11
+ include SynchronizableConfiguration
12
+
13
+ PROXY_DELAY = 2.seconds.freeze
14
+ CHECKOUT_TIMEOUT = 2.seconds.freeze
15
+ DEFAULT_PREFIX = proc do |event|
16
+ connection = event.payload[:connection]
17
+
18
+ connection.pool.try(:db_config).try(:name) || connection.class::ADAPTER_NAME
19
+ end
20
+
21
+ # @return [ActiveSupport::Duration] How long the proxy should reroute all read requests to the primary database
22
+ # since the latest write. Defaults to PROXY_DELAY. Thread safe.
23
+ attr_reader :proxy_delay
24
+ # @return [ActiveSupport::Duration] How long the proxy should wait for a connection from the replica pool.
25
+ # Defaults to CHECKOUT_TIMEOUT. Thread safe.
26
+ attr_reader :checkout_timeout
27
+
28
+ # @return [Proc] Prefix for the log subscriber when the primary database is used. Thread safe.
29
+ attr_reader :log_subscriber_primary_prefix
30
+
31
+ # @return [Proc] Prefix for the log subscriber when the replica database is used. Thread safe.
32
+ attr_reader :log_subscriber_replica_prefix
33
+
34
+ def initialize
35
+ @lock = Monitor.new
36
+ self.proxy_delay = PROXY_DELAY
37
+ self.checkout_timeout = CHECKOUT_TIMEOUT
38
+ self.log_subscriber_primary_prefix = DEFAULT_PREFIX
39
+ self.log_subscriber_replica_prefix = DEFAULT_PREFIX
40
+ end
41
+
42
+ def proxy_delay=(proxy_delay)
43
+ synchronize_update(:proxy_delay, from: @proxy_delay, to: proxy_delay) do
44
+ @proxy_delay = proxy_delay
45
+ end
46
+ end
47
+
48
+ def checkout_timeout=(checkout_timeout)
49
+ synchronize_update(:checkout_timeout, from: @checkout_timeout, to: checkout_timeout) do
50
+ @checkout_timeout = checkout_timeout
51
+ end
52
+ end
53
+
54
+ def log_subscriber_primary_prefix=(prefix)
55
+ prefix_proc = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
56
+
57
+ synchronize_update(:log_subscriber_primary_prefix, from: @log_subscriber_primary_prefix, to: prefix_proc) do
58
+ @log_subscriber_primary_prefix = prefix_proc
59
+ end
60
+ end
61
+
62
+ def log_subscriber_replica_prefix=(prefix)
63
+ prefix_proc = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
64
+
65
+ synchronize_update(:log_subscriber_replica_prefix, from: @log_subscriber_replica_prefix, to: prefix_proc) do
66
+ @log_subscriber_replica_prefix = prefix_proc
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :lock
73
+ end
74
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module ActiveRecordProxyAdapters
4
4
  class LogSubscriber < ActiveRecord::LogSubscriber # rubocop:disable Style/Documentation
5
+ include Mixin::Configuration
6
+
5
7
  attach_to :active_record
6
8
 
7
9
  IGNORE_PAYLOAD_NAMES = %w[SCHEMA EXPLAIN].freeze
@@ -19,23 +21,27 @@ module ActiveRecordProxyAdapters
19
21
  protected
20
22
 
21
23
  def database_instance_prefix_for(event)
22
- connection = event.payload[:connection]
23
- config = connection.instance_variable_get(:@config)
24
- prefix = if config[:replica] || config["replica"]
25
- log_subscriber_replica_prefix
24
+ connection = event.payload[:connection]
25
+ db_config = connection.pool.try(:db_config) || NullConfig.new # AR 7.0.x does not support "NullConfig"
26
+ connection_name = db_config.name
27
+
28
+ prefix = if db_config.replica?
29
+ log_subscriber_replica_prefix(connection_name)
26
30
  else
27
- log_subscriber_primary_prefix
31
+ log_subscriber_primary_prefix(connection_name)
28
32
  end
29
33
 
30
34
  "[#{prefix.call(event)}]"
31
35
  end
32
36
 
33
- private
34
-
35
- delegate :log_subscriber_primary_prefix, :log_subscriber_replica_prefix, to: :config
37
+ class NullConfig # rubocop:disable Style/Documentation
38
+ def method_missing(...)
39
+ nil
40
+ end
36
41
 
37
- def config
38
- ActiveRecordProxyAdapters.config
42
+ def respond_to_missing?(*)
43
+ true
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+ require "json"
5
+ require "active_record_proxy_adapters/context"
6
+ require "active_record_proxy_adapters/contextualizer"
7
+ require "active_record_proxy_adapters/mixin/configuration"
8
+
9
+ module ActiveRecordProxyAdapters
10
+ class Middleware # rubocop:disable Style/Documentation
11
+ include Contextualizer
12
+ include Mixin::Configuration
13
+
14
+ COOKIE_NAME = "arpa_context"
15
+ COOKIE_BUFFER = 5.seconds.freeze
16
+ DEFAULT_COOKIE_OPTIONS = {
17
+ path: "/",
18
+ http_only: true
19
+ }.freeze
20
+
21
+ class << self
22
+ include Mixin::Configuration
23
+ end
24
+
25
+ COOKIE_READER = lambda do |rack_env|
26
+ rack_request = Rack::Request.new(rack_env)
27
+ arpa_cookie = rack_request.cookies[COOKIE_NAME]
28
+ JSON.parse(arpa_cookie || "{}")
29
+ rescue JSON::ParserError
30
+ {}
31
+ end.freeze
32
+
33
+ COOKIE_WRITER = lambda do |headers, cookie_hash, options|
34
+ cookie = DEFAULT_COOKIE_OPTIONS.merge(options)
35
+ max_value = cookie_hash.values.max || 0
36
+ then_time = Time.at(max_value).utc
37
+ expires = then_time + proxy_delay(cookie_hash.key(max_value)) + COOKIE_BUFFER
38
+ max_age = expires - then_time
39
+ cookie[:expires] = expires
40
+ cookie[:max_age] = max_age
41
+ cookie[:value] = cookie_hash.to_json
42
+
43
+ Rack::Utils.set_cookie_header!(headers, COOKIE_NAME, cookie)
44
+ end.freeze
45
+
46
+ def initialize(app, cookie_options = {})
47
+ @app = app
48
+ @cookie_options = cookie_options
49
+ end
50
+
51
+ def call(env)
52
+ return @app.call(env) if ignore_request?(env)
53
+
54
+ self.current_context = context_store.new(COOKIE_READER.call(env))
55
+
56
+ status, headers, body = @app.call(env)
57
+
58
+ update_cookie_from_context(headers)
59
+
60
+ [status, headers, body]
61
+ end
62
+
63
+ private
64
+
65
+ def update_cookie_from_context(headers)
66
+ COOKIE_WRITER.call(headers, current_context.to_h, @cookie_options)
67
+ end
68
+
69
+ def ignore_request?(env)
70
+ return false unless defined?(Rails)
71
+ return false unless asset_prefix
72
+
73
+ /^#{asset_prefix}/.match?(env["PATH_INFO"].to_s)
74
+ end
75
+
76
+ def asset_prefix
77
+ Rails.try(:application).try(:config).try(:assets).try(:prefix)
78
+ end
79
+ end
80
+ end
@@ -10,17 +10,35 @@ module ActiveRecordProxyAdapters
10
10
  # Provides helpers to access to reduce boilerplate while retrieving configuration properties.
11
11
  module Configuration
12
12
  # Helper to retrieve the proxy delay from the configuration stored in
13
- # {ActiveRecordProxyAdapters::Configuration#proxy_delay}.
13
+ # {ActiveRecordProxyAdapters::DatabaseConfiguration#log_subscriber_primary_prefix}.
14
+ # @param database_name [Symbol, String] The name of the database to retrieve the prefix.
15
+ # @return [Proc]
16
+ def log_subscriber_primary_prefix(database_name)
17
+ database_config(database_name).log_subscriber_primary_prefix
18
+ end
19
+
20
+ # Helper to retrieve the proxy delay from the configuration stored in
21
+ # {ActiveRecordProxyAdapters::DatabaseConfiguration#log_subscriber_replica_prefix}.
22
+ # @param database_name [Symbol, String] The name of the database to retrieve the prefix.
23
+ # @return [Proc]
24
+ def log_subscriber_replica_prefix(database_name)
25
+ database_config(database_name).log_subscriber_replica_prefix
26
+ end
27
+
28
+ # Helper to retrieve the proxy delay from the configuration stored in
29
+ # {ActiveRecordProxyAdapters::DatabaseConfiguration#proxy_delay}.
30
+ # @param database_name [Symbol, String] The name of the database to retrieve the proxy delay for.
14
31
  # @return [ActiveSupport::Duration]
15
- def proxy_delay
16
- proxy_config.proxy_delay
32
+ def proxy_delay(database_name)
33
+ database_config(database_name).proxy_delay
17
34
  end
18
35
 
19
36
  # Helper to retrieve the checkout timeout from the configuration stored in
20
- # {ActiveRecordProxyAdapters::Configuration#checkout_timeout}.
37
+ # {ActiveRecordProxyAdapters::DatabaseConfiguration#checkout_timeout}.
38
+ # @param database_name [Symbol, String] The name of the database to retrieve the checkout timeout for.
21
39
  # @return [ActiveSupport::Duration]
22
- def checkout_timeout
23
- proxy_config.checkout_timeout
40
+ def checkout_timeout(database_name)
41
+ database_config(database_name).checkout_timeout
24
42
  end
25
43
 
26
44
  # Helper to retrieve the context store class from the configuration stored in
@@ -50,6 +68,11 @@ module ActiveRecordProxyAdapters
50
68
  proxy_config.cache
51
69
  end
52
70
 
71
+ # @!visibility private
72
+ def database_config(database_name)
73
+ proxy_config.database(database_name)
74
+ end
75
+
53
76
  # @!visibility private
54
77
  def proxy_config
55
78
  ActiveRecordProxyAdapters.config
@@ -35,13 +35,13 @@ module ActiveRecordProxyAdapters
35
35
  # These patterns define which database statments are considered write statments, so we can shortly re-route all
36
36
  # requests to the primary database so the replica has time to replicate
37
37
  WRITE_STATEMENT_MATCHERS = [
38
- /(\A|\s+?)BEGIN/i,
39
- /(\A|\s+?)COMMIT/i,
40
- /(\A|\s+?)ROLLBACK/i,
41
- /(\A|\s+?)(INSERT\s+?INTO\s+?\S+?)/i,
42
- /(\A|\s+?)UPDATE\s+?\S+?/i,
43
- /(\A|\s+?)DELETE\s+?FROM\s+?\S+?/i,
44
- /(\A|\s+?)DROP\s/i
38
+ /\ABEGIN/i,
39
+ /\ACOMMIT/i,
40
+ /\AROLLBACK/i,
41
+ /INSERT\s[\s\S]*INTO\s[\s\S]*/i,
42
+ /UPDATE\s[\s\S]*/i,
43
+ /DELETE\s[\s\S]*FROM\s[\s\S]*/i,
44
+ /DROP\s/i
45
45
  ].map(&:freeze).freeze
46
46
 
47
47
  # Abstract adapter methods that should be proxied.
@@ -181,7 +181,7 @@ module ActiveRecordProxyAdapters
181
181
  end
182
182
 
183
183
  def checkout_replica_connection
184
- replica_pool.checkout(checkout_timeout)
184
+ replica_pool.checkout(checkout_timeout(primary_connection_name))
185
185
  # rescue NoDatabaseError to avoid crashing when running db:create rake task
186
186
  # rescue ConnectionNotEstablished to handle connectivity issues in the replica
187
187
  # (for example, replication delay)
@@ -189,7 +189,6 @@ module ActiveRecordProxyAdapters
189
189
  primary_connection
190
190
  end
191
191
 
192
- # @return [TrueClass] if there has been a write within the last {#proxy_delay} seconds
193
192
  # @return [TrueClass] if sql_string matches a write statement (i.e. INSERT, UPDATE, DELETE, SELECT FOR UPDATE)
194
193
  # @return [FalseClass] if sql_string matches a read statement (i.e. SELECT)
195
194
  def need_primary?(sql_string)
@@ -233,7 +232,7 @@ module ActiveRecordProxyAdapters
233
232
  end
234
233
 
235
234
  def primary_connection_name
236
- @primary_connection_name ||= primary_connection.pool.try(:db_config).try(:name).try(:to_sym)
235
+ @primary_connection_name ||= primary_connection.pool.try(:db_config).try(:name).try(:to_s)
237
236
  end
238
237
 
239
238
  def proxy_context
@@ -6,6 +6,7 @@ module ActiveRecordProxyAdapters
6
6
  # Hooks into rails boot process to extend ActiveRecord with the proxy adapter.
7
7
  class Railtie < Rails::Railtie
8
8
  require "active_record_proxy_adapters/connection_handling"
9
+ require "active_record_proxy_adapters/middleware"
9
10
 
10
11
  config.to_prepare do
11
12
  Rails.autoloaders.each do |autoloader|
@@ -17,5 +18,9 @@ module ActiveRecordProxyAdapters
17
18
  )
18
19
  end
19
20
  end
21
+
22
+ initializer "active_record_proxy_adapters.configure_rails_initialization" do |app|
23
+ app.middleware.use ActiveRecordProxyAdapters::Middleware
24
+ end
20
25
  end
21
26
  end
@@ -7,8 +7,6 @@ module ActiveRecordProxyAdapters
7
7
  included do
8
8
  private
9
9
 
10
- attr_reader :lock
11
-
12
10
  def synchronize_update(attribute, from:, to:, &block)
13
11
  ActiveSupport::Notifications.instrument(
14
12
  "active_record_proxy_adapters.configuration_update",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordProxyAdapters
4
- VERSION = "0.6.3"
4
+ VERSION = "0.7.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_proxy_adapters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Cruz
@@ -63,6 +63,20 @@ dependencies:
63
63
  - - ">="
64
64
  - !ruby/object:Gem::Version
65
65
  version: 3.1.0
66
+ - !ruby/object:Gem::Dependency
67
+ name: json
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
66
80
  description: |-
67
81
  This gem allows automatic connection switching between a primary and one read replica database in ActiveRecord.
68
82
  It pattern matches the SQL statement being sent to decide whether it should go to the replica (SELECT) or the
@@ -96,9 +110,11 @@ files:
96
110
  - lib/active_record_proxy_adapters/connection_handling/trilogy.rb
97
111
  - lib/active_record_proxy_adapters/context.rb
98
112
  - lib/active_record_proxy_adapters/contextualizer.rb
113
+ - lib/active_record_proxy_adapters/database_configuration.rb
99
114
  - lib/active_record_proxy_adapters/database_tasks.rb
100
115
  - lib/active_record_proxy_adapters/hijackable.rb
101
116
  - lib/active_record_proxy_adapters/log_subscriber.rb
117
+ - lib/active_record_proxy_adapters/middleware.rb
102
118
  - lib/active_record_proxy_adapters/mixin/configuration.rb
103
119
  - lib/active_record_proxy_adapters/mysql2_proxy.rb
104
120
  - lib/active_record_proxy_adapters/postgresql_proxy.rb