aws_advanced_ruby_driver_wrapper 1.0.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 +7 -0
- data/CHANGELOG.md +23 -0
- data/LICENSE +175 -0
- data/NOTICE +1 -0
- data/README.md +168 -0
- data/THIRD-PARTY-LICENSES +473 -0
- data/aws_advanced_ruby_driver_wrapper.gemspec +73 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +73 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/custom_configuration.rb +58 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_mysql_dialect.rb +103 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/aurora_pg_dialect.rb +124 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/dialect_codes.rb +38 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_mysql_dialect.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/global_pg_dialect.rb +92 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_mysql_dialect.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/multi_az_cluster_pg_dialect.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/mysql_dialect.rb +98 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/pg_dialect.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_mysql_dialect.rb +88 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/rds_pg_dialect.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/unknown_dialect.rb +72 -0
- data/lib/aws_advanced_ruby_driver_wrapper/db_dialects/utils/dialect_utils.rb +71 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +154 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +55 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +165 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +201 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +62 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +80 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/pg_error_handler.rb +126 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +59 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/connection_string_host_list_provider.rb +95 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/global_aurora_host_list_provider.rb +65 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability.rb +24 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_availability_strategy.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_info.rb +137 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/host_role.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/random_host_selector.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/host/rds_host_list_provider.rb +206 -0
- data/lib/aws_advanced_ruby_driver_wrapper/logging.rb +110 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +709 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/global_cluster_topology_monitor.rb +72 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +57 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_state.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +429 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +205 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +132 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/iam_host_tracker.rb +84 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interim_status.rb +92 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/interval_rate.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase.rb +69 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_event_log.rb +85 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/phase_time_info.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/role.rb +38 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +83 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/reject_connect_routing.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +136 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +53 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +52 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +83 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status.rb +68 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +244 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_info.rb +30 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +564 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +414 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_state.rb +98 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/switchover_timer.rb +46 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +266 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +158 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/info.rb +111 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/member_list_type.rb +31 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/role.rb +45 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_mode.rb +43 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +467 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_mode.rb +68 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +403 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +159 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +485 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/audit_logger.rb +157 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_cipher.rb +159 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/column_encryption_config.rb +61 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/connection_source.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/data_key_cache.rb +220 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_algorithm.rb +75 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_config.rb +146 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_service.rb +391 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/error_context.rb +198 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/errors.rb +259 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +435 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +378 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_metadata.rb +86 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +890 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_utility.rb +281 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/metadata_manager.rb +332 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sanitizer.rb +147 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_name.rb +70 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/schema_validator.rb +211 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql_runner.rb +147 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/type_marker.rb +109 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +358 -0
- data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +659 -0
- data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +409 -0
- data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +122 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/connection_service.rb +143 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +267 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +199 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +186 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_call_context.rb +63 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +273 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +30 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +78 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/session_state_service.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/accessible_regions.rb +52 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/ar_constants.rb +25 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/aurora_topology_utils.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/aws_credentials_utils.rb +62 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +91 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +368 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/conversion_utils.rb +51 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +119 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/data_access_event.rb +26 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/monitor_reset_event.rb +26 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +185 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/host_list_utils.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +112 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/multi_az_topology_utils.rb +117 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +99 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +641 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +502 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +63 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_type.rb +35 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint.rb +27 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/routing_hint_parser.rb +50 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +139 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_url_type.rb +71 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/rds_utils.rb +575 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +153 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_encoding.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/sql_method_analyzer.rb +195 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/cache_entry.rb +56 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/expiration_cache.rb +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/sliding_expiration_cache.rb +137 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +172 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +127 -0
- data/lib/aws_advanced_ruby_driver_wrapper/version.rb +19 -0
- data/lib/aws_advanced_ruby_driver_wrapper/wrapper_property.rb +64 -0
- data/lib/aws_advanced_ruby_driver_wrapper.rb +116 -0
- metadata +227 -0
|
@@ -0,0 +1,137 @@
|
|
|
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 'cache_entry'
|
|
18
|
+
|
|
19
|
+
module AwsAdvancedRubyDriverWrapper
|
|
20
|
+
module Utils
|
|
21
|
+
module Storage
|
|
22
|
+
# A thread-safe cache with sliding TTL expiration. Accessing an existing entry
|
|
23
|
+
# via {#compute_if_absent} renews its expiration, and {#extend_expiration} allows
|
|
24
|
+
# manual renewal. Provides conditional removal via {#remove_if} and
|
|
25
|
+
# {#remove_if_expired} for entries that require careful lifecycle management.
|
|
26
|
+
# Disposal of removed items should be handled by the caller.
|
|
27
|
+
#
|
|
28
|
+
# For simple data that does not need expiration renewal or controlled removal,
|
|
29
|
+
# see {ExpirationCache}.
|
|
30
|
+
class SlidingExpirationCache
|
|
31
|
+
DEFAULT_TTL = 900 # 15 minutes in seconds
|
|
32
|
+
|
|
33
|
+
# @param ttl [Numeric] time-to-live for cache entries in seconds.
|
|
34
|
+
def initialize(ttl: DEFAULT_TTL)
|
|
35
|
+
@cache = {}
|
|
36
|
+
@ttl = ttl
|
|
37
|
+
@lock = Mutex.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Retrieves the value at the given key. Returns nil if absent or expired.
|
|
41
|
+
# Extends the expiration if the entry exists and is not expired.
|
|
42
|
+
# @param key [Object] the cache key.
|
|
43
|
+
# @return [Object, nil] the cached value, or nil.
|
|
44
|
+
def get(key)
|
|
45
|
+
@lock.synchronize do
|
|
46
|
+
entry = @cache[key]
|
|
47
|
+
return nil if entry.nil? || entry.expired?
|
|
48
|
+
|
|
49
|
+
entry.extend_expiration(@ttl)
|
|
50
|
+
entry.value
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Computes and stores a value if the key is absent.
|
|
55
|
+
# If the key exists, extends its expiration and returns the existing value, even if it is expired.
|
|
56
|
+
# @param key [Object] the cache key.
|
|
57
|
+
# @yield [key] block to compute the value if absent.
|
|
58
|
+
# @return [Object] the current (existing or computed) value.
|
|
59
|
+
def compute_if_absent(key)
|
|
60
|
+
@lock.synchronize do
|
|
61
|
+
entry = @cache[key]
|
|
62
|
+
|
|
63
|
+
if entry.nil?
|
|
64
|
+
value = yield(key)
|
|
65
|
+
@cache[key] = new_cache_entry(value)
|
|
66
|
+
return value
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
entry.extend_expiration(@ttl)
|
|
70
|
+
entry.value
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Extends the expiration of the entry at the given key, if it exists.
|
|
75
|
+
# @param key [Object] the cache key.
|
|
76
|
+
def extend_expiration(key)
|
|
77
|
+
@lock.synchronize do
|
|
78
|
+
entry = @cache[key]
|
|
79
|
+
entry&.extend_expiration(@ttl)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Removes the value at the given key.
|
|
84
|
+
# @param key [Object] the cache key.
|
|
85
|
+
# @return [Object, nil] the removed value, or nil.
|
|
86
|
+
def remove(key)
|
|
87
|
+
@lock.synchronize do
|
|
88
|
+
entry = @cache.delete(key)
|
|
89
|
+
entry&.value
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Removes the value at the given key only if the predicate returns true.
|
|
94
|
+
# @param key [Object] the cache key.
|
|
95
|
+
# @yield [value] block that returns true if the value should be removed.
|
|
96
|
+
# @return [Object, nil] the removed value, or nil.
|
|
97
|
+
def remove_if(key)
|
|
98
|
+
@lock.synchronize do
|
|
99
|
+
entry = @cache[key]
|
|
100
|
+
return nil if entry.nil?
|
|
101
|
+
return nil unless yield(entry.value)
|
|
102
|
+
|
|
103
|
+
@cache.delete(key)
|
|
104
|
+
entry.value
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Removes the value at the given key only if it is expired.
|
|
109
|
+
# @param key [Object] the cache key.
|
|
110
|
+
# @return [Object, nil] the removed value, or nil.
|
|
111
|
+
def remove_if_expired(key)
|
|
112
|
+
@lock.synchronize do
|
|
113
|
+
entry = @cache[key]
|
|
114
|
+
return nil if entry.nil? || !entry.expired?
|
|
115
|
+
|
|
116
|
+
@cache.delete(key)
|
|
117
|
+
entry.value
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns a hash copy of all entries (including expired ones).
|
|
122
|
+
# @return [Hash]
|
|
123
|
+
def entries
|
|
124
|
+
@lock.synchronize do
|
|
125
|
+
@cache.transform_values(&:value)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
def new_cache_entry(value)
|
|
132
|
+
CacheEntry.new(value, Process.clock_gettime(Process::CLOCK_MONOTONIC) + @ttl)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
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 'expiration_cache'
|
|
18
|
+
require_relative '../../logging'
|
|
19
|
+
require_relative '../events/data_access_event'
|
|
20
|
+
|
|
21
|
+
module AwsAdvancedRubyDriverWrapper
|
|
22
|
+
module Utils
|
|
23
|
+
module Storage
|
|
24
|
+
# A centralized, shared cache registry with per-type TTL and background cleanup.
|
|
25
|
+
# Each named cache partition stores items independently with its own expiration policy.
|
|
26
|
+
class StorageService
|
|
27
|
+
include Logging
|
|
28
|
+
|
|
29
|
+
DEFAULT_CLEANUP_INTERVAL = 300 # 5 minutes in seconds
|
|
30
|
+
|
|
31
|
+
# @param event_publisher [#publish] the event publisher for data access events.
|
|
32
|
+
# @param cleanup_interval [Numeric] seconds between cleanup runs.
|
|
33
|
+
def initialize(event_publisher:, cleanup_interval: DEFAULT_CLEANUP_INTERVAL)
|
|
34
|
+
@caches = {}
|
|
35
|
+
@event_publisher = event_publisher
|
|
36
|
+
@lock = Mutex.new
|
|
37
|
+
@running = true
|
|
38
|
+
@cleanup_thread = start_cleanup_thread(cleanup_interval)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Registers a named cache. No-op if already registered.
|
|
42
|
+
#
|
|
43
|
+
# @param name [Symbol] cache partition name.
|
|
44
|
+
# @param ttl [Numeric] time-to-live in seconds.
|
|
45
|
+
def register(name, ttl:)
|
|
46
|
+
@lock.synchronize do
|
|
47
|
+
return if @caches.key?(name)
|
|
48
|
+
|
|
49
|
+
@caches[name] = ExpirationCache.new(ttl:)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Stores an item.
|
|
54
|
+
# @param name [Symbol] registered cache name.
|
|
55
|
+
# @param key [Object] item key.
|
|
56
|
+
# @param value [Object] item to store.
|
|
57
|
+
def set(name, key, value)
|
|
58
|
+
fetch_cache!(name).put(key, value)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Retrieves an item. Returns nil if absent or expired.
|
|
62
|
+
# @param name [Symbol] registered cache name.
|
|
63
|
+
# @param key [Object] item key.
|
|
64
|
+
# @param register_access [Boolean] whether to publish a DataAccessEvent.
|
|
65
|
+
# @return [Object, nil]
|
|
66
|
+
def get(name, key, register_access: true)
|
|
67
|
+
value = fetch_cache!(name).get(key)
|
|
68
|
+
return nil unless value
|
|
69
|
+
|
|
70
|
+
@event_publisher.publish(Events::DataAccessEvent.new(data_type: name, key:)) if register_access && @event_publisher
|
|
71
|
+
|
|
72
|
+
value
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Retrieves an item without raising if the named cache has not been registered.
|
|
76
|
+
# Returns nil when the cache partition is absent, or when the item is absent or expired.
|
|
77
|
+
# Use this for reads of optional/foreign caches that may not exist in the current
|
|
78
|
+
# plugin configuration (e.g. a plugin reading a cache owned by another, optional plugin).
|
|
79
|
+
# @param name [Symbol] cache name (need not be registered).
|
|
80
|
+
# @param key [Object] item key.
|
|
81
|
+
# @param register_access [Boolean] whether to publish a DataAccessEvent.
|
|
82
|
+
# @return [Object, nil]
|
|
83
|
+
def get_if_registered(name, key, register_access: true)
|
|
84
|
+
cache = @caches[name]
|
|
85
|
+
return nil if cache.nil?
|
|
86
|
+
|
|
87
|
+
value = cache.get(key)
|
|
88
|
+
return nil unless value
|
|
89
|
+
|
|
90
|
+
@event_publisher.publish(Events::DataAccessEvent.new(data_type: name, key:)) if register_access && @event_publisher
|
|
91
|
+
|
|
92
|
+
value
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Returns true if a non-expired item exists at the given name + key.
|
|
96
|
+
# @param name [Symbol] registered cache name.
|
|
97
|
+
# @param key [Object] item key.
|
|
98
|
+
# @return [Boolean]
|
|
99
|
+
def exists?(name, key)
|
|
100
|
+
!get(name, key, register_access: false).nil?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Removes an item.
|
|
104
|
+
# @param name [Symbol] registered cache name.
|
|
105
|
+
# @param key [Object] item key.
|
|
106
|
+
def remove(name, key)
|
|
107
|
+
fetch_cache!(name).remove(key)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Clears all items for a given name.
|
|
111
|
+
# @param name [Symbol] registered cache name.
|
|
112
|
+
def clear(name)
|
|
113
|
+
fetch_cache!(name).clear
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Clears all items from all registered caches.
|
|
117
|
+
def clear_all
|
|
118
|
+
@lock.synchronize { @caches.keys }.each { |name| clear(name) }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns the number of items (including expired) for a given name.
|
|
122
|
+
# @param name [Symbol] registered cache name.
|
|
123
|
+
# @return [Integer]
|
|
124
|
+
def size(name)
|
|
125
|
+
fetch_cache!(name).size
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Stops the cleanup thread.
|
|
129
|
+
def shutdown
|
|
130
|
+
@running = false
|
|
131
|
+
begin
|
|
132
|
+
@cleanup_thread&.wakeup
|
|
133
|
+
rescue ThreadError
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
@cleanup_thread&.join(5)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
def fetch_cache!(name)
|
|
142
|
+
cache = @caches[name]
|
|
143
|
+
raise ArgumentError, "Cache not registered: #{name.inspect}" unless cache
|
|
144
|
+
|
|
145
|
+
cache
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def start_cleanup_thread(interval)
|
|
149
|
+
thread = Thread.new do
|
|
150
|
+
while @running
|
|
151
|
+
sleep(interval)
|
|
152
|
+
remove_expired_items
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
thread.name = 'storage-service-cleanup'
|
|
156
|
+
thread
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def remove_expired_items
|
|
160
|
+
@lock.synchronize { @caches.keys }.each do |name|
|
|
161
|
+
cache = @caches[name]
|
|
162
|
+
next unless cache
|
|
163
|
+
|
|
164
|
+
cache.remove_expired_entries
|
|
165
|
+
rescue StandardError => e
|
|
166
|
+
logger.debug("StorageService cleanup failed for #{name}: #{e.message}")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
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 'logger'
|
|
18
|
+
require_relative '../host/host_info'
|
|
19
|
+
require_relative '../host/host_role'
|
|
20
|
+
require_relative '../host/host_availability'
|
|
21
|
+
require_relative '../logging'
|
|
22
|
+
|
|
23
|
+
module AwsAdvancedRubyDriverWrapper
|
|
24
|
+
module Utils
|
|
25
|
+
# A mixin providing shared utility methods for retrieving and processing single-cluster topology information.
|
|
26
|
+
# Classes that include this module must implement:
|
|
27
|
+
# - #build_hosts(conn, results, initial_host_info, instance_template) => Array<HostInfo> or nil
|
|
28
|
+
module TopologyUtils
|
|
29
|
+
include Logging
|
|
30
|
+
|
|
31
|
+
attr_reader :dialect
|
|
32
|
+
|
|
33
|
+
# Builds a HostInfo from the given topology information.
|
|
34
|
+
#
|
|
35
|
+
# @param instance_id [String, nil] the database instance identifier, e.g. "mydb-instance-1" (Aurora) or "123456789" (Multi-AZ).
|
|
36
|
+
# @param instance_name [String, nil] the database instance name, e.g. "mydb-instance-1" (Aurora and Multi-AZ).
|
|
37
|
+
# @param is_writer [Boolean] true if this is a writer instance.
|
|
38
|
+
# @param weight [Integer] the instance weight for load balancing.
|
|
39
|
+
# @param last_update_time [Time] the timestamp of the last update to this instance's information.
|
|
40
|
+
# @param initial_host_info [AwsAdvancedRubyDriverWrapper::Host::HostInfo] the original host info used for connecting.
|
|
41
|
+
# @param instance_template [AwsAdvancedRubyDriverWrapper::Host::HostInfo] the template used to construct the new HostInfo.
|
|
42
|
+
# @return [AwsAdvancedRubyDriverWrapper::Host::HostInfo] a HostInfo representing the given information.
|
|
43
|
+
def build_host(instance_id, instance_name, is_writer, weight, last_update_time, initial_host_info, instance_template)
|
|
44
|
+
instance_name = '?' if instance_name.nil?
|
|
45
|
+
endpoint = instance_template.host.sub('?', instance_name)
|
|
46
|
+
port = resolve_port(instance_template, initial_host_info)
|
|
47
|
+
role = is_writer ? Host::HostRole::WRITER : Host::HostRole::READER
|
|
48
|
+
|
|
49
|
+
Host::HostInfo.new(
|
|
50
|
+
host: endpoint,
|
|
51
|
+
port:,
|
|
52
|
+
role:,
|
|
53
|
+
availability: Host::HostAvailability::AVAILABLE,
|
|
54
|
+
weight:,
|
|
55
|
+
id: instance_id,
|
|
56
|
+
last_update_time:
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Retrieves a value from a row hash, trying both string and symbol keys.
|
|
61
|
+
def row_value(row, key)
|
|
62
|
+
row[key] || row[key.to_sym]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Query the database for information for each instance in the database topology.
|
|
66
|
+
#
|
|
67
|
+
# @param conn [Object] the connection to use to query the database.
|
|
68
|
+
# @param initial_host_info [AwsAdvancedRubyDriverWrapper::Host::HostInfo] the HostInfo used to initially connect.
|
|
69
|
+
# @param instance_template [AwsAdvancedRubyDriverWrapper::Host::HostInfo] the template HostInfo to use when
|
|
70
|
+
# constructing new HostInfo objects from the data returned by the topology query.
|
|
71
|
+
# @return [Array<AwsAdvancedRubyDriverWrapper::Host::HostInfo>, nil] a list of HostInfo objects representing
|
|
72
|
+
# the results of the topology query, or nil if the query returned unexpected results.
|
|
73
|
+
def query_topology(conn, initial_host_info, instance_template)
|
|
74
|
+
results = @dialect.execute(conn, @dialect.topology_query)
|
|
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. ' \
|
|
78
|
+
'This may occur if the topology query is executed when the server is failing over.')
|
|
79
|
+
return nil
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
verify_writer(build_hosts(conn, results, initial_host_info, instance_template))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# Verifies the writer in the host list. If multiple writers exist, the one with the most recent
|
|
88
|
+
# last_update_time is used as the current writer.
|
|
89
|
+
#
|
|
90
|
+
# @param all_hosts [Array<AwsAdvancedRubyDriverWrapper::Host::HostInfo>, nil] the list of all hosts.
|
|
91
|
+
# @return [Array<AwsAdvancedRubyDriverWrapper::Host::HostInfo>, nil] the verified host list, or nil if no writer found.
|
|
92
|
+
def verify_writer(all_hosts)
|
|
93
|
+
return nil if all_hosts.nil?
|
|
94
|
+
|
|
95
|
+
hosts = []
|
|
96
|
+
writers = []
|
|
97
|
+
|
|
98
|
+
all_hosts.each do |host|
|
|
99
|
+
if host.role == Host::HostRole::WRITER
|
|
100
|
+
writers << host
|
|
101
|
+
else
|
|
102
|
+
hosts << host
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
return nil if writers.empty?
|
|
107
|
+
|
|
108
|
+
if writers.size == 1
|
|
109
|
+
hosts << writers.first
|
|
110
|
+
else
|
|
111
|
+
# Assume the latest updated writer instance is the current writer.
|
|
112
|
+
sorted_writers = writers.sort_by { |w| w.last_update_time || Time.at(0) }.reverse
|
|
113
|
+
hosts << sorted_writers.first
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
hosts
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def resolve_port(instance_template, initial_host_info)
|
|
120
|
+
return instance_template.port if instance_template.port_specified?
|
|
121
|
+
return initial_host_info.port if initial_host_info
|
|
122
|
+
|
|
123
|
+
Host::HostInfo::NO_PORT
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
VERSION = '1.0.0'
|
|
19
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
class WrapperProperty
|
|
19
|
+
attr_reader :name, :default_value, :description, :type
|
|
20
|
+
|
|
21
|
+
def initialize(name, description, default_value: nil, type: nil, validator: nil)
|
|
22
|
+
@name = name.to_sym
|
|
23
|
+
@description = description
|
|
24
|
+
@default_value = default_value
|
|
25
|
+
@type = type
|
|
26
|
+
@validator = validator
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [String, Boolean, Integer, nil] the value from props, or the property's default
|
|
30
|
+
def get(props, override = nil)
|
|
31
|
+
override&.key?(@name) ? override.fetch(@name, @default_value) : props.fetch(@name, @default_value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get_bool(props, override = nil)
|
|
35
|
+
val = get(props, override)
|
|
36
|
+
return val if val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
|
37
|
+
|
|
38
|
+
val.to_s.downcase == 'true'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def get_int(props, override = nil)
|
|
42
|
+
val = get(props, override)
|
|
43
|
+
val.is_a?(Integer) ? val : val.to_i
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_float(props, override = nil)
|
|
47
|
+
val = get(props, override)
|
|
48
|
+
val.is_a?(Float) ? val : val.to_f
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def get_string(props, override = nil)
|
|
52
|
+
val = get(props, override)
|
|
53
|
+
val&.to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def validate!(value)
|
|
57
|
+
@validator&.call(value, @name)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def set(props, value)
|
|
61
|
+
props.put(@name, value)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
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 'aws_advanced_ruby_driver_wrapper/version'
|
|
18
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/custom_configuration'
|
|
19
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/property_definition'
|
|
20
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/logging'
|
|
21
|
+
# Error classes are loaded up front so they can be named before any connection is opened, for
|
|
22
|
+
# example in a Rails `rescue_from` or ActiveJob `retry_on`, which are evaluated at class load.
|
|
23
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/errors'
|
|
24
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/errors'
|
|
25
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/utils/rds_utils'
|
|
26
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/utils/connection_config'
|
|
27
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/utils/connection_config_parser'
|
|
28
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/monitoring/monitor_state'
|
|
29
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/monitoring/monitor'
|
|
30
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin'
|
|
31
|
+
|
|
32
|
+
module AwsAdvancedRubyDriverWrapper
|
|
33
|
+
@config = Configuration.new
|
|
34
|
+
|
|
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
|
|
38
|
+
# required when a connection is actually opened.
|
|
39
|
+
autoload :WrapperPgConnection, 'aws_advanced_ruby_driver_wrapper/postgresql'
|
|
40
|
+
autoload :WrapperMysql2Client, 'aws_advanced_ruby_driver_wrapper/mysql'
|
|
41
|
+
|
|
42
|
+
# Other public entry points are autoloaded for the same reason, so they work from code that runs
|
|
43
|
+
# before any connection is opened, such as a Rails initializer or a setup script.
|
|
44
|
+
module Services
|
|
45
|
+
autoload :HostService, 'aws_advanced_ruby_driver_wrapper/services/host_service'
|
|
46
|
+
autoload :PluginManager, 'aws_advanced_ruby_driver_wrapper/services/plugin_manager'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module Plugins
|
|
50
|
+
module Encryption
|
|
51
|
+
autoload :EncryptionConfig, 'aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/encryption_config'
|
|
52
|
+
autoload :KeyManagementUtility, 'aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class << self
|
|
57
|
+
attr_reader :config
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Gracefully tears down all background resources. Invoked by the at_exit hook (and thus
|
|
61
|
+
# indirectly by the TERM/INT signal traps, which just exit). Safe to call more than once.
|
|
62
|
+
def self.shutdown(grace_period_sec: 10)
|
|
63
|
+
Plugins::BlueGreen::BlueGreenPlugin.clean_up_providers
|
|
64
|
+
release_resources(grace_period_sec: grace_period_sec)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.clear_caches
|
|
68
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/services/service_utility'
|
|
69
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/services/host_service'
|
|
70
|
+
Services::CoreServices.storage_service.clear_all
|
|
71
|
+
Utils::RdsUtils.clear_cache
|
|
72
|
+
Services::DialectService.known_endpoint_dialects.clear
|
|
73
|
+
Services::HostService.clear_id_cache
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.release_resources(grace_period_sec: 5)
|
|
77
|
+
require_relative 'aws_advanced_ruby_driver_wrapper/services/service_utility'
|
|
78
|
+
Services::CoreServices.monitor_service.shutdown(grace_period: grace_period_sec)
|
|
79
|
+
Services::CoreServices.event_publisher.release_resources
|
|
80
|
+
clear_caches
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Register signal traps and at_exit hook for graceful shutdown. The traps only exit — the real
|
|
85
|
+
# teardown runs in the at_exit hook, since acquiring locks / joining threads inside a signal-trap
|
|
86
|
+
# context is unsafe in Ruby and can deadlock.
|
|
87
|
+
%w[TERM INT].each { |signal| trap(signal) { exit(0) } }
|
|
88
|
+
|
|
89
|
+
at_exit { AwsAdvancedRubyDriverWrapper.shutdown }
|
|
90
|
+
|
|
91
|
+
# Register adapters with ActiveRecord via a lazy-load hook so the require order between this file and
|
|
92
|
+
# ActiveRecord does not matter. The block runs the first time ActiveRecord::Base is referenced, whether
|
|
93
|
+
# ActiveRecord is loaded before or after this file. The register call is itself lazy — each adapter file
|
|
94
|
+
# is only loaded when a connection using that adapter is first established, so users of a single adapter
|
|
95
|
+
# never load the other.
|
|
96
|
+
begin
|
|
97
|
+
require 'active_support/lazy_load_hooks'
|
|
98
|
+
rescue LoadError
|
|
99
|
+
# ActiveSupport is absent (raw-driver-only usage with no ActiveRecord); there is nothing to register.
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
|
|
103
|
+
ActiveSupport.on_load(:active_record) do
|
|
104
|
+
ActiveRecord::ConnectionAdapters.register(
|
|
105
|
+
'aws_postgresql',
|
|
106
|
+
'ActiveRecord::ConnectionAdapters::AwsPostgreSQLAdapter',
|
|
107
|
+
'aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
ActiveRecord::ConnectionAdapters.register(
|
|
111
|
+
'aws_mysql2',
|
|
112
|
+
'ActiveRecord::ConnectionAdapters::AwsMysql2Adapter',
|
|
113
|
+
'aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter'
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|