aws_advanced_ruby_driver_wrapper 1.0.0 → 1.1.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -2
  3. data/README.md +115 -6
  4. data/THIRD-PARTY-LICENSES +70 -11
  5. data/aws_advanced_ruby_driver_wrapper.gemspec +9 -0
  6. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb +40 -0
  7. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb +47 -0
  8. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +23 -9
  9. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +65 -10
  10. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb +80 -0
  11. data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +61 -0
  12. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +48 -0
  13. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +11 -4
  14. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb +129 -0
  15. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +9 -81
  16. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +28 -0
  17. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb +118 -0
  18. data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +16 -0
  19. data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +10 -5
  20. data/lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb +127 -0
  21. data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +1 -0
  22. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +11 -0
  23. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +14 -0
  24. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +6 -0
  25. data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +27 -9
  26. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +125 -7
  27. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb +84 -0
  28. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +3 -1
  29. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +7 -0
  30. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +68 -41
  31. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +4 -2
  32. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +5 -3
  33. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +7 -1
  34. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +1 -1
  35. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +10 -13
  36. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +95 -3
  37. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +11 -1
  38. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +4 -1
  39. data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +14 -3
  40. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +68 -3
  41. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb +266 -0
  42. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb +134 -0
  43. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb +113 -0
  44. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +30 -9
  45. data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +16 -2
  46. data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +4 -1
  47. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +6 -3
  48. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +13 -4
  49. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +29 -6
  50. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql +108 -0
  51. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql +54 -0
  52. data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +23 -1
  53. data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +49 -23
  54. data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +63 -1
  55. data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +3 -0
  56. data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +20 -7
  57. data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +34 -8
  58. data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +23 -4
  59. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +80 -29
  60. data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +10 -2
  61. data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +4 -1
  62. data/lib/aws_advanced_ruby_driver_wrapper/trilogy.rb +167 -0
  63. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +1 -1
  64. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +25 -15
  65. data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +18 -7
  66. data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +2 -2
  67. data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +13 -4
  68. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +15 -31
  69. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +55 -76
  70. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb +215 -0
  71. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +11 -20
  72. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +2 -3
  73. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +21 -14
  74. data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +2 -1
  75. data/lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb +133 -0
  76. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +29 -8
  77. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb +89 -0
  78. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb +124 -0
  79. data/lib/aws_advanced_ruby_driver_wrapper/utils/{ar_constants.rb → telemetry/open_telemetry_counter.rb} +19 -5
  80. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb +122 -0
  81. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb +36 -0
  82. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb +50 -0
  83. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb +143 -0
  84. data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +9 -2
  85. data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
  86. data/lib/aws_advanced_ruby_driver_wrapper.rb +47 -2
  87. metadata +57 -3
@@ -0,0 +1,36 @@
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
+ module Telemetry
20
+ # A gauge whose value is read from its callback each time metrics are collected.
21
+ #
22
+ # The instrument is registered once, and reads whichever callback was set last. The callback
23
+ # can therefore be replaced, which a second registration of the same instrument would not do.
24
+ class OpenTelemetryGauge
25
+ attr_reader :name
26
+ attr_writer :callback
27
+
28
+ def initialize(meter, name)
29
+ @name = name
30
+ @callback = nil
31
+ @gauge = meter.create_observable_gauge(name, callback: -> { @callback&.call })
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,50 @@
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
+ module Telemetry
20
+ # The levels a telemetry context can be opened at. Callers name a level with one of these
21
+ # constants, so that a mistyped level raises NameError where it is written.
22
+ module TraceLevel
23
+ # Always starts a new trace, whatever the settings say.
24
+ FORCE_TOP_LEVEL = :force_top_level
25
+ # Starts a new trace when +telemetry_submit_top_level+ is enabled, and is otherwise treated
26
+ # as {NESTED}.
27
+ TOP_LEVEL = :top_level
28
+ # Becomes a child of the current span. Outside of any trace nothing is recorded, so the
29
+ # wrapper does not start traces of its own unless asked to.
30
+ NESTED = :nested
31
+ # Records nothing.
32
+ NO_TRACE = :no_trace
33
+ end
34
+
35
+ # Instrumentation scope name the wrapper's tracer and meter are registered under.
36
+ INSTRUMENTATION_NAME = 'aws-advanced-ruby-driver-wrapper'
37
+
38
+ # Span attribute names, and the prefix of the name of a copied span.
39
+ module TelemetryConst
40
+ TRACE_NAME_ANNOTATION = 'trace_name'
41
+ RUBY_CALL_ANNOTATION = 'ruby_call'
42
+ PARENT_TRACE_ANNOTATION = 'parent_trace_id'
43
+ EXCEPTION_TYPE_ANNOTATION = 'exception_type'
44
+ EXCEPTION_MESSAGE_ANNOTATION = 'exception_message'
45
+ SOURCE_TRACE_ANNOTATION = 'source_trace_id'
46
+ COPY_TRACE_NAME_PREFIX = 'copy: '
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,143 @@
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 '../../errors'
18
+ require_relative '../../property_definition'
19
+ require_relative 'telemetry_const'
20
+ require_relative 'null_telemetry'
21
+ require_relative 'open_telemetry_factory'
22
+
23
+ module AwsAdvancedRubyDriverWrapper
24
+ module Utils
25
+ module Telemetry
26
+ # Records the wrapper's traces and metrics through the backends selected by the connection
27
+ # properties. Traces and metrics are configured separately; whichever is disabled is not recorded.
28
+ class TelemetryFactory
29
+ TRACES_BACKENDS = { 'otlp' => OpenTelemetryFactory, 'none' => nil }.freeze
30
+ METRICS_BACKENDS = { 'otlp' => OpenTelemetryFactory, 'none' => nil }.freeze
31
+
32
+ # @param wrapper_props [Hash, Concurrent::Map] the wrapper properties of the connection
33
+ # @raise [Errors::AwsError] if telemetry is enabled and a backend is missing or not recognized
34
+ # @raise [LoadError] if a selected backend's gem is not installed
35
+ def initialize(wrapper_props)
36
+ @submit_top_level = PropertyDefinition::TELEMETRY_SUBMIT_TOP_LEVEL.get_bool(wrapper_props)
37
+
38
+ if PropertyDefinition::ENABLE_TELEMETRY.get_bool(wrapper_props)
39
+ @traces_factory = backend(PropertyDefinition::TELEMETRY_TRACES_BACKEND, TRACES_BACKENDS, wrapper_props)
40
+ @metrics_factory = backend(PropertyDefinition::TELEMETRY_METRICS_BACKEND, METRICS_BACKENDS, wrapper_props)
41
+ end
42
+
43
+ @traces_factory&.require_traces_api!
44
+ @metrics_factory&.require_metrics_api!
45
+ end
46
+
47
+ # Opens a context that the caller must close. Prefer {#in_context}, which closes it.
48
+ #
49
+ # @param name [String] the span name
50
+ # @param trace_level [Symbol] one of the {TraceLevel} constants
51
+ # @return [OpenTelemetryContext, NullTelemetryContext]
52
+ def open_telemetry_context(name, trace_level)
53
+ return NullTelemetryContext::INSTANCE if @traces_factory.nil?
54
+
55
+ trace_level = TraceLevel::NESTED if trace_level == TraceLevel::TOP_LEVEL && !@submit_top_level
56
+ @traces_factory.open_telemetry_context(name, trace_level)
57
+ end
58
+
59
+ # Runs the block inside a new context and closes the context when the block finishes.
60
+ #
61
+ # @param record_result [Boolean] whether to mark the span as succeeded or failed according to
62
+ # how the block finishes. An error raised by the block marks it failed and is recorded on the
63
+ # span. Leaving the block early with +break+, +next+, +return+ or +throw+ is not an error, so
64
+ # it marks the span as succeeded.
65
+ # @param record_failure [Boolean] whether to mark the span as failed, recording the error, when
66
+ # the block raises, while leaving its status unset when it does not. Implied by +record_result+.
67
+ # @yieldparam context [OpenTelemetryContext, NullTelemetryContext]
68
+ # @return the block's result
69
+ def in_context(name, trace_level, record_result: false, record_failure: false)
70
+ return yield NullTelemetryContext::INSTANCE if @traces_factory.nil?
71
+
72
+ context = open_telemetry_context(name, trace_level)
73
+ failed = false
74
+ begin
75
+ yield context
76
+ rescue Exception => e # rubocop:disable Lint/RescueException -- recorded, then re-raised
77
+ failed = true
78
+ if record_result || record_failure
79
+ context.record_exception(e)
80
+ context.success = false
81
+ end
82
+ raise
83
+ ensure
84
+ context.success = true if record_result && !failed
85
+ context.close
86
+ end
87
+ end
88
+
89
+ # Records a copy of a closed context's span at another trace level, typically {TraceLevel::FORCE_TOP_LEVEL},
90
+ # so that work recorded inside a trace, such as a failover, can also be found as a trace of
91
+ # its own. The copy has the same timings, attributes and status, is named with a +copy: +
92
+ # prefix, and is linked to the original.
93
+ #
94
+ # @param context [OpenTelemetryContext, NullTelemetryContext] a context that has been closed
95
+ def post_copy(context, trace_level)
96
+ @traces_factory&.post_copy(context, trace_level)
97
+ end
98
+
99
+ # @return [OpenTelemetryCounter, NullTelemetryCounter]
100
+ def create_counter(name)
101
+ return NullTelemetryCounter::INSTANCE if @metrics_factory.nil?
102
+
103
+ @metrics_factory.create_counter(name)
104
+ end
105
+
106
+ # A gauge reports one value for the whole process: creating a gauge with a name that already
107
+ # exists, from this connection or any other, replaces the callback it is read from. So the
108
+ # callback should report state shared by all connections (such as the size of a shared
109
+ # cache) rather than state of its own connection.
110
+ #
111
+ # @yieldreturn [Numeric] the gauge's current value, read each time metrics are collected
112
+ # @return [OpenTelemetryGauge, NullTelemetryGauge]
113
+ def create_gauge(name, &callback)
114
+ return NullTelemetryGauge::INSTANCE if @metrics_factory.nil?
115
+
116
+ @metrics_factory.create_gauge(name, callback)
117
+ end
118
+
119
+ # @return [Boolean] whether traces or metrics are being recorded
120
+ def in_use?
121
+ traces_in_use? || !@metrics_factory.nil?
122
+ end
123
+
124
+ # @return [Boolean] whether traces are being recorded
125
+ def traces_in_use?
126
+ !@traces_factory.nil?
127
+ end
128
+
129
+ private
130
+
131
+ def backend(property, backends, wrapper_props)
132
+ value = property.get_string(wrapper_props)
133
+ key = value&.downcase
134
+ return backends[key] if backends.key?(key)
135
+
136
+ raise Errors::AwsError,
137
+ "#{value.inspect} is not a valid #{property.name}. " \
138
+ "When enable_telemetry is true, #{property.name} must be one of: #{backends.keys.join(', ')}"
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -73,8 +73,8 @@ module AwsAdvancedRubyDriverWrapper
73
73
  def query_topology(conn, initial_host_info, instance_template)
74
74
  results = @dialect.execute(conn, @dialect.topology_query)
75
75
  # We expect at least 4 columns. Note that the server may return 0 columns if failover has occurred.
76
- if results.fields.empty?
77
- logger.debug('The topology query returned a result with 0 columns. ' \
76
+ if topology_result_empty?(results)
77
+ logger.debug('The topology query returned a result with no rows or rows with no columns. ' \
78
78
  'This may occur if the topology query is executed when the server is failing over.')
79
79
  return nil
80
80
  end
@@ -84,6 +84,13 @@ module AwsAdvancedRubyDriverWrapper
84
84
 
85
85
  private
86
86
 
87
+ # True if the topology query returned no rows, or rows without columns (the server may return
88
+ # no columns while failing over).
89
+ def topology_result_empty?(results)
90
+ first_row = results.first
91
+ first_row.nil? || first_row.empty?
92
+ end
93
+
87
94
  # Verifies the writer in the host list. If multiple writers exist, the one with the most recent
88
95
  # last_update_time is used as the current writer.
89
96
  #
@@ -15,5 +15,5 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module AwsAdvancedRubyDriverWrapper
18
- VERSION = '1.0.0'
18
+ VERSION = '1.1.0'
19
19
  end
@@ -33,11 +33,12 @@ module AwsAdvancedRubyDriverWrapper
33
33
  @config = Configuration.new
34
34
 
35
35
  # Direct-driver connection classes are autoloaded so requiring this file alone is enough to use them:
36
- # referencing either constant loads its driver-specific file on demand. Loading stays lazy - a client
37
- # for one driver never loads the other driver's code, and the underlying 'pg'/'mysql2' gem is only
36
+ # referencing any of them loads its driver-specific file on demand. Loading stays lazy - a client
37
+ # for one driver never loads another driver's code, and the underlying 'pg'/'mysql2'/'trilogy' gem is only
38
38
  # required when a connection is actually opened.
39
39
  autoload :WrapperPgConnection, 'aws_advanced_ruby_driver_wrapper/postgresql'
40
40
  autoload :WrapperMysql2Client, 'aws_advanced_ruby_driver_wrapper/mysql'
41
+ autoload :WrapperTrilogyClient, 'aws_advanced_ruby_driver_wrapper/trilogy'
41
42
 
42
43
  # Other public entry points are autoloaded for the same reason, so they work from code that runs
43
44
  # before any connection is opened, such as a Rails initializer or a setup script.
@@ -73,6 +74,38 @@ module AwsAdvancedRubyDriverWrapper
73
74
  Services::HostService.clear_id_cache
74
75
  end
75
76
 
77
+ # Runs in a forked child (see ForkHook). Only the forking thread survives a fork, so every background
78
+ # thread is gone and the inherited monitors look alive but never refresh. The monitors and Blue/Green
79
+ # providers are forgotten without closing their connections, which the parent still uses, Secrets
80
+ # Manager fetches that were in flight are forgotten, and the shared services restart their threads.
81
+ # Cached data such as topology stays valid and is kept.
82
+ def self.after_fork
83
+ Plugins::BlueGreen::BlueGreenPlugin.release_providers_after_fork
84
+ Plugins::SecretsManagerPlugin.release_pending_refreshes_after_fork if defined?(Plugins::SecretsManagerPlugin)
85
+ return unless defined?(Services::CoreServices)
86
+
87
+ Services::CoreServices.monitor_service.restart_after_fork
88
+ Services::CoreServices.event_publisher.restart_after_fork
89
+ Services::CoreServices.storage_service.restart_after_fork
90
+ end
91
+
92
+ # Process._fork is the single entry point for Kernel#fork, Process.fork and IO.popen('-'), so
93
+ # hooking it covers every way an application server or job runner forks a worker. An error in the
94
+ # child is logged rather than raised: raising here would fail the application's own fork call.
95
+ module ForkHook
96
+ def _fork
97
+ pid = super
98
+ if pid.zero?
99
+ begin
100
+ AwsAdvancedRubyDriverWrapper.after_fork
101
+ rescue StandardError => e
102
+ AwsAdvancedRubyDriverWrapper.logger.error("Failed to reset the wrapper's background services after fork: #{e.message}")
103
+ end
104
+ end
105
+ pid
106
+ end
107
+ end
108
+
76
109
  def self.release_resources(grace_period_sec: 5)
77
110
  require_relative 'aws_advanced_ruby_driver_wrapper/services/service_utility'
78
111
  Services::CoreServices.monitor_service.shutdown(grace_period: grace_period_sec)
@@ -88,6 +121,8 @@ end
88
121
 
89
122
  at_exit { AwsAdvancedRubyDriverWrapper.shutdown }
90
123
 
124
+ Process.singleton_class.prepend(AwsAdvancedRubyDriverWrapper::ForkHook)
125
+
91
126
  # Register adapters with ActiveRecord via a lazy-load hook so the require order between this file and
92
127
  # ActiveRecord does not matter. The block runs the first time ActiveRecord::Base is referenced, whether
93
128
  # ActiveRecord is loaded before or after this file. The register call is itself lazy — each adapter file
@@ -101,6 +136,8 @@ end
101
136
 
102
137
  if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
103
138
  ActiveSupport.on_load(:active_record) do
139
+ require_relative 'aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias'
140
+
104
141
  ActiveRecord::ConnectionAdapters.register(
105
142
  'aws_postgresql',
106
143
  'ActiveRecord::ConnectionAdapters::AwsPostgreSQLAdapter',
@@ -112,5 +149,13 @@ if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
112
149
  'ActiveRecord::ConnectionAdapters::AwsMysql2Adapter',
113
150
  'aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter'
114
151
  )
152
+
153
+ ActiveRecord::ConnectionAdapters.register(
154
+ 'aws_trilogy',
155
+ 'ActiveRecord::ConnectionAdapters::AwsTrilogyAdapter',
156
+ 'aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter'
157
+ )
115
158
  end
116
159
  end
160
+
161
+ require_relative 'aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias' if defined?(ActiveRecord)
metadata CHANGED
@@ -1,15 +1,29 @@
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.1.0
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-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: concurrent-ruby
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -30,6 +44,20 @@ dependencies:
30
44
  - - ">="
31
45
  - !ruby/object:Gem::Version
32
46
  version: 1.3.7
47
+ - !ruby/object:Gem::Dependency
48
+ name: logger
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
33
61
  description: A Ruby DB driver wrapper that provides enhanced features for AWS RDS
34
62
  MySQL/PostgreSQL databases
35
63
  email:
@@ -44,8 +72,12 @@ files:
44
72
  - THIRD-PARTY-LICENSES
45
73
  - aws_advanced_ruby_driver_wrapper.gemspec
46
74
  - lib/aws_advanced_ruby_driver_wrapper.rb
75
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb
76
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb
47
77
  - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb
48
78
  - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb
79
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb
80
+ - lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb
49
81
  - lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb
50
82
  - lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb
51
83
  - lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb
@@ -62,12 +94,15 @@ files:
62
94
  - lib/aws_advanced_ruby_driver_wrapper/db_dialects/utils/dialect_utils.rb
63
95
  - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb
64
96
  - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb
97
+ - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb
65
98
  - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb
66
99
  - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb
100
+ - lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb
67
101
  - lib/aws_advanced_ruby_driver_wrapper/errors.rb
68
102
  - lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb
69
103
  - lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb
70
104
  - lib/aws_advanced_ruby_driver_wrapper/errors/pg_error_handler.rb
105
+ - lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb
71
106
  - lib/aws_advanced_ruby_driver_wrapper/host/connection_string_host_list_provider.rb
72
107
  - lib/aws_advanced_ruby_driver_wrapper/host/global_aurora_host_list_provider.rb
73
108
  - lib/aws_advanced_ruby_driver_wrapper/host/host_availability.rb
@@ -84,6 +119,7 @@ files:
84
119
  - lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_state.rb
85
120
  - lib/aws_advanced_ruby_driver_wrapper/mysql.rb
86
121
  - lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb
122
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb
87
123
  - lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb
88
124
  - lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/iam_host_tracker.rb
89
125
  - lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interim_status.rb
@@ -113,6 +149,9 @@ files:
113
149
  - lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb
114
150
  - lib/aws_advanced_ruby_driver_wrapper/plugins/failover_mode.rb
115
151
  - lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb
152
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb
153
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb
154
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb
116
155
  - lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_mode.rb
117
156
  - lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb
118
157
  - lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb
@@ -136,6 +175,8 @@ files:
136
175
  - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sanitizer.rb
137
176
  - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_name.rb
138
177
  - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_validator.rb
178
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql
179
+ - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql
139
180
  - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql_runner.rb
140
181
  - lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/type_marker.rb
141
182
  - lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb
@@ -151,8 +192,8 @@ files:
151
192
  - lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb
152
193
  - lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb
153
194
  - lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb
195
+ - lib/aws_advanced_ruby_driver_wrapper/trilogy.rb
154
196
  - lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb
155
- - lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb
156
197
  - lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb
157
198
  - lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb
158
199
  - lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb
@@ -167,6 +208,7 @@ files:
167
208
  - lib/aws_advanced_ruby_driver_wrapper/utils/multi_az_topology_utils.rb
168
209
  - lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb
169
210
  - lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb
211
+ - lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb
170
212
  - lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb
171
213
  - lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb
172
214
  - lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_type.rb
@@ -176,12 +218,20 @@ files:
176
218
  - lib/aws_advanced_ruby_driver_wrapper/utils/rds_url_type.rb
177
219
  - lib/aws_advanced_ruby_driver_wrapper/utils/rds_utils.rb
178
220
  - lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb
221
+ - lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb
179
222
  - lib/aws_advanced_ruby_driver_wrapper/utils/sql_encoding.rb
180
223
  - lib/aws_advanced_ruby_driver_wrapper/utils/sql_method_analyzer.rb
181
224
  - lib/aws_advanced_ruby_driver_wrapper/utils/storage/cache_entry.rb
182
225
  - lib/aws_advanced_ruby_driver_wrapper/utils/storage/expiration_cache.rb
183
226
  - lib/aws_advanced_ruby_driver_wrapper/utils/storage/sliding_expiration_cache.rb
184
227
  - lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb
228
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb
229
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb
230
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_counter.rb
231
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb
232
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb
233
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb
234
+ - lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb
185
235
  - lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb
186
236
  - lib/aws_advanced_ruby_driver_wrapper/version.rb
187
237
  - lib/aws_advanced_ruby_driver_wrapper/wrapper_property.rb
@@ -200,6 +250,10 @@ post_install_message: |
200
250
  gem install mysql2
201
251
  require 'aws_advanced_ruby_driver_wrapper/mysql'
202
252
 
253
+ To use with MySQL through trilogy:
254
+ gem install trilogy
255
+ require 'aws_advanced_ruby_driver_wrapper/trilogy'
256
+
203
257
  To use with PostgreSQL:
204
258
  gem install pg
205
259
  require 'aws_advanced_ruby_driver_wrapper/postgresql'