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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -2
- data/README.md +115 -6
- data/THIRD-PARTY-LICENSES +70 -11
- data/aws_advanced_ruby_driver_wrapper.gemspec +9 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb +47 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +23 -9
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +65 -10
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb +80 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +61 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +48 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +11 -4
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb +129 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +9 -81
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +28 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb +118 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +16 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +10 -5
- data/lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb +127 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +1 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +11 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +14 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +6 -0
- data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +27 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +125 -7
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb +84 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +3 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +7 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +68 -41
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +4 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +5 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +7 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +10 -13
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +95 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +11 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +14 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +68 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb +266 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb +134 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb +113 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +30 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +16 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +6 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +29 -6
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql +54 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +23 -1
- data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +49 -23
- data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +63 -1
- data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +3 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +20 -7
- data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +34 -8
- data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +23 -4
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +80 -29
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +10 -2
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/trilogy.rb +167 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +25 -15
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +18 -7
- data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +2 -2
- data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +15 -31
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +55 -76
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb +215 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +11 -20
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +2 -3
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +21 -14
- data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +2 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb +133 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +29 -8
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb +89 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb +124 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/{ar_constants.rb → telemetry/open_telemetry_counter.rb} +19 -5
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb +122 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb +36 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb +50 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb +143 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +9 -2
- data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper.rb +47 -2
- 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
|
|
77
|
-
logger.debug('The topology query returned a result with
|
|
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
|
#
|
|
@@ -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
|
|
37
|
-
# for one driver never loads
|
|
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.
|
|
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-
|
|
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'
|