aws_advanced_ruby_driver_wrapper 1.0.0 → 1.0.1

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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb +40 -0
  4. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb +47 -0
  5. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +23 -9
  6. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +51 -10
  7. data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +61 -0
  8. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +5 -0
  9. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +10 -0
  10. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +10 -0
  11. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +10 -0
  12. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +14 -0
  13. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +6 -0
  14. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +10 -0
  15. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +4 -0
  16. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +5 -0
  17. data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +9 -1
  18. data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +8 -0
  19. data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +22 -3
  20. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +18 -7
  21. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +20 -3
  22. data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
  23. data/lib/aws_advanced_ruby_driver_wrapper.rb +38 -0
  24. metadata +5 -3
  25. data/lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ab8433b9c38b4c70ea438830ccc3d870bdd56141e5be9ad28e309aad7852074
4
- data.tar.gz: bfc31bb5bbd87b1a3bb2ee416cc0208b79bd15c9e92422266822cc5a0904b0f5
3
+ metadata.gz: 6da8d07797b41d2bef7c26ac10bff8a3fcf6050d098344d3e850cf80d88305a9
4
+ data.tar.gz: 2f17adb4cca840143bacbf16056d67748f12204f22a5beb71ddb8bdc445aca3e
5
5
  SHA512:
6
- metadata.gz: f321a9d2942e5cef6eada081baa62f5cedc42b906b8f991ab42bb9ee55bd6323381b0aa781090427e1f4d9b5a1c6ac9d2e32aadf0e2d4dfd476dc57ef34217d1
7
- data.tar.gz: d6125a87b85478e47d4f851ff7c9d7a0a6aa6a14806575e6b77df86bff38f458c516497bc3c458abd0ccc66937fb1de1f77164d64c324bed60ee1786f7e7035d
6
+ metadata.gz: dc3f77408c42d2a2dde71cce86af1c0bb294380b6e7c679c51118e0fd2383f4d677e95d77521cbe974bf3c584e5f7af7b65244834a0489034d7ab9541982dcc6
7
+ data.tar.gz: fcfaa69564b9abfeed8095e5995a9893a636def8ea0f8c1ad471bbcf69a0f36f7593090b42f76083556c7ee834350238bc73c8e090408572ccf78b8a01ee858f
data/CHANGELOG.md CHANGED
@@ -3,7 +3,22 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/#semantic-versioning-200).
5
5
 
6
- ## [1.0.0] - 2026-10-02
6
+ ## [1.0.1] - 2026-10-07
7
+
8
+ ### :bug: Fixed
9
+ - Fixed the `aws_postgresql` ActiveRecord adapter passing ActiveRecord-only `database.yml` keys, such as the Rails 8.1 pool settings (`max_connections`, `min_connections`, `keepalive`, `max_age`) and multi-database settings (`replica`, `migrations_paths`, `database_tasks`), to `pg`, which rejected them with `PG::Error: invalid connection option` ([PR #191](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/191)).
10
+ - Fixed the `aws_mysql2` ActiveRecord adapter dropping the `flags`, `encoding`, `socket`, and `reconnect` client options, which removed ActiveRecord's `FOUND_ROWS` flag so that statements such as `update_all` reported changed rows instead of matched rows ([PR #193](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/193)).
11
+ - Fixed the `aws_postgresql` and `aws_mysql2` ActiveRecord adapters not translating connection errors the way the standard adapters do, so a missing database was not reported as `ActiveRecord::NoDatabaseError` and `db:prepare` (and `bin/setup`) failed instead of creating it ([PR #193](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/193)).
12
+ - Fixed the `aws_postgresql` and `aws_mysql2` ActiveRecord adapters keeping ActiveRecord's prepared statement cache after a successful failover, so every query prepared before the failover failed on that connection with `Method invoked against old connection` until the process restarted ([PR #194](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/194), [documentation](https://aws.github.io/aws-advanced-wrapper-docs/ruby/enhanced-failover)).
13
+ - Fixed `db:drop`, `db:reset`, and `db:test:prepare` failing on Aurora PostgreSQL with `database "<name>" is being accessed by other users`. The same error occurred when running `bin/rails test` after a schema change. The cause was the wrapper's topology and Blue/Green monitors, which kept their own connections open to the database being dropped. The wrapper now stops these monitors before dropping a database and when ActiveRecord clears all its connections ([PR #195](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/195)).
14
+ - Fixed forked processes, such as Puma workers with `preload_app!`, Unicorn workers, and Resque jobs, inheriting the parent's background monitors after their threads had stopped, so the cluster topology never refreshed in the child and failover there could not find the new writer. A forked child now starts its own monitors and leaves the parent's monitoring connections open. A forked child also no longer waits on a Secrets Manager fetch that was in progress in the parent when it forked ([PR #196](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/196)).
15
+ - Fixed the AWS Secrets Manager plugin not reporting a timed-out secret fetch as a timeout. A fetch that did not finish within 60 seconds failed with a generic `SecretsManagerAuthError` (`Failed to fetch database credentials from AWS Secrets Manager`) instead of `Timed out fetching secret after 60s` ([PR #196](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/196)).
16
+ - Fixed Action Cable's PostgreSQL subscription adapter (`adapter: postgresql` in `cable.yml`) refusing to run on the `aws_postgresql` ActiveRecord adapter with `The Active Record database must be PostgreSQL in order to use the PostgreSQL Action Cable storage adapter`, which also stopped Turbo Stream broadcasts ([PR #197](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/197)).
17
+ - Fixed the `aws_postgresql` and `aws_mysql2` ActiveRecord adapters raising `Unknown type` for adapter-specific attribute types and columns. ActiveRecord keys its type registry by the connection's adapter name, and the wrapped adapters registered none of their own, so types such as PostgreSQL `:interval`, `:point`, `:uuid`, array, and range, and MySQL `:unsigned_integer`, could not be resolved. The wrapped adapter names are now aliased to the underlying `postgresql` and `mysql2` adapters for type registration and lookup, so the wrapped adapters resolve the same types as the standard adapters ([PR #200](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/200)).
18
+ - **Side effect:** in an application that uses both a standard (`postgresql`/`mysql2`) connection and a wrapped (`aws_postgresql`/`aws_mysql2`) connection, a type registered for one is now shared with the other, because both resolve under the same underlying adapter key.
19
+ - Changed the `aws_postgresql` and `aws_mysql2` ActiveRecord adapters to report the underlying `adapter_name` (`"PostgreSQL"` and `"Mysql2"`) instead of `"AwsPostgreSQL"` and `"AwsMySQL2"`. ActiveRecord's migration compatibility layer gates PostgreSQL- and MySQL-specific behavior on `connection.adapter_name` string comparisons. Legacy versioned migrations (`ActiveRecord::Migration[5.0]` through `[7.0]`) now complete as expected ([PR #200](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/200)).
20
+
21
+ ## [1.0.0] - 2026-10-05
7
22
 
8
23
  The Amazon Web Services (AWS) Advanced Ruby Driver Wrapper allows an application to take advantage of the features of clustered Aurora databases.
9
24
 
@@ -20,4 +35,5 @@ The Amazon Web Services (AWS) Advanced Ruby Driver Wrapper allows an application
20
35
  - [Initial Connection Strategy Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/initial-connection-strategy).
21
36
  - [KMS Encryption Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/kms-encryption).
22
37
 
38
+ [1.0.1]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/1.0.1
23
39
  [1.0.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/1.0.0
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative '../postgresql'
18
+
19
+ module ActiveRecord
20
+ module ConnectionAdapters
21
+ # Lets Action Cable's PostgreSQL subscription adapter (cable.yml `adapter: postgresql`) run on the
22
+ # aws_postgresql adapter. Action Cable refuses any raw connection that is not a PG::Connection, and
23
+ # aws_postgresql hands out a WrapperPgConnection, which forwards the calls Action Cable makes
24
+ # (exec, escape_identifier, escape_string, wait_for_notify) to the PG::Connection it wraps.
25
+ module AwsActionCablePostgreSQLSupport
26
+ private
27
+
28
+ def verify!(pg_conn)
29
+ super unless pg_conn.is_a?(AwsAdvancedRubyDriverWrapper::WrapperPgConnection)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # Action Cable runs this hook when its server loads, before it loads a subscription adapter, so the
36
+ # PostgreSQL one is loaded here to patch it. Applications without Action Cable never run the hook.
37
+ ActiveSupport.on_load(:action_cable) do
38
+ require 'action_cable/subscription_adapter/postgresql'
39
+ ActionCable::SubscriptionAdapter::PostgreSQL.prepend(ActiveRecord::ConnectionAdapters::AwsActionCablePostgreSQLSupport)
40
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_record'
18
+ require_relative '../services/service_utility'
19
+ require_relative '../host/rds_host_list_provider'
20
+ require_relative '../plugins/blue_green/blue_green_plugin'
21
+
22
+ module ActiveRecord
23
+ module ConnectionAdapters
24
+ # Stops the wrapper's background monitors and Blue/Green status providers when ActiveRecord closes every
25
+ # connection pool, and forgets the state they cached, so that the next connection starts new ones straight away.
26
+ #
27
+ # The monitors keep their own connections to the database, outside ActiveRecord's pools. Closing
28
+ # everything is what ActiveRecord does before another process takes over the database, for example
29
+ # when bin/rails test runs db:test:prepare in a child process to drop and reload the test database,
30
+ # and PostgreSQL refuses to drop a database that a monitor is still connected to. The next
31
+ # connection that needs a monitor starts a new one.
32
+ module AwsConnectionHandler
33
+ def clear_all_connections!(...)
34
+ super
35
+ core = AwsAdvancedRubyDriverWrapper::Services::CoreServices
36
+ core.monitor_service.stop_and_remove_all
37
+ AwsAdvancedRubyDriverWrapper::Plugins::BlueGreen::BlueGreenPlugin.clean_up_providers
38
+ # Without this, connections would keep reading cached state that nothing refreshes any more.
39
+ cached = [AwsAdvancedRubyDriverWrapper::Host::RdsHostListProvider::TOPOLOGY_CACHE_NAME,
40
+ AwsAdvancedRubyDriverWrapper::Plugins::BlueGreen::BlueGreenPlugin::BLUE_GREEN_NAME]
41
+ cached.each { |name| core.storage_service.clear(name) if core.storage_service.registered?(name) }
42
+ end
43
+ end
44
+
45
+ ConnectionHandler.prepend(AwsConnectionHandler)
46
+ end
47
+ end
@@ -17,20 +17,31 @@
17
17
  require 'active_record/connection_adapters/mysql2_adapter'
18
18
  require_relative '../mysql'
19
19
  require_relative '../errors'
20
- require_relative '../utils/ar_constants'
20
+ require_relative 'type_adapter_alias'
21
+ require_relative 'aws_connection_handler'
21
22
 
22
23
  module ActiveRecord
23
24
  module ConnectionAdapters
24
25
  class AwsMysql2Adapter < Mysql2Adapter
25
- ADAPTER_NAME = 'AwsMySQL2'
26
-
27
- # ActiveRecord-only keys that should not be passed to the wrapper or native driver.
28
- AR_ONLY_KEYS = AwsAdvancedRubyDriverWrapper::Utils::AR_COMMON_KEYS
29
-
30
- def adapter_name = ADAPTER_NAME
31
-
26
+ # Passes the whole config on, as the parent adapter does: the wrapper takes its own properties out,
27
+ # and mysql2 reads the client options it knows (including the FOUND_ROWS flag the parent adds) and
28
+ # ignores the ActiveRecord-only keys.
29
+ #
30
+ # Translates connection errors the same way the parent adapter does, so ActiveRecord can tell a
31
+ # missing database (which db:prepare creates) or rejected credentials from other failures.
32
32
  def self.new_client(config)
33
- AwsAdvancedRubyDriverWrapper::WrapperMysql2Client.new(**config.except(*AR_ONLY_KEYS))
33
+ AwsAdvancedRubyDriverWrapper::WrapperMysql2Client.new(**config)
34
+ rescue ::Mysql2::Error => e
35
+ case e.error_number
36
+ when ER_BAD_DB_ERROR
37
+ raise ActiveRecord::NoDatabaseError.db_error(config[:database])
38
+ when ER_DBACCESS_DENIED_ERROR, ER_ACCESS_DENIED_ERROR
39
+ raise ActiveRecord::DatabaseConnectionError.username_error(config[:username])
40
+ when ER_CONN_HOST_ERROR, ER_UNKNOWN_HOST_ERROR
41
+ raise ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
42
+ else
43
+ raise ActiveRecord::ConnectionNotEstablished, e.message
44
+ end
34
45
  end
35
46
 
36
47
  def connect
@@ -53,6 +64,9 @@ module ActiveRecord
53
64
  return super unless exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::AwsError)
54
65
 
55
66
  if exception.needs_reconfiguration
67
+ # The wrapper has reconnected this connection object to a new physical connection, where the
68
+ # statements prepared on the old one do not exist. Forget them so they are prepared again.
69
+ clear_cache!(new_connection: true)
56
70
  configure_connection
57
71
  exception
58
72
  elsif exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::FailoverFailedError)
@@ -17,39 +17,67 @@
17
17
  require 'active_record/connection_adapters/postgresql_adapter'
18
18
  require_relative '../postgresql'
19
19
  require_relative '../errors'
20
- require_relative '../utils/ar_constants'
20
+ require_relative 'type_adapter_alias'
21
+ require_relative 'aws_connection_handler'
22
+ require_relative 'aws_action_cable_postgresql_support'
21
23
 
22
24
  module ActiveRecord
23
25
  module ConnectionAdapters
24
26
  class AwsPostgreSQLAdapter < PostgreSQLAdapter
25
- ADAPTER_NAME = 'AwsPostgreSQL'
26
-
27
- # ActiveRecord-only keys that should not be passed to the wrapper or native driver.
28
- AR_ONLY_KEYS = (AwsAdvancedRubyDriverWrapper::Utils::AR_COMMON_KEYS + %i[advisory_locks schema_search_path]).freeze
29
-
30
27
  # ActiveRecord uses :username and :database, but the PG gem expects :user and :dbname.
31
28
  # The parent adapter translates these in @connection_parameters, but also strips
32
29
  # non-PG keys (including wrapper properties) via slice!. Since we rebuild from @config
33
30
  # to preserve wrapper properties, we need to redo this translation ourselves.
34
31
  AR_TO_PG_KEY_MAP = { username: :user, database: :dbname }.freeze
35
32
 
33
+ # The connection options PG accepts, the same set the parent adapter forwards.
34
+ PG_CONNECTION_KEYS = (PG::Connection.conndefaults_hash.keys + [:requiressl]).to_set.freeze
35
+
36
36
  def initialize(...)
37
37
  # Capture the full config before the parent's initialize strips it
38
38
  # down to only PG-recognized keys in @connection_parameters.
39
39
  super
40
40
  @connection_broken = false
41
- # Store non-AR parameters in @wrapper_config.
42
- wrapper_config = @config.compact.except(*AR_ONLY_KEYS)
41
+ wrapper_config = @config.compact
43
42
  # Remap ActiveRecord key names to PG gem key names.
44
43
  AR_TO_PG_KEY_MAP.each { |ar_key, pg_key| wrapper_config[pg_key] = wrapper_config.delete(ar_key) if wrapper_config.key?(ar_key) }
45
- @wrapper_config = wrapper_config
44
+ # Keep only what PG or the wrapper understands. Every other key is an ActiveRecord setting,
45
+ # and PG rejects any connection option it does not recognize.
46
+ @wrapper_config = wrapper_config.select { |key, _| self.class.forwarded_key?(key) }
47
+ end
48
+
49
+ # @return [Boolean] whether the config key is passed on to the wrapper connection
50
+ def self.forwarded_key?(key)
51
+ PG_CONNECTION_KEYS.include?(key) ||
52
+ AwsAdvancedRubyDriverWrapper::PropertyDefinition.wrapper_property?(key) ||
53
+ AwsAdvancedRubyDriverWrapper::PropertyDefinition::KNOWN_PREFIXES.any? { |prefix| key.to_s.start_with?(prefix) }
46
54
  end
47
55
 
48
- def adapter_name = ADAPTER_NAME
56
+ # Resolve native database types from the wrapped PostgreSQLAdapter, overriding only :datetime.
57
+ # PostgreSQLAdapter builds its type hash from two things: the shared NATIVE_DATABASE_TYPES
58
+ # constant and the per-class datetime_type class_attribute. Delegating to the parent keeps a
59
+ # single source of truth, but the parent reads *its own* datetime_type, so this adapter's
60
+ # datetime_type (e.g. :timestamptz) must be re-applied here or it is silently ignored and
61
+ # t.datetime columns are created as plain timestamp.
62
+ def self.native_database_types
63
+ superclass.native_database_types.merge(datetime: NATIVE_DATABASE_TYPES[datetime_type])
64
+ end
49
65
 
50
66
  # Note that this config includes wrapper properties.
67
+ #
68
+ # Translates connection errors the same way the parent adapter does, so ActiveRecord can tell a
69
+ # missing database (which db:prepare creates) or rejected credentials from other failures.
51
70
  def self.new_client(config)
52
71
  AwsAdvancedRubyDriverWrapper::WrapperPgConnection.new(**config)
72
+ rescue ::PG::Error => e
73
+ dbname, user, host = config.values_at(:dbname, :user, :host)
74
+ # The postgres maintenance database always exists, so a failure there is not a missing database.
75
+ raise ActiveRecord::ConnectionNotEstablished, e.message if dbname == 'postgres'
76
+ raise ActiveRecord::NoDatabaseError.db_error(dbname) if dbname && e.message.include?(dbname)
77
+ raise ActiveRecord::DatabaseConnectionError.username_error(user) if user && e.message.include?(user)
78
+ raise ActiveRecord::DatabaseConnectionError.hostname_error(host) if host && e.message.include?(host)
79
+
80
+ raise ActiveRecord::ConnectionNotEstablished, e.message
53
81
  end
54
82
 
55
83
  def connect
@@ -71,10 +99,23 @@ module ActiveRecord
71
99
  super
72
100
  end
73
101
 
102
+ # Used by db:drop, db:reset, db:test:prepare and db:purge. ActiveRecord disconnects its own
103
+ # connections first, but the topology monitor shared by this cluster's connections, and the Blue/Green
104
+ # status providers, keep their own connections to the database, and PostgreSQL refuses to drop a
105
+ # database other sessions are using.
106
+ def drop_database(name)
107
+ raw_connection.stop_topology_monitor
108
+ AwsAdvancedRubyDriverWrapper::Plugins::BlueGreen::BlueGreenPlugin.clean_up_providers
109
+ super
110
+ end
111
+
74
112
  def translate_exception(exception, message:, sql:, binds:)
75
113
  return super unless exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::AwsError)
76
114
 
77
115
  if exception.needs_reconfiguration
116
+ # The wrapper has reconnected this connection object to a new physical connection, where the
117
+ # statements prepared on the old one do not exist. Forget them so they are prepared again.
118
+ clear_cache!(new_connection: true)
78
119
  configure_connection
79
120
  exception
80
121
  elsif exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::FailoverFailedError)
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_record'
18
+
19
+ module AwsAdvancedRubyDriverWrapper
20
+ # ActiveRecord's adapter-specific type registry (ActiveRecord::Type) keys every type
21
+ # registration and lookup by the *config adapter name*. The wrapped adapters register nothing of
22
+ # their own: they rely entirely on the vanilla PostgreSQL/Mysql2 adapters, which register their
23
+ # OID / native types under adapter: :postgresql and adapter: :mysql2. A lookup for an
24
+ # :aws_postgresql / :aws_mysql2 connection would therefore find none of them and raise
25
+ # "Unknown type" for things like :interval, :point, array/range columns, or MySQL's
26
+ # :unsigned_integer.
27
+ #
28
+ # Rather than copy the parent's registrations (which misses types registered after the adapter
29
+ # loads, needs a duplicate guard, and reaches into the registry's private internals), alias the
30
+ # wrapper adapter names to their parents inside the registry's own register/add_modifier/lookup.
31
+ # Every registration and every lookup — including the ones ActiveRecord routes through
32
+ # Type.adapter_name_from — passes through the registry, so normalizing the adapter there makes the
33
+ # wrapped adapters resolve the exact same types as the vanilla ones, for all current and future
34
+ # types, across Rails 7.2–8.1.
35
+ #
36
+ # Side effect: in an app that uses BOTH a plain postgresql and an aws_postgresql connection, a
37
+ # type explicitly registered for :aws_postgresql is normalized to :postgresql and so also applies
38
+ # to the plain postgresql connections (and vice versa). This is documented in the CHANGELOG.
39
+ module TypeAdapterAlias
40
+ ADAPTER_ALIASES = { aws_postgresql: :postgresql, aws_mysql2: :mysql2 }.freeze
41
+
42
+ # Prepended onto ActiveRecord::Type::AdapterSpecificRegistry. Normalizing the adapter in lookup
43
+ # covers both the framework path and a direct Type.lookup(..., adapter: :aws_postgresql); any
44
+ # type registered explicitly for a wrapper adapter lands under the parent's key.
45
+ module RegistryAlias
46
+ def register(type_name, klass = nil, adapter: nil, **, &)
47
+ super(type_name, klass, adapter: ADAPTER_ALIASES.fetch(adapter, adapter), **, &)
48
+ end
49
+
50
+ def add_modifier(options, klass, adapter: nil, **args)
51
+ super(options, klass, adapter: ADAPTER_ALIASES.fetch(adapter, adapter), **args)
52
+ end
53
+
54
+ def lookup(symbol, *, adapter: nil, **)
55
+ super(symbol, *, adapter: ADAPTER_ALIASES.fetch(adapter, adapter), **)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ ActiveRecord::Type::AdapterSpecificRegistry.prepend(AwsAdvancedRubyDriverWrapper::TypeAdapterAlias::RegistryAlias)
@@ -115,6 +115,11 @@ module AwsAdvancedRubyDriverWrapper
115
115
  raise NotImplementedError
116
116
  end
117
117
 
118
+ # Releases a connection inherited from the parent process after a fork, without telling the
119
+ # server: the parent still owns the session. Garbage collection or process exit in the child
120
+ # must not end it.
121
+ def abandon_connection(connection); end
122
+
118
123
  def sql_state(_exception)
119
124
  nil
120
125
  end
@@ -131,6 +131,16 @@ module AwsAdvancedRubyDriverWrapper
131
131
  logger.error("Failed to close MySQL connection: #{e.message}")
132
132
  end
133
133
 
134
+ # With automatic_close off, mysql2 invalidates the socket instead of sending COM_QUIT when
135
+ # the client is collected, leaving the parent's session open.
136
+ def abandon_connection(connection)
137
+ return if connection.nil? || connection.closed?
138
+
139
+ connection.automatic_close = false
140
+ rescue StandardError => e
141
+ logger.debug("Failed to abandon MySQL connection: #{e.message}")
142
+ end
143
+
134
144
  def sql_state(exception)
135
145
  return nil unless exception.respond_to?(:sql_state)
136
146
 
@@ -162,6 +162,16 @@ module AwsAdvancedRubyDriverWrapper
162
162
  logger.error("Failed to close PostgreSQL connection: #{e.message}")
163
163
  end
164
164
 
165
+ # Points the socket at /dev/null, so the Terminate message libpq sends when the connection
166
+ # is finished or collected never reaches the server.
167
+ def abandon_connection(connection)
168
+ return if connection.nil? || connection.finished?
169
+
170
+ connection.socket_io.reopen(IO::NULL)
171
+ rescue StandardError => e
172
+ logger.debug("Failed to abandon PostgreSQL connection: #{e.message}")
173
+ end
174
+
165
175
  def sql_state(exception)
166
176
  return nil unless exception.is_a?(::PG::Error) && exception.result
167
177
 
@@ -131,6 +131,16 @@ module AwsAdvancedRubyDriverWrapper
131
131
  @instance_monitors_writer_conn.close
132
132
  end
133
133
 
134
+ def abandon_connections
135
+ @monitoring_connection.abandon
136
+ @instance_monitors_writer_conn.abandon
137
+ driver_dialect = @service_container.dialect_service.driver_dialect
138
+ @instance_monitor_connections.each_pair do |host, conn|
139
+ driver_dialect.abandon_connection(conn)
140
+ @instance_monitor_connections.delete(host)
141
+ end
142
+ end
143
+
134
144
  private
135
145
 
136
146
  # Main monitoring loop.
@@ -73,6 +73,20 @@ module AwsAdvancedRubyDriverWrapper
73
73
 
74
74
  def close; end
75
75
 
76
+ # Detaches this monitor in a forked child. Its thread did not survive the fork and its
77
+ # connections still belong to the parent, so the thread reference is dropped and the
78
+ # connections are abandoned rather than closed: closing them would end the parent's sessions.
79
+ def release_after_fork
80
+ @stop_flag.make_true
81
+ @thread = nil
82
+ @state.set(MonitorState::STOPPED)
83
+ abandon_connections
84
+ end
85
+
86
+ # Releases connections inherited from the parent process without closing them on the server.
87
+ # Subclasses that hold connections override this.
88
+ def abandon_connections; end
89
+
76
90
  private
77
91
 
78
92
  def run
@@ -52,6 +52,12 @@ module AwsAdvancedRubyDriverWrapper
52
52
  def close
53
53
  set(nil)
54
54
  end
55
+
56
+ # Releases a connection inherited across a fork without closing it on the server. The reference
57
+ # is dropped too, so a later close or set cannot reach the parent's session.
58
+ def abandon
59
+ @driver_dialect.abandon_connection(@connection.get_and_set(nil))
60
+ end
55
61
  end
56
62
  end
57
63
  end
@@ -130,6 +130,16 @@ module AwsAdvancedRubyDriverWrapper
130
130
  PROVIDERS.each_key { |k| PROVIDERS.delete(k)&.stop }
131
131
  end
132
132
 
133
+ # Forgets the providers inherited by a forked child so the child starts its own on first use.
134
+ # A provider that fails to release is still forgotten, and the rest are released.
135
+ def self.release_providers_after_fork
136
+ PROVIDERS.each_key do |key|
137
+ PROVIDERS.delete(key)&.release_after_fork
138
+ rescue StandardError => e
139
+ AwsAdvancedRubyDriverWrapper.logger.warn("Failed to release Blue/Green status provider #{key} after fork: #{e.message}")
140
+ end
141
+ end
142
+
133
143
  private
134
144
 
135
145
  def route_connect(host_info, driver_props, is_initial_connection, pipeline_callable, is_internal: false)
@@ -338,6 +338,10 @@ module AwsAdvancedRubyDriverWrapper
338
338
  @event.reset
339
339
  end
340
340
 
341
+ def abandon_connections
342
+ @connection.abandon
343
+ end
344
+
341
345
  private
342
346
 
343
347
  def attempt_open_connection
@@ -93,6 +93,11 @@ module AwsAdvancedRubyDriverWrapper
93
93
  @monitors.each_value { |m| m&.stop }
94
94
  end
95
95
 
96
+ # Detaches the monitors inherited by a forked child without closing the parent's connections.
97
+ def release_after_fork
98
+ @monitors.each_value { |m| m&.release_after_fork }
99
+ end
100
+
96
101
  def log_switchover_final_summary
97
102
  return unless switchover_finalized?
98
103
 
@@ -79,6 +79,12 @@ module AwsAdvancedRubyDriverWrapper
79
79
  storage_service.clear(SECRETS_MANAGER_CACHE_NAME)
80
80
  end
81
81
 
82
+ # Forgets fetches inherited by a forked child. A fetch running at fork time lost its thread,
83
+ # so its future never resolves and would otherwise be returned to every later fetch for its key.
84
+ def release_pending_refreshes_after_fork
85
+ @pending_refreshes.clear
86
+ end
87
+
82
88
  # The secret's value depends on which secret is read, from which region and endpoint, and
83
89
  # with which AWS credentials, so all of them are part of the key. Connections that differ in
84
90
  # any of them neither share a cached secret nor wait on each other's fetch.
@@ -244,7 +250,9 @@ module AwsAdvancedRubyDriverWrapper
244
250
  else
245
251
  Concurrent::Promises.future_on(:io) { fetch_and_store_secret(nil, credentials) }
246
252
  end
247
- future.value!(SYNC_FETCH_TIMEOUT_SEC)
253
+ # value! returns nil instead of raising when the timeout elapses; a completed fetch always
254
+ # returns an entry or raises.
255
+ future.value!(SYNC_FETCH_TIMEOUT_SEC) || raise(Timeout::Error)
248
256
  rescue Concurrent::CancelledOperationError, Timeout::Error
249
257
  raise Errors::SecretsManagerAuthError,
250
258
  "Timed out fetching secret after #{SYNC_FETCH_TIMEOUT_SEC}s"
@@ -224,6 +224,14 @@ module AwsAdvancedRubyDriverWrapper
224
224
 
225
225
  alias finish close
226
226
 
227
+ # Stops the background topology monitor of this connection's cluster, which closes the connections it
228
+ # holds to the database it was started for. The next connection that needs topology starts a new one.
229
+ # PostgreSQL refuses to drop a database that other sessions are connected to, so this has to happen
230
+ # before dropping the database the monitor was started for.
231
+ def stop_topology_monitor
232
+ @service_container.host_service.host_list_provider&.stop_monitor
233
+ end
234
+
227
235
  # Resets the connection through the pipeline and returns this wrapper, so the reset connection stays
228
236
  # usable through it. The driver's own reset tears down and re-establishes the underlying socket, which
229
237
  # clears any server-side session state, so the tracked session state is reset to match.
@@ -14,6 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'concurrent'
17
18
  require_relative '../monitoring/monitor_state'
18
19
  require_relative '../logging'
19
20
  require_relative '../utils/storage/sliding_expiration_cache'
@@ -36,7 +37,7 @@ module AwsAdvancedRubyDriverWrapper
36
37
  def initialize(event_publisher:)
37
38
  @caches = {}
38
39
  @lock = Mutex.new
39
- @running = true
40
+ @running = Concurrent::AtomicBoolean.new(true)
40
41
  @cleanup_thread = start_cleanup_thread
41
42
  event_publisher.subscribe(
42
43
  self,
@@ -112,7 +113,7 @@ module AwsAdvancedRubyDriverWrapper
112
113
  end
113
114
 
114
115
  def shutdown(grace_period:)
115
- @running = false
116
+ @running.make_false
116
117
  begin
117
118
  @cleanup_thread&.wakeup
118
119
  rescue ThreadError
@@ -122,6 +123,24 @@ module AwsAdvancedRubyDriverWrapper
122
123
  stop_and_remove_all
123
124
  end
124
125
 
126
+ # Resets this service in a forked child. Monitor threads do not survive a fork, so the inherited
127
+ # monitors are detached (keeping the parent's connections open) and forgotten, letting
128
+ # run_if_absent start live ones. A monitor that fails to detach is still forgotten. The cleanup
129
+ # thread is restarted unless it is still alive, so calling this again does not start a second one.
130
+ def restart_after_fork
131
+ @lock.synchronize { @caches.values }.each do |container|
132
+ container.cache.entries.each_key do |key|
133
+ container.cache.remove(key)&.release_after_fork
134
+ rescue StandardError => e
135
+ logger.warn("Failed to release monitor #{key} after fork: #{e.message}")
136
+ end
137
+ end
138
+ return if @cleanup_thread&.alive?
139
+
140
+ @running.make_true
141
+ @cleanup_thread = start_cleanup_thread
142
+ end
143
+
125
144
  # Processes events from the event publisher.
126
145
  # @param event [Event] the event to process.
127
146
  def process_event(event)
@@ -142,7 +161,7 @@ module AwsAdvancedRubyDriverWrapper
142
161
 
143
162
  def start_cleanup_thread
144
163
  thread = Thread.new do
145
- while @running
164
+ while @running.true?
146
165
  sleep(CLEANUP_INTERVAL_SEC)
147
166
  run_cleanup
148
167
  end
@@ -14,6 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'concurrent'
17
18
  require_relative '../../logging'
18
19
 
19
20
  module AwsAdvancedRubyDriverWrapper
@@ -23,10 +24,11 @@ module AwsAdvancedRubyDriverWrapper
23
24
  # Batches deduplicate events via Set semantics (eql?/hash).
24
25
  #
25
26
  # Public API:
26
- # subscribe(subscriber, event_classes) — register for event types
27
- # unsubscribe(subscriber, event_classes) — deregister
28
- # publish(event) — deliver immediate or queue batched
29
- # release_resources — stop background thread
27
+ # subscribe(subscriber, event_classes) - register for event types
28
+ # unsubscribe(subscriber, event_classes) - deregister
29
+ # publish(event) - deliver immediate or queue batched
30
+ # release_resources - stop background thread
31
+ # restart_after_fork - restart background thread in a forked child
30
32
  class BatchingEventPublisher
31
33
  include Logging
32
34
 
@@ -37,7 +39,7 @@ module AwsAdvancedRubyDriverWrapper
37
39
  @subscribers = {}
38
40
  @event_queue = Set.new
39
41
  @lock = Mutex.new
40
- @running = true
42
+ @running = Concurrent::AtomicBoolean.new(true)
41
43
  @thread = start_publishing_thread
42
44
  end
43
45
 
@@ -70,7 +72,7 @@ module AwsAdvancedRubyDriverWrapper
70
72
  end
71
73
 
72
74
  def release_resources
73
- @lock.synchronize { @running = false }
75
+ @running.make_false
74
76
  begin
75
77
  @thread&.wakeup
76
78
  rescue ThreadError
@@ -79,11 +81,20 @@ module AwsAdvancedRubyDriverWrapper
79
81
  @thread&.join(@message_interval_sec)
80
82
  end
81
83
 
84
+ # Restarts the publishing thread in a forked child, where it no longer runs. A thread that is
85
+ # still alive is kept, so calling this again does not start a second one.
86
+ def restart_after_fork
87
+ return if @thread&.alive?
88
+
89
+ @running.make_true
90
+ @thread = start_publishing_thread
91
+ end
92
+
82
93
  private
83
94
 
84
95
  def start_publishing_thread
85
96
  thread = Thread.new do
86
- while @lock.synchronize { @running }
97
+ while @running.true?
87
98
  sleep(@message_interval_sec)
88
99
  send_messages
89
100
  end
@@ -14,6 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'concurrent'
17
18
  require_relative 'expiration_cache'
18
19
  require_relative '../../logging'
19
20
  require_relative '../events/data_access_event'
@@ -34,7 +35,8 @@ module AwsAdvancedRubyDriverWrapper
34
35
  @caches = {}
35
36
  @event_publisher = event_publisher
36
37
  @lock = Mutex.new
37
- @running = true
38
+ @running = Concurrent::AtomicBoolean.new(true)
39
+ @cleanup_interval = cleanup_interval
38
40
  @cleanup_thread = start_cleanup_thread(cleanup_interval)
39
41
  end
40
42
 
@@ -107,6 +109,12 @@ module AwsAdvancedRubyDriverWrapper
107
109
  fetch_cache!(name).remove(key)
108
110
  end
109
111
 
112
+ # @param name [Symbol] cache name.
113
+ # @return [Boolean] whether a cache is registered under the name
114
+ def registered?(name)
115
+ @lock.synchronize { @caches.key?(name) }
116
+ end
117
+
110
118
  # Clears all items for a given name.
111
119
  # @param name [Symbol] registered cache name.
112
120
  def clear(name)
@@ -127,7 +135,7 @@ module AwsAdvancedRubyDriverWrapper
127
135
 
128
136
  # Stops the cleanup thread.
129
137
  def shutdown
130
- @running = false
138
+ @running.make_false
131
139
  begin
132
140
  @cleanup_thread&.wakeup
133
141
  rescue ThreadError
@@ -136,6 +144,15 @@ module AwsAdvancedRubyDriverWrapper
136
144
  @cleanup_thread&.join(5)
137
145
  end
138
146
 
147
+ # Restarts the cleanup thread in a forked child, where it no longer runs. A thread that is
148
+ # still alive is kept, so calling this again does not start a second one.
149
+ def restart_after_fork
150
+ return if @cleanup_thread&.alive?
151
+
152
+ @running.make_true
153
+ @cleanup_thread = start_cleanup_thread(@cleanup_interval)
154
+ end
155
+
139
156
  private
140
157
 
141
158
  def fetch_cache!(name)
@@ -147,7 +164,7 @@ module AwsAdvancedRubyDriverWrapper
147
164
 
148
165
  def start_cleanup_thread(interval)
149
166
  thread = Thread.new do
150
- while @running
167
+ while @running.true?
151
168
  sleep(interval)
152
169
  remove_expired_items
153
170
  end
@@ -15,5 +15,5 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module AwsAdvancedRubyDriverWrapper
18
- VERSION = '1.0.0'
18
+ VERSION = '1.0.1'
19
19
  end
@@ -73,6 +73,38 @@ module AwsAdvancedRubyDriverWrapper
73
73
  Services::HostService.clear_id_cache
74
74
  end
75
75
 
76
+ # Runs in a forked child (see ForkHook). Only the forking thread survives a fork, so every background
77
+ # thread is gone and the inherited monitors look alive but never refresh. The monitors and Blue/Green
78
+ # providers are forgotten without closing their connections, which the parent still uses, Secrets
79
+ # Manager fetches that were in flight are forgotten, and the shared services restart their threads.
80
+ # Cached data such as topology stays valid and is kept.
81
+ def self.after_fork
82
+ Plugins::BlueGreen::BlueGreenPlugin.release_providers_after_fork
83
+ Plugins::SecretsManagerPlugin.release_pending_refreshes_after_fork if defined?(Plugins::SecretsManagerPlugin)
84
+ return unless defined?(Services::CoreServices)
85
+
86
+ Services::CoreServices.monitor_service.restart_after_fork
87
+ Services::CoreServices.event_publisher.restart_after_fork
88
+ Services::CoreServices.storage_service.restart_after_fork
89
+ end
90
+
91
+ # Process._fork is the single entry point for Kernel#fork, Process.fork and IO.popen('-'), so
92
+ # hooking it covers every way an application server or job runner forks a worker. An error in the
93
+ # child is logged rather than raised: raising here would fail the application's own fork call.
94
+ module ForkHook
95
+ def _fork
96
+ pid = super
97
+ if pid.zero?
98
+ begin
99
+ AwsAdvancedRubyDriverWrapper.after_fork
100
+ rescue StandardError => e
101
+ AwsAdvancedRubyDriverWrapper.logger.error("Failed to reset the wrapper's background services after fork: #{e.message}")
102
+ end
103
+ end
104
+ pid
105
+ end
106
+ end
107
+
76
108
  def self.release_resources(grace_period_sec: 5)
77
109
  require_relative 'aws_advanced_ruby_driver_wrapper/services/service_utility'
78
110
  Services::CoreServices.monitor_service.shutdown(grace_period: grace_period_sec)
@@ -88,6 +120,8 @@ end
88
120
 
89
121
  at_exit { AwsAdvancedRubyDriverWrapper.shutdown }
90
122
 
123
+ Process.singleton_class.prepend(AwsAdvancedRubyDriverWrapper::ForkHook)
124
+
91
125
  # Register adapters with ActiveRecord via a lazy-load hook so the require order between this file and
92
126
  # ActiveRecord does not matter. The block runs the first time ActiveRecord::Base is referenced, whether
93
127
  # ActiveRecord is loaded before or after this file. The register call is itself lazy — each adapter file
@@ -101,6 +135,8 @@ end
101
135
 
102
136
  if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
103
137
  ActiveSupport.on_load(:active_record) do
138
+ require_relative 'aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias'
139
+
104
140
  ActiveRecord::ConnectionAdapters.register(
105
141
  'aws_postgresql',
106
142
  'ActiveRecord::ConnectionAdapters::AwsPostgreSQLAdapter',
@@ -114,3 +150,5 @@ if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
114
150
  )
115
151
  end
116
152
  end
153
+
154
+ require_relative 'aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias' if defined?(ActiveRecord)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_advanced_ruby_driver_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-05 00:00:00.000000000 Z
11
+ date: 2026-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -44,8 +44,11 @@ files:
44
44
  - THIRD-PARTY-LICENSES
45
45
  - aws_advanced_ruby_driver_wrapper.gemspec
46
46
  - lib/aws_advanced_ruby_driver_wrapper.rb
47
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb
48
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb
47
49
  - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb
48
50
  - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb
51
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb
49
52
  - lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb
50
53
  - lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb
51
54
  - lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb
@@ -152,7 +155,6 @@ files:
152
155
  - lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb
153
156
  - lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb
154
157
  - lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb
155
- - lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb
156
158
  - lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb
157
159
  - lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb
158
160
  - lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License").
6
- # You may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- module AwsAdvancedRubyDriverWrapper
18
- module Utils
19
- # ActiveRecord-only keys that should not be passed to the wrapper or native driver.
20
- AR_COMMON_KEYS = %i[
21
- adapter pool checkout_timeout idle_timeout reaping_frequency
22
- variables prepared_statements encoding reconnect socket flags
23
- ].freeze
24
- end
25
- end