active_record_proxy_adapters 0.7.2 → 0.9.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 +13 -1
- data/lib/active_record/connection_adapters/mysql2_proxy_adapter.rb +0 -6
- data/lib/active_record/connection_adapters/postgresql_proxy_adapter.rb +0 -6
- data/lib/active_record/connection_adapters/trilogy_proxy_adapter.rb +1 -7
- data/lib/active_record_proxy_adapters/active_record_context.rb +1 -25
- data/lib/active_record_proxy_adapters/configuration.rb +65 -4
- data/lib/active_record_proxy_adapters/connection_handling/sqlite3_proxy.rb +28 -0
- data/lib/active_record_proxy_adapters/connection_handling.rb +4 -4
- data/lib/active_record_proxy_adapters/core.rb +13 -0
- data/lib/active_record_proxy_adapters/errors.rb +7 -0
- data/lib/active_record_proxy_adapters/log_subscriber.rb +1 -11
- data/lib/active_record_proxy_adapters/mixin/configuration.rb +14 -1
- data/lib/active_record_proxy_adapters/primary_replica_proxy.rb +26 -7
- data/lib/active_record_proxy_adapters/railtie.rb +5 -12
- data/lib/active_record_proxy_adapters/railties/mysql2.rb +13 -0
- data/lib/active_record_proxy_adapters/railties/postgresql.rb +21 -0
- data/lib/active_record_proxy_adapters/railties/sqlite3.rb +21 -0
- data/lib/active_record_proxy_adapters/railties/trilogy.rb +13 -0
- data/lib/active_record_proxy_adapters/trilogy_proxy.rb +1 -0
- data/lib/active_record_proxy_adapters/version.rb +1 -1
- data/lib/active_record_proxy_adapters.rb +0 -19
- metadata +44 -11
- data/lib/active_record_proxy_adapters/connection_handling/sqlite3.rb +0 -68
- data/lib/active_record_proxy_adapters/transactionable_proxy_a_r_70.rb +0 -31
- /data/lib/active_record_proxy_adapters/connection_handling/{mysql2.rb → mysql2_proxy.rb} +0 -0
- /data/lib/active_record_proxy_adapters/connection_handling/{postgresql.rb → postgresql_proxy.rb} +0 -0
- /data/lib/active_record_proxy_adapters/connection_handling/{trilogy.rb → trilogy_proxy.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f404b61f94eec82c838124e111eba202e7fdbea61c07596739219749e7c76ac2
|
4
|
+
data.tar.gz: 930327b485fb9b7637a1b810c0cb52def9d0164777103f918862a9dd4a0a89e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d0c6210521feb5db9ce40fc476607fb862d818e16feb23d795e95f20f20b8db0b1311049a5895f6e9795ba2740cdef140ecb6ec67f5f1c7c7aec759e0a4c2ca
|
7
|
+
data.tar.gz: 1134342f6be3093cb5a3ddaba514ef702adb611e5646a3abd3c68073fcb7060459a39a5845983733b4c5f0bc24d5928f57e8333b7741bbb8b3fa812d9472f066
|
data/README.md
CHANGED
@@ -25,6 +25,18 @@ Install the gem and add to the application's Gemfile by executing:
|
|
25
25
|
|
26
26
|
$ bundle add 'active_record_proxy_adapters'
|
27
27
|
|
28
|
+
That will install and load the proxies for all Rails-supported adapters (i.e. `postgresql_proxy`, `mysql2_proxy`, `sqlite3_proxy` and `trilogy_proxy`).
|
29
|
+
|
30
|
+
If you wish to load only one specific adapter for a faster application boot, use:
|
31
|
+
|
32
|
+
$ bundle add 'active_record_proxy_adapters' --require 'active_record_proxy_adapters/railties/<postgresql|mysql2|sqlite3|trilogy>'
|
33
|
+
|
34
|
+
Or, in your Gemfile, use:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
gem "active_record_proxy_adapters", require: 'active_record_proxy_adapters/railties/<postgresql|mysql2|sqlite3|trilogy>'
|
38
|
+
```
|
39
|
+
|
28
40
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
29
41
|
|
30
42
|
$ gem install active_record_proxy_adapters
|
@@ -558,7 +570,7 @@ To create a proxy adapter for an existing database `FoobarAdapter`, follow these
|
|
558
570
|
return
|
559
571
|
end
|
560
572
|
|
561
|
-
# This is only required for Rails 7.
|
573
|
+
# This is only required for Rails 7.1 or earlier.
|
562
574
|
module ActiveRecordProxyAdapters
|
563
575
|
module Foobar
|
564
576
|
module ConnectionHandling
|
@@ -13,12 +13,6 @@ module ActiveRecord
|
|
13
13
|
class Mysql2ProxyAdapter < Mysql2Adapter
|
14
14
|
include ActiveRecordProxyAdapters::Hijackable
|
15
15
|
|
16
|
-
if ActiveRecordProxyAdapters::ActiveRecordContext.active_record_v7_0?
|
17
|
-
require "active_record_proxy_adapters/transactionable_proxy_a_r_70"
|
18
|
-
|
19
|
-
include ActiveRecordProxyAdapters::TransactionableProxyAR70
|
20
|
-
end
|
21
|
-
|
22
16
|
ADAPTER_NAME = "Mysql2Proxy"
|
23
17
|
|
24
18
|
delegate_to_proxy(*ActiveRecordProxyAdapters::ActiveRecordContext.hijackable_methods)
|
@@ -13,12 +13,6 @@ module ActiveRecord
|
|
13
13
|
class PostgreSQLProxyAdapter < PostgreSQLAdapter
|
14
14
|
include ActiveRecordProxyAdapters::Hijackable
|
15
15
|
|
16
|
-
if ActiveRecordProxyAdapters::ActiveRecordContext.active_record_v7_0?
|
17
|
-
require "active_record_proxy_adapters/transactionable_proxy_a_r_70"
|
18
|
-
|
19
|
-
include ActiveRecordProxyAdapters::TransactionableProxyAR70
|
20
|
-
end
|
21
|
-
|
22
16
|
ADAPTER_NAME = "PostgreSQLProxy"
|
23
17
|
|
24
18
|
delegate_to_proxy(*ActiveRecordProxyAdapters::ActiveRecordContext.hijackable_methods)
|
@@ -13,15 +13,9 @@ module ActiveRecord
|
|
13
13
|
class TrilogyProxyAdapter < TrilogyAdapter
|
14
14
|
include ActiveRecordProxyAdapters::Hijackable
|
15
15
|
|
16
|
-
if ActiveRecordProxyAdapters::ActiveRecordContext.active_record_v7_0?
|
17
|
-
require "active_record_proxy_adapters/transactionable_proxy_a_r_70"
|
18
|
-
|
19
|
-
include ActiveRecordProxyAdapters::TransactionableProxyAR70
|
20
|
-
end
|
21
|
-
|
22
16
|
ADAPTER_NAME = "TrilogyProxy"
|
23
17
|
|
24
|
-
delegate_to_proxy(*ActiveRecordProxyAdapters::ActiveRecordContext.hijackable_methods)
|
18
|
+
delegate_to_proxy(*ActiveRecordProxyAdapters::ActiveRecordContext.hijackable_methods, :exec_insert)
|
25
19
|
|
26
20
|
def initialize(...)
|
27
21
|
@proxy = ActiveRecordProxyAdapters::TrilogyProxy.new(self)
|
@@ -5,38 +5,18 @@ module ActiveRecordProxyAdapters
|
|
5
5
|
# versions of rails.
|
6
6
|
class ActiveRecordContext
|
7
7
|
delegate :reading_role, :reading_role=, :writing_role, :writing_role=, to: :ActiveRecord
|
8
|
-
delegate :legacy_connection_handling, :legacy_connection_handling=, to: :connection_handling_context
|
9
8
|
delegate :version, to: :ActiveRecord, prefix: :active_record
|
10
9
|
|
11
10
|
class << self
|
12
11
|
delegate_missing_to :new
|
13
12
|
end
|
14
13
|
|
15
|
-
# rubocop:disable Naming/PredicateMethod
|
16
|
-
NullConnectionHandlingContext = Class.new do
|
17
|
-
def legacy_connection_handling
|
18
|
-
false
|
19
|
-
end
|
20
|
-
|
21
|
-
def legacy_connection_handling=(_value)
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
# rubocop:enable Naming/PredicateMethod
|
26
|
-
|
27
14
|
def connection_class_for(connection)
|
28
15
|
return connection.connection_descriptor.name.constantize if active_record_v8_0_2_or_greater?
|
29
16
|
|
30
17
|
connection.connection_class || ActiveRecord::Base
|
31
18
|
end
|
32
19
|
|
33
|
-
def connection_handling_context
|
34
|
-
# This config option has been removed in Rails 7.1+
|
35
|
-
return NullConnectionHandlingContext.new if active_record_v7_1_or_greater?
|
36
|
-
|
37
|
-
ActiveRecord
|
38
|
-
end
|
39
|
-
|
40
20
|
def hijackable_methods
|
41
21
|
hijackable = %i[execute exec_query]
|
42
22
|
|
@@ -46,11 +26,7 @@ module ActiveRecordProxyAdapters
|
|
46
26
|
end
|
47
27
|
|
48
28
|
def active_record_v7?
|
49
|
-
active_record_version >= Gem::Version.new("7.
|
50
|
-
end
|
51
|
-
|
52
|
-
def active_record_v7_0?
|
53
|
-
active_record_version >= Gem::Version.new("7.0") && active_record_version < Gem::Version.new("7.1")
|
29
|
+
active_record_version >= Gem::Version.new("7.1") && active_record_version < Gem::Version.new("8.0")
|
54
30
|
end
|
55
31
|
|
56
32
|
def active_record_v7_1_or_greater?
|
@@ -3,26 +3,64 @@
|
|
3
3
|
require "active_record_proxy_adapters/cache_configuration"
|
4
4
|
require "active_record_proxy_adapters/context"
|
5
5
|
require "active_record_proxy_adapters/database_configuration"
|
6
|
+
require "active_record_proxy_adapters/errors"
|
6
7
|
require "active_record_proxy_adapters/synchronizable_configuration"
|
7
8
|
require "active_support/core_ext/integer/time"
|
9
|
+
require "logger"
|
10
|
+
|
11
|
+
module ActiveRecordProxyAdapters # rubocop:disable Style/Documentation
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def configure
|
15
|
+
yield(config)
|
16
|
+
end
|
17
|
+
|
18
|
+
def bust_query_cache
|
19
|
+
config.cache.bust
|
20
|
+
end
|
21
|
+
|
22
|
+
def config
|
23
|
+
@config ||= Configuration.new
|
24
|
+
end
|
8
25
|
|
9
|
-
module ActiveRecordProxyAdapters
|
10
26
|
# Provides a global configuration object to configure how the proxy should behave.
|
11
27
|
class Configuration
|
12
28
|
include SynchronizableConfiguration
|
13
29
|
|
14
30
|
DEFAULT_DATABASE_NAME = :primary
|
15
31
|
DEFAULT_REPLICA_DATABASE_NAME = :primary_replica
|
32
|
+
TIMEOUT_MESSAGE_BUILDER = proc { |sql_string, regex = nil|
|
33
|
+
[regex, "timed out. Input too big (#{sql_string.size})."].compact_blank.join(" ")
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
private_constant :TIMEOUT_MESSAGE_BUILDER
|
37
|
+
|
38
|
+
REGEXP_TIMEOUT_STRATEGY_REGISTRY = {
|
39
|
+
log: proc { |sql_string, regex = nil|
|
40
|
+
ActiveRecordProxyAdapters.config.logger.error(TIMEOUT_MESSAGE_BUILDER.call(sql_string, regex))
|
41
|
+
},
|
42
|
+
raise: proc { |sql_string, regex = nil|
|
43
|
+
raise ActiveRecordProxyAdapters::RegexpTimeoutError, TIMEOUT_MESSAGE_BUILDER.call(sql_string, regex)
|
44
|
+
}
|
45
|
+
}.freeze
|
16
46
|
|
17
47
|
# @return [Class] The context that is used to store the current request's state.
|
18
48
|
attr_reader :context_store
|
19
49
|
|
50
|
+
# @return [Proc] The timeout strategy to use for regex matching.
|
51
|
+
attr_reader :regexp_timeout_strategy
|
52
|
+
|
53
|
+
# @return [Logger] The logger to use for logging messages.
|
54
|
+
attr_reader :logger
|
55
|
+
|
20
56
|
def initialize
|
21
57
|
@lock = Monitor.new
|
22
58
|
|
23
|
-
self.cache_configuration
|
24
|
-
self.context_store
|
25
|
-
|
59
|
+
self.cache_configuration = CacheConfiguration.new(@lock)
|
60
|
+
self.context_store = ActiveRecordProxyAdapters::Context
|
61
|
+
self.regexp_timeout_strategy = :log
|
62
|
+
self.logger = ActiveRecord::Base.logger || Logger.new($stdout)
|
63
|
+
@database_configurations = {}
|
26
64
|
end
|
27
65
|
|
28
66
|
def log_subscriber_primary_prefix=(prefix)
|
@@ -57,6 +95,25 @@ module ActiveRecordProxyAdapters
|
|
57
95
|
default_database_config.checkout_timeout = checkout_timeout
|
58
96
|
end
|
59
97
|
|
98
|
+
def logger=(logger)
|
99
|
+
synchronize_update(:logger, from: @logger, to: logger) do
|
100
|
+
@logger = logger
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def regexp_timeout_strategy=(strategy)
|
105
|
+
synchronize_update(:regexp_timeout_strategy, from: @regexp_timeout_strategy, to: strategy) do
|
106
|
+
@regexp_timeout_strategy = if strategy.respond_to?(:call)
|
107
|
+
strategy
|
108
|
+
else
|
109
|
+
REGEXP_TIMEOUT_STRATEGY_REGISTRY.fetch(strategy)
|
110
|
+
end
|
111
|
+
rescue KeyError
|
112
|
+
raise ActiveRecordProxyAdapters::ConfigurationError,
|
113
|
+
"Invalid regex timeout strategy: #{strategy.inspect}. Must be one of: #{valid_regexp_timeout_strategies}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
60
117
|
def database(database_name)
|
61
118
|
key = database_name.to_s
|
62
119
|
lock.synchronize { @database_configurations[key] ||= DatabaseConfiguration.new }
|
@@ -72,6 +129,10 @@ module ActiveRecordProxyAdapters
|
|
72
129
|
|
73
130
|
attr_reader :cache_configuration, :database_configurations, :lock
|
74
131
|
|
132
|
+
def valid_regexp_timeout_strategies
|
133
|
+
REGEXP_TIMEOUT_STRATEGY_REGISTRY.keys
|
134
|
+
end
|
135
|
+
|
75
136
|
def default_database_config
|
76
137
|
database(DEFAULT_DATABASE_NAME)
|
77
138
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "active_record/connection_adapters/sqlite3_proxy_adapter"
|
5
|
+
rescue LoadError
|
6
|
+
# sqlite3 not available
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
module ActiveRecordProxyAdapters
|
11
|
+
module SQLite3
|
12
|
+
# Module to extend ActiveRecord::Base with the connection handling methods.
|
13
|
+
# Required to make adapter work in ActiveRecord versions <= 7.2.x
|
14
|
+
module ConnectionHandling
|
15
|
+
def sqlite3_proxy_adapter_class
|
16
|
+
ActiveRecord::ConnectionAdapters::SQLite3ProxyAdapter
|
17
|
+
end
|
18
|
+
|
19
|
+
def sqlite3_proxy_connection(config)
|
20
|
+
sqlite3_proxy_adapter_class.new(config)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveSupport.on_load(:active_record) do
|
27
|
+
ActiveRecord::Base.extend(ActiveRecordProxyAdapters::SQLite3::ConnectionHandling)
|
28
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_record_proxy_adapters/connection_handling/
|
4
|
-
require "active_record_proxy_adapters/connection_handling/
|
5
|
-
require "active_record_proxy_adapters/connection_handling/
|
6
|
-
require "active_record_proxy_adapters/connection_handling/
|
3
|
+
require "active_record_proxy_adapters/connection_handling/postgresql_proxy"
|
4
|
+
require "active_record_proxy_adapters/connection_handling/mysql2_proxy"
|
5
|
+
require "active_record_proxy_adapters/connection_handling/trilogy_proxy"
|
6
|
+
require "active_record_proxy_adapters/connection_handling/sqlite3_proxy"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
require "active_record_proxy_adapters/version"
|
5
|
+
require "active_record_proxy_adapters/active_record_context"
|
6
|
+
require "active_record_proxy_adapters/configuration"
|
7
|
+
require "active_record_proxy_adapters/context"
|
8
|
+
require "active_record_proxy_adapters/contextualizer"
|
9
|
+
require "active_record_proxy_adapters/database_tasks"
|
10
|
+
require "active_record_proxy_adapters/errors"
|
11
|
+
require "active_record_proxy_adapters/hijackable"
|
12
|
+
require "active_record_proxy_adapters/mixin/configuration"
|
13
|
+
require "active_record_proxy_adapters/primary_replica_proxy"
|
@@ -22,22 +22,12 @@ module ActiveRecordProxyAdapters
|
|
22
22
|
|
23
23
|
def database_instance_prefix_for(event)
|
24
24
|
connection = event.payload[:connection]
|
25
|
-
db_config = connection.pool.try(:db_config)
|
25
|
+
db_config = connection.pool.try(:db_config)
|
26
26
|
connection_name = db_config.name
|
27
27
|
|
28
28
|
prefix = log_subscriber_prefix(connection_name)
|
29
29
|
|
30
30
|
"[#{prefix.call(event)}]"
|
31
31
|
end
|
32
|
-
|
33
|
-
class NullConfig # rubocop:disable Style/Documentation
|
34
|
-
def method_missing(...)
|
35
|
-
nil
|
36
|
-
end
|
37
|
-
|
38
|
-
def respond_to_missing?(*)
|
39
|
-
true
|
40
|
-
end
|
41
|
-
end
|
42
32
|
end
|
43
33
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "active_support/core_ext/integer/time"
|
4
4
|
require "active_record_proxy_adapters/synchronizable_configuration"
|
5
5
|
require "active_record_proxy_adapters/cache_configuration"
|
6
|
-
require "active_record_proxy_adapters/context"
|
7
6
|
|
8
7
|
module ActiveRecordProxyAdapters
|
9
8
|
module Mixin
|
@@ -40,6 +39,20 @@ module ActiveRecordProxyAdapters
|
|
40
39
|
proxy_config.context_store
|
41
40
|
end
|
42
41
|
|
42
|
+
# Helper to retrieve the logger from the configuration stored in
|
43
|
+
# {ActiveRecordProxyAdapters::Configuration#logger}.
|
44
|
+
# @return [Logger]
|
45
|
+
def logger
|
46
|
+
proxy_config.logger
|
47
|
+
end
|
48
|
+
|
49
|
+
# Helper to retrieve the timeout strategy from the configuration stored in
|
50
|
+
# {ActiveRecordProxyAdapters::Configuration#regexp_timeout_strategy}.
|
51
|
+
# @return [Proc]
|
52
|
+
def regexp_timeout_strategy
|
53
|
+
proxy_config.regexp_timeout_strategy
|
54
|
+
end
|
55
|
+
|
43
56
|
# Helper to retrieve the cache store from the configuration stored in
|
44
57
|
# {ActiveRecordProxyAdapters::CacheConfiguration#store}.
|
45
58
|
# @return [ActiveSupport::Cache::Store]
|
@@ -7,6 +7,7 @@ require "active_record_proxy_adapters/hijackable"
|
|
7
7
|
require "active_record_proxy_adapters/mixin/configuration"
|
8
8
|
require "active_support/core_ext/module/delegation"
|
9
9
|
require "active_support/core_ext/object/blank"
|
10
|
+
require "timeout"
|
10
11
|
|
11
12
|
module ActiveRecordProxyAdapters
|
12
13
|
# This is the base class for all proxies. It defines the methods that should be proxied
|
@@ -113,8 +114,9 @@ module ActiveRecordProxyAdapters
|
|
113
114
|
end.last
|
114
115
|
end
|
115
116
|
|
116
|
-
def roles_for(sql_string) # rubocop:disable Metrics/MethodLength
|
117
|
-
|
117
|
+
def roles_for(sql_string) # rubocop:disable Metrics/MethodLength
|
118
|
+
top_of_stack_role = top_of_connection_stack_role
|
119
|
+
return [top_of_stack_role] if top_of_stack_role.present?
|
118
120
|
return [writing_role] if recent_write_to_primary? || in_transaction?
|
119
121
|
|
120
122
|
cache_key = cache_key_for(sql_string)
|
@@ -136,17 +138,23 @@ module ActiveRecordProxyAdapters
|
|
136
138
|
return if connected_to_stack.empty?
|
137
139
|
|
138
140
|
top = connected_to_stack.last
|
139
|
-
role = top
|
141
|
+
role, klasses = top.values_at(:role, :klasses)
|
140
142
|
return unless role.present?
|
141
143
|
|
142
|
-
|
144
|
+
# ActiveRecord::Base is the parent record for all models so,
|
145
|
+
# if the top of the stack includes it, we should respect it.
|
146
|
+
role_for_current_class = klasses.include?(connection_class) || klasses.include?(ActiveRecord::Base)
|
147
|
+
|
148
|
+
[reading_role, writing_role].include?(role) && role_for_current_class ? role : nil
|
143
149
|
end
|
144
150
|
|
145
151
|
def connected_to_stack
|
146
152
|
return connection_class.connected_to_stack if connection_class.respond_to?(:connected_to_stack)
|
147
153
|
|
148
154
|
# handle Rails 7.2+ pending migrations Connection
|
149
|
-
|
155
|
+
if pending_migration_connection?
|
156
|
+
return [{ role: writing_role, shard: nil, prevent_writes: false, klasses: [connection_class] }]
|
157
|
+
end
|
150
158
|
|
151
159
|
[]
|
152
160
|
end
|
@@ -181,7 +189,7 @@ module ActiveRecordProxyAdapters
|
|
181
189
|
end
|
182
190
|
|
183
191
|
def checkout_replica_connection
|
184
|
-
replica_pool.checkout(
|
192
|
+
replica_pool.checkout(proxy_checkout_timeout)
|
185
193
|
# rescue NoDatabaseError to avoid crashing when running db:create rake task
|
186
194
|
# rescue ConnectionNotEstablished to handle connectivity issues in the replica
|
187
195
|
# (for example, replication delay)
|
@@ -215,7 +223,14 @@ module ActiveRecordProxyAdapters
|
|
215
223
|
end
|
216
224
|
|
217
225
|
def match_sql?(sql_string)
|
218
|
-
proc
|
226
|
+
proc do |matcher|
|
227
|
+
# TODO: switch to regexp timeout once Ruby 3.1 support is dropped.
|
228
|
+
Timeout.timeout(proxy_checkout_timeout.to_f) { matcher.match?(sql_string) }
|
229
|
+
rescue Timeout::Error
|
230
|
+
regexp_timeout_strategy.call(sql_string, matcher)
|
231
|
+
|
232
|
+
false
|
233
|
+
end
|
219
234
|
end
|
220
235
|
|
221
236
|
# @return Boolean
|
@@ -235,6 +250,10 @@ module ActiveRecordProxyAdapters
|
|
235
250
|
@primary_connection_name ||= primary_connection.pool.try(:db_config).try(:name).try(:to_s)
|
236
251
|
end
|
237
252
|
|
253
|
+
def proxy_checkout_timeout
|
254
|
+
checkout_timeout(primary_connection_name)
|
255
|
+
end
|
256
|
+
|
238
257
|
def proxy_context
|
239
258
|
self.current_context ||= context_store.new({})
|
240
259
|
end
|
@@ -1,24 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support"
|
4
|
+
require "active_record_proxy_adapters/core"
|
5
|
+
require "active_record_proxy_adapters/railties/postgresql"
|
6
|
+
require "active_record_proxy_adapters/railties/mysql2"
|
7
|
+
require "active_record_proxy_adapters/railties/trilogy"
|
8
|
+
require "active_record_proxy_adapters/railties/sqlite3"
|
4
9
|
|
5
10
|
module ActiveRecordProxyAdapters
|
6
11
|
# Hooks into rails boot process to extend ActiveRecord with the proxy adapter.
|
7
12
|
class Railtie < Rails::Railtie
|
8
|
-
require "active_record_proxy_adapters/connection_handling"
|
9
13
|
require "active_record_proxy_adapters/middleware"
|
10
14
|
|
11
|
-
config.to_prepare do
|
12
|
-
Rails.autoloaders.each do |autoloader|
|
13
|
-
autoloader.inflector.inflect(
|
14
|
-
"postgresql_proxy_adapter" => "PostgreSQLProxyAdapter"
|
15
|
-
)
|
16
|
-
autoloader.inflector.inflect(
|
17
|
-
"sqlite3_proxy_adapter" => "SQLite3ProxyAdapter"
|
18
|
-
)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
15
|
initializer "active_record_proxy_adapters.configure_rails_initialization" do |app|
|
23
16
|
app.middleware.use ActiveRecordProxyAdapters::Middleware
|
24
17
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_record_proxy_adapters/core"
|
5
|
+
|
6
|
+
module ActiveRecordProxyAdapters
|
7
|
+
module Railties
|
8
|
+
# Hooks into rails boot process to load the Mysql2 Proxy adapter.
|
9
|
+
class Mysql2Proxy < Rails::Railtie
|
10
|
+
require "active_record_proxy_adapters/connection_handling/mysql2_proxy"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_record_proxy_adapters/core"
|
5
|
+
|
6
|
+
module ActiveRecordProxyAdapters
|
7
|
+
module Railties
|
8
|
+
# Hooks into rails boot process to load the PostgreSQL Proxy adapter.
|
9
|
+
class PostgreSQLProxy < Rails::Railtie
|
10
|
+
require "active_record_proxy_adapters/connection_handling/postgresql_proxy"
|
11
|
+
|
12
|
+
config.to_prepare do
|
13
|
+
Rails.autoloaders.each do |autoloader|
|
14
|
+
autoloader.inflector.inflect(
|
15
|
+
"postgresql_proxy_adapter" => "PostgreSQLProxyAdapter"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_record_proxy_adapters/core"
|
5
|
+
|
6
|
+
module ActiveRecordProxyAdapters
|
7
|
+
module Railties
|
8
|
+
# Hooks into rails boot process to load the SQLite3 Proxy adapter.
|
9
|
+
class SQLite3Proxy < Rails::Railtie
|
10
|
+
require "active_record_proxy_adapters/connection_handling/sqlite3_proxy"
|
11
|
+
|
12
|
+
config.to_prepare do
|
13
|
+
Rails.autoloaders.each do |autoloader|
|
14
|
+
autoloader.inflector.inflect(
|
15
|
+
"sqlite3_proxy_adapter" => "SQLite3ProxyAdapter"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_record_proxy_adapters/core"
|
5
|
+
|
6
|
+
module ActiveRecordProxyAdapters
|
7
|
+
module Railties
|
8
|
+
# Hooks into rails boot process to load the Trilogy Proxy adapter.
|
9
|
+
class TrilogyProxy < Rails::Railtie
|
10
|
+
require "active_record_proxy_adapters/connection_handling/trilogy_proxy"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,26 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_record"
|
4
|
-
require "active_record_proxy_adapters/version"
|
5
|
-
require "active_record_proxy_adapters/configuration"
|
6
|
-
|
7
3
|
# The gem namespace.
|
8
4
|
module ActiveRecordProxyAdapters
|
9
|
-
class Error < StandardError; end
|
10
|
-
|
11
|
-
module_function
|
12
|
-
|
13
|
-
def configure
|
14
|
-
yield(config)
|
15
|
-
end
|
16
|
-
|
17
|
-
def bust_query_cache
|
18
|
-
config.cache.bust
|
19
|
-
end
|
20
|
-
|
21
|
-
def config
|
22
|
-
@config ||= Configuration.new
|
23
|
-
end
|
24
5
|
end
|
25
6
|
|
26
7
|
require_relative "active_record_proxy_adapters/railtie" if defined?(Rails::Railtie)
|
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Cruz
|
@@ -15,7 +15,7 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 7.
|
18
|
+
version: 7.1.0
|
19
19
|
- - "<"
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '8.1'
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 7.
|
28
|
+
version: 7.1.0
|
29
29
|
- - "<"
|
30
30
|
- !ruby/object:Gem::Version
|
31
31
|
version: '8.1'
|
@@ -35,7 +35,7 @@ dependencies:
|
|
35
35
|
requirements:
|
36
36
|
- - ">="
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version: 7.
|
38
|
+
version: 7.1.0
|
39
39
|
- - "<"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '8.1'
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 7.
|
48
|
+
version: 7.1.0
|
49
49
|
- - "<"
|
50
50
|
- !ruby/object:Gem::Version
|
51
51
|
version: '8.1'
|
@@ -77,6 +77,34 @@ dependencies:
|
|
77
77
|
- - ">="
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '0'
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: logger
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: timeout
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
type: :runtime
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
80
108
|
description: |-
|
81
109
|
This gem allows automatic connection switching between a primary and one read replica database in ActiveRecord.
|
82
110
|
It pattern matches the SQL statement being sent to decide whether it should go to the replica (SELECT) or the
|
@@ -104,14 +132,16 @@ files:
|
|
104
132
|
- lib/active_record_proxy_adapters/cache_configuration.rb
|
105
133
|
- lib/active_record_proxy_adapters/configuration.rb
|
106
134
|
- lib/active_record_proxy_adapters/connection_handling.rb
|
107
|
-
- lib/active_record_proxy_adapters/connection_handling/
|
108
|
-
- lib/active_record_proxy_adapters/connection_handling/
|
109
|
-
- lib/active_record_proxy_adapters/connection_handling/
|
110
|
-
- lib/active_record_proxy_adapters/connection_handling/
|
135
|
+
- lib/active_record_proxy_adapters/connection_handling/mysql2_proxy.rb
|
136
|
+
- lib/active_record_proxy_adapters/connection_handling/postgresql_proxy.rb
|
137
|
+
- lib/active_record_proxy_adapters/connection_handling/sqlite3_proxy.rb
|
138
|
+
- lib/active_record_proxy_adapters/connection_handling/trilogy_proxy.rb
|
111
139
|
- lib/active_record_proxy_adapters/context.rb
|
112
140
|
- lib/active_record_proxy_adapters/contextualizer.rb
|
141
|
+
- lib/active_record_proxy_adapters/core.rb
|
113
142
|
- lib/active_record_proxy_adapters/database_configuration.rb
|
114
143
|
- lib/active_record_proxy_adapters/database_tasks.rb
|
144
|
+
- lib/active_record_proxy_adapters/errors.rb
|
115
145
|
- lib/active_record_proxy_adapters/hijackable.rb
|
116
146
|
- lib/active_record_proxy_adapters/log_subscriber.rb
|
117
147
|
- lib/active_record_proxy_adapters/middleware.rb
|
@@ -120,9 +150,12 @@ files:
|
|
120
150
|
- lib/active_record_proxy_adapters/postgresql_proxy.rb
|
121
151
|
- lib/active_record_proxy_adapters/primary_replica_proxy.rb
|
122
152
|
- lib/active_record_proxy_adapters/railtie.rb
|
153
|
+
- lib/active_record_proxy_adapters/railties/mysql2.rb
|
154
|
+
- lib/active_record_proxy_adapters/railties/postgresql.rb
|
155
|
+
- lib/active_record_proxy_adapters/railties/sqlite3.rb
|
156
|
+
- lib/active_record_proxy_adapters/railties/trilogy.rb
|
123
157
|
- lib/active_record_proxy_adapters/sqlite3_proxy.rb
|
124
158
|
- lib/active_record_proxy_adapters/synchronizable_configuration.rb
|
125
|
-
- lib/active_record_proxy_adapters/transactionable_proxy_a_r_70.rb
|
126
159
|
- lib/active_record_proxy_adapters/trilogy_proxy.rb
|
127
160
|
- lib/active_record_proxy_adapters/version.rb
|
128
161
|
homepage: https://github.com/Nasdaq/active_record_proxy_adapters
|
@@ -141,7 +174,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
174
|
requirements:
|
142
175
|
- - ">="
|
143
176
|
- !ruby/object:Gem::Version
|
144
|
-
version: 3.
|
177
|
+
version: 3.2.0
|
145
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
179
|
requirements:
|
147
180
|
- - ">="
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
begin
|
4
|
-
require "active_record/connection_adapters/sqlite3_proxy_adapter"
|
5
|
-
rescue LoadError
|
6
|
-
# sqlite3 not available
|
7
|
-
return
|
8
|
-
end
|
9
|
-
|
10
|
-
module ActiveRecordProxyAdapters
|
11
|
-
module SQLite3
|
12
|
-
# Module to extend ActiveRecord::Base with the connection handling methods.
|
13
|
-
# Required to make adapter work in ActiveRecord versions <= 7.2.x
|
14
|
-
module ConnectionHandling
|
15
|
-
def sqlite3_proxy_adapter_class
|
16
|
-
ActiveRecord::ConnectionAdapters::SQLite3ProxyAdapter
|
17
|
-
end
|
18
|
-
|
19
|
-
def sqlite3_proxy_connection(config)
|
20
|
-
connection_factory_mapping
|
21
|
-
.fetch("#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}")
|
22
|
-
.call(config)
|
23
|
-
end
|
24
|
-
|
25
|
-
def connection_factory_mapping
|
26
|
-
{
|
27
|
-
"7.0" => ->(config) { sqlite3_proxy_connection_ar_v70(config) },
|
28
|
-
"7.1" => ->(config) { sqlite3_proxy_connection_ar_v71(config) }
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def sqlite3_proxy_connection_ar_v70(config) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
33
|
-
config = config.symbolize_keys
|
34
|
-
|
35
|
-
# Require database.
|
36
|
-
raise ArgumentError, "No database file specified. Missing argument: database" unless config[:database]
|
37
|
-
|
38
|
-
# Allow database path relative to Rails.root, but only if the database
|
39
|
-
# path is not the special path that tells sqlite to build a database only
|
40
|
-
# in memory.
|
41
|
-
if ":memory:" != config[:database] && !config[:database].to_s.start_with?("file:") # rubocop:disable Style/YodaCondition
|
42
|
-
config[:database] = File.expand_path(config[:database], Rails.root) if defined?(Rails.root)
|
43
|
-
dirname = File.dirname(config[:database])
|
44
|
-
Dir.mkdir(dirname) unless File.directory?(dirname)
|
45
|
-
end
|
46
|
-
|
47
|
-
db = ::SQLite3::Database.new(
|
48
|
-
config[:database].to_s,
|
49
|
-
config.merge(results_as_hash: true)
|
50
|
-
)
|
51
|
-
|
52
|
-
sqlite3_proxy_adapter_class.new(db, logger, nil, config)
|
53
|
-
rescue Errno::ENOENT => e
|
54
|
-
raise ActiveRecord::NoDatabaseError if e.message.include?("No such file or directory")
|
55
|
-
|
56
|
-
raise
|
57
|
-
end
|
58
|
-
|
59
|
-
def sqlite3_proxy_connection_ar_v71(config)
|
60
|
-
sqlite3_proxy_adapter_class.new(config)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
ActiveSupport.on_load(:active_record) do
|
67
|
-
ActiveRecord::Base.extend(ActiveRecordProxyAdapters::SQLite3::ConnectionHandling)
|
68
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecordProxyAdapters
|
4
|
-
module TransactionableProxyAR70 # rubocop:disable Style/Documentation
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
def begin_db_transaction # :nodoc:
|
9
|
-
bypass_proxy_or_else("BEGIN", "TRANSACTION") { super }
|
10
|
-
end
|
11
|
-
|
12
|
-
def commit_db_transaction # :nodoc:
|
13
|
-
bypass_proxy_or_else("COMMIT", "TRANSACTION") { super }
|
14
|
-
end
|
15
|
-
|
16
|
-
def exec_rollback_db_transaction # :nodoc:
|
17
|
-
bypass_proxy_or_else("ROLLBACK", "TRANSACTION") { super }
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def bypass_proxy_or_else(*args)
|
23
|
-
method_name = proxy_method_name_for(:execute)
|
24
|
-
|
25
|
-
return public_send(method_name, *args) if respond_to?(method_name)
|
26
|
-
|
27
|
-
yield
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
File without changes
|
/data/lib/active_record_proxy_adapters/connection_handling/{postgresql.rb → postgresql_proxy.rb}
RENAMED
File without changes
|
File without changes
|