aws_advanced_ruby_driver_wrapper 1.0.1 → 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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -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_postgresql_adapter.rb +17 -3
  7. data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb +80 -0
  8. data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +1 -1
  9. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +43 -0
  10. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +11 -4
  11. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb +129 -0
  12. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +9 -91
  13. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +18 -0
  14. data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb +118 -0
  15. data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +16 -0
  16. data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +10 -5
  17. data/lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb +127 -0
  18. data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +1 -0
  19. data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +1 -0
  20. data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +27 -9
  21. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +115 -7
  22. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb +84 -0
  23. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +3 -1
  24. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +7 -0
  25. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +68 -41
  26. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +4 -2
  27. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +5 -3
  28. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +7 -1
  29. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +1 -1
  30. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +6 -13
  31. data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +90 -3
  32. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +11 -1
  33. data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +4 -1
  34. data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +14 -3
  35. data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +68 -3
  36. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb +266 -0
  37. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb +134 -0
  38. data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb +113 -0
  39. data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +30 -9
  40. data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +16 -2
  41. data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +4 -1
  42. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +6 -3
  43. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +13 -4
  44. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +29 -6
  45. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql +108 -0
  46. data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql +54 -0
  47. data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +14 -0
  48. data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +41 -23
  49. data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +63 -1
  50. data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +3 -0
  51. data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +20 -7
  52. data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +34 -8
  53. data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +1 -1
  54. data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +80 -29
  55. data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +10 -2
  56. data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +4 -1
  57. data/lib/aws_advanced_ruby_driver_wrapper/trilogy.rb +167 -0
  58. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +1 -1
  59. data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +25 -15
  60. data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +2 -2
  61. data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +13 -4
  62. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +15 -31
  63. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +55 -76
  64. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb +215 -0
  65. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +11 -20
  66. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +2 -3
  67. data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +21 -14
  68. data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +2 -1
  69. data/lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb +133 -0
  70. data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +9 -5
  71. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb +89 -0
  72. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb +124 -0
  73. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_counter.rb +39 -0
  74. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb +122 -0
  75. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb +36 -0
  76. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb +50 -0
  77. data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb +143 -0
  78. data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +9 -2
  79. data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
  80. data/lib/aws_advanced_ruby_driver_wrapper.rb +9 -2
  81. metadata +54 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6da8d07797b41d2bef7c26ac10bff8a3fcf6050d098344d3e850cf80d88305a9
4
- data.tar.gz: 2f17adb4cca840143bacbf16056d67748f12204f22a5beb71ddb8bdc445aca3e
3
+ metadata.gz: b3f6f4cf5575f7126636ad09c23b81a3feec7544b36c7fd3a1d13cb159f0978d
4
+ data.tar.gz: e5053d0035262786e689706ecc48788fd031c06b4144f2cc3e15e0dba2d44589
5
5
  SHA512:
6
- metadata.gz: dc3f77408c42d2a2dde71cce86af1c0bb294380b6e7c679c51118e0fd2383f4d677e95d77521cbe974bf3c584e5f7af7b65244834a0489034d7ab9541982dcc6
7
- data.tar.gz: fcfaa69564b9abfeed8095e5995a9893a636def8ea0f8c1ad471bbcf69a0f36f7593090b42f76083556c7ee834350238bc73c8e090408572ccf78b8a01ee858f
6
+ metadata.gz: 8c3bfe267a552d4542b4b89944c76f35442ffbe1a16fde107126660b8aa0e352f932353fba29e67029db860fda83aea0c3acace10c3997a4a50b7b0bc89d0652
7
+ data.tar.gz: fe7c1b9e226219d8740daa00f0f101004e3c869044cac2b7b950a8cf6447c6ebc9ac418c2fcc30ea3c86767d72cb9091ce18c587d19fbae4663d174fd20f98b5
data/CHANGELOG.md CHANGED
@@ -3,6 +3,35 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/#semantic-versioning-200).
5
5
 
6
+ ## [1.1.0] - 2026-11-05
7
+
8
+ ### :magic_wand: Added
9
+ - [Federated Authentication Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/federated-auth), which authenticates with Active Directory Federation Services (AD FS), exchanges the resulting SAML assertion for temporary AWS credentials via STS, and connects to the database with an RDS IAM authentication token. Enabled with the `federated_auth` plugin code ([PR #207](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/207)).
10
+ - [Okta Authentication Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/okta-auth), which uses the same SAML-to-STS flow as AD FS but against Okta, is also available via the `okta` plugin code ([PR #215](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/215)).
11
+ - [Telemetry](https://aws.github.io/aws-advanced-wrapper-docs/ruby/telemetry) through OpenTelemetry. With `enable_telemetry` set, the wrapper records traces of each wrapper call, the plugins it passes through, and the driver, plus failover, Blue/Green switchover, and authentication spans, and metrics such as failover and token fetch counts. Traces and metrics are sent wherever the application's OpenTelemetry SDK exports them. The OpenTelemetry gems are optional dependencies ([PR #220](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/220), [PR #225](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/225)).
12
+ - Support for the [`trilogy`](https://rubygems.org/gems/trilogy) MySQL driver, through the `WrapperTrilogyClient` connection class and the drop-in `aws_trilogy` ActiveRecord adapter. The KMS Encryption Plugin is not supported with `trilogy` ([PR #203](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/203)).
13
+ - The [Blue/Green Deployment plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/blue-green) now invalidates connections that were opened to the old blue environment before a switchover, controlled by the new `bg_drop_blue_connections` property (default `true`). Once a switchover is confirmed, each such connection is closed the next time it is used, so with the failover plugin enabled it fails over through Blue/Green routing and raises `FailoverSuccessError` (or `TransactionStateUnknownError` inside a transaction), and without failover the driver raises its closed-connection error ([PR #223](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/223)).
14
+ - AI assistant skills for the wrapper, in the repository under [`skills/`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills): a [configuration assistant](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills/ruby-wrapper-configuration-assistant) that builds a working configuration through an interview, reviews existing configurations, and answers parameter and plugin questions, and a [troubleshooting assistant](https://github.com/aws/aws-advanced-ruby-driver-wrapper/tree/main/skills/ruby-wrapper-troubleshooting-assistant) that diagnoses errors and unexpected behavior and classifies the cause as configuration, environment, wrapper bug, or not the wrapper. Both are self-contained and grounded in the wrapper source and the official Ruby docs ([PR #214](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/214), [PR #219](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/219), [PR #233](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/233), [PR #237](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/237), [PR #239](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/239)).
15
+
16
+ ### :crab: Changed
17
+ - Simplified the KMS Encryption Plugin's PostgreSQL trigger SQL to read the column's HMAC key from `key_storage` for every row. Re-run the trigger SQL from the [documentation](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/kms-encryption#postgresql-1) to update existing deployments ([PR #216](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/216)).
18
+ - The KMS Encryption Plugin's trigger SQL now ships with the gem and is stamped with its version, so deployed triggers can be checked against the version in use ([PR #218](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/218)).
19
+ - With `mysql2` (`WrapperMysql2Client` and the `aws_mysql2` ActiveRecord adapter), the failover plugin now fails over on a `read_timeout`, when MySQL 8.0.24+ disconnects a connection that exceeded `wait_timeout` (error 4031), and on a lost connection reported as error 2055 (`CR_SERVER_LOST_EXTENDED`), matching `trilogy`. Before, none of these triggered failover: a `read_timeout` raised `Mysql2::Error::TimeoutError` (`ActiveRecord::AdapterTimeout` under `aws_mysql2`), and errors 4031 and 2055 were raised as-is (`ActiveRecord::ConnectionFailed` under `aws_mysql2`, which ActiveRecord answered by reconnecting to the original endpoint and retrying queries it considers retryable). **Behavior change:** these errors now fail over and raise `FailoverSuccessError` (or `TransactionStateUnknownError` inside a transaction), which ActiveRecord does not retry. This includes:
20
+ - a query that runs longer than `read_timeout`. Set `read_timeout` higher than your slowest expected query.
21
+ - the first query on a pooled connection that sat idle longer than the server's `wait_timeout`. Raise `wait_timeout`, or have the pool reap idle connections sooner (for example with ActiveRecord's `idle_timeout`).
22
+
23
+ Lock wait timeouts (error 1205) still do not trigger failover ([PR #234](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/234)).
24
+ - Declared `bigdecimal` and `logger` as runtime dependencies, since Ruby no longer installs them by default from 3.4 (`bigdecimal`) and 4.0 (`logger`) on, and dropped the need for `base64` and the full `cgi` library. This keeps a bundle that does not otherwise include them, such as an app using the drivers without ActiveRecord, from failing to load the wrapper ([PR #224](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/224)).
25
+
26
+ ### :bug: Fixed
27
+ - Fixed the Custom Endpoint Plugin signing its RDS API calls with the default credential chain instead of the configured `aws_credentials_provider`, so a custom endpoint could not be resolved in an account reachable only through the configured credentials ([PR #205](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/205)).
28
+ - Fixed an unknown host selection strategy being accepted at configuration time and only failing later during connection use. An invalid strategy is now rejected when the connection is set up ([PR #206](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/206)).
29
+ - Fixed `iam_access_token_property_name`, `cluster_id`, and `bgd_id` not accepting YAML-typed (non-string) values from `database.yml`, such as a numeric `cluster_id` ([PR #209](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/209)).
30
+ - Fixed the block form of `pg`'s `exec`, `query`, `exec_params`, and `exec_prepared` not working through `WrapperPgConnection`. The wrapper now yields the result to the block, clears it when the block returns, and returns the block's value, matching `pg` ([PR #221](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/221)).
31
+ - Fixed the cluster topology and custom endpoint monitors stopping when their stored data was read, which could leave the wrapper with a stale topology so failover could not find the new writer ([PR #226](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/226)).
32
+ - Fixed the KMS Encryption Plugin matching MySQL placeholders to the wrong encrypted columns when the statement contained comments, so values could be encrypted against the wrong column ([PR #227](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/227)).
33
+ - Fixed several ActiveRecord error-handling gaps: a `nil` connection is now recognized as a connection error; a `pg` IAM authentication failure is classified as a connection error rather than `ActiveRecord::NoDatabaseError`; `trilogy` schema errors are identified correctly; and `ping` and `close` now match the underlying driver's behavior ([PR #228](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/228)).
34
+
6
35
  ## [1.0.1] - 2026-10-07
7
36
 
8
37
  ### :bug: Fixed
@@ -35,5 +64,6 @@ The Amazon Web Services (AWS) Advanced Ruby Driver Wrapper allows an application
35
64
  - [Initial Connection Strategy Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/initial-connection-strategy).
36
65
  - [KMS Encryption Plugin](https://aws.github.io/aws-advanced-wrapper-docs/ruby/using-plugins/kms-encryption).
37
66
 
38
- [1.0.1]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/1.0.1
39
- [1.0.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/1.0.0
67
+ [1.1.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.1.0
68
+ [1.0.1]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.0.1
69
+ [1.0.0]: https://github.com/aws/aws-advanced-ruby-driver-wrapper/releases/tag/v1.0.0
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  The **AWS Advanced Ruby Driver Wrapper** is complementary to an existing Ruby database driver and aims to extend the functionality of the driver to enable applications to take full advantage of the features of clustered databases such as Amazon Aurora. In other words, the AWS Advanced Ruby Driver Wrapper does not connect directly to any database, but enables support of AWS and Aurora functionalities on top of an underlying Ruby driver of the user's choice. This approach enables service-specific enhancements without requiring users to change their workflow with their existing Ruby drivers and tooling.
6
6
 
7
- The wrapper integrates with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) by providing drop-in `aws_mysql2` and `aws_postgresql` adapters that sit on top of the community [`mysql2`](https://rubygems.org/gems/mysql2) and [`pg`](https://rubygems.org/gems/pg) drivers.
7
+ The wrapper integrates with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) by providing drop-in `aws_mysql2`, `aws_trilogy` and `aws_postgresql` adapters that sit on top of the community [`mysql2`](https://rubygems.org/gems/mysql2), [`trilogy`](https://rubygems.org/gems/trilogy) and [`pg`](https://rubygems.org/gems/pg) drivers.
8
8
 
9
9
  ## About the Wrapper
10
10
 
@@ -54,10 +54,12 @@ Add this line to your application's Gemfile:
54
54
  gem 'aws_advanced_ruby_driver_wrapper'
55
55
  ```
56
56
 
57
- For MySQL users, also install the underlying driver:
57
+ For MySQL users, also install one of the underlying drivers:
58
58
 
59
59
  ```ruby
60
60
  gem 'mysql2'
61
+ # or
62
+ gem 'trilogy'
61
63
  ```
62
64
 
63
65
  For PostgreSQL users, also install the underlying driver:
@@ -74,14 +76,17 @@ bundle install
74
76
 
75
77
  ## Getting Started
76
78
 
77
- The wrapper registers two ActiveRecord adapters — `aws_mysql2` and `aws_postgresql` — that are drop-in replacements for the standard `mysql2` and `postgresql` adapters.
79
+ The wrapper registers three ActiveRecord adapters — `aws_mysql2`, `aws_trilogy` and `aws_postgresql` — that are drop-in replacements for the standard `mysql2`, `trilogy` and `postgresql` adapters.
78
80
 
79
81
  Require the appropriate entry point for your database:
80
82
 
81
83
  ```ruby
82
- # For MySQL
84
+ # For MySQL with mysql2
83
85
  require 'aws_advanced_ruby_driver_wrapper/mysql'
84
86
 
87
+ # For MySQL with trilogy
88
+ require 'aws_advanced_ruby_driver_wrapper/trilogy'
89
+
85
90
  # For PostgreSQL
86
91
  require 'aws_advanced_ruby_driver_wrapper/postgresql'
87
92
  ```
@@ -89,7 +94,7 @@ require 'aws_advanced_ruby_driver_wrapper/postgresql'
89
94
  Then set the adapter in your database configuration (for example, `config/database.yml` in a Rails application):
90
95
 
91
96
  ```yaml
92
- # MySQL
97
+ # MySQL (use aws_trilogy with the trilogy driver)
93
98
  production:
94
99
  adapter: aws_mysql2
95
100
  host: my-cluster.cluster-xxxx.us-east-1.rds.amazonaws.com
@@ -106,6 +111,105 @@ production:
106
111
  password: <password>
107
112
  ```
108
113
 
114
+ This is a minimal configuration. To add failover tuning, IAM or Secrets Manager authentication, TLS, and other plugins for your deployment, see the [documentation](#documentation), or [let an AI assistant build the configuration with you](#configuring-the-wrapper-with-ai-tools).
115
+
116
+ ### Configuring the Wrapper with AI Tools
117
+
118
+ If you use an AI assistant (Kiro, Cursor, Claude Code, GitHub Copilot, ChatGPT, Amazon Bedrock, etc.), you can give it the wrapper's configuration assistant skill to help build, review, or troubleshoot your wrapper configuration.
119
+
120
+ The skill is a single self-contained markdown file, [`skills/ruby-wrapper-configuration-assistant/SKILL.md`](./skills/ruby-wrapper-configuration-assistant/SKILL.md). It covers every plugin, parameter, default value, dialect, failover mode, and compatibility constraint, so the AI can answer configuration questions without access to the wrapper source. It follows the [Agent Skills](https://agentskills.io) format. It is about 65,000 tokens on Claude Opus 5.5 and Sonnet 5.5 (other models count tokens differently). How much of that you pay for depends on how you add it:
121
+
122
+ - **Tools that support Agent Skills** load only the skill's name and description (about 100 tokens) until a request needs the skill. They then load the full file, and it stays in context for the rest of that conversation.
123
+ - **A system prompt, or a file pasted into a chat,** sends the full file with every message.
124
+
125
+ Once the full file is in context, it is sent again with each message, so tools that cache prompts handle it most cheaply.
126
+
127
+ #### Quick start
128
+
129
+ 1. Download or copy [`SKILL.md`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/blob/v1.1.0/skills/ruby-wrapper-configuration-assistant/SKILL.md) from the latest release, or the whole `skills/ruby-wrapper-configuration-assistant` folder. The copy on `main` can describe changes that aren't released yet; it marks them `[Unreleased]`, and the AI won't recommend them for a released gem version.
130
+ 2. Add it to your AI tool:
131
+ - **Tools that support Agent Skills** (Kiro, Cursor, Claude Code, GitHub Copilot in VS Code, and others): copy the `ruby-wrapper-configuration-assistant` folder (or create a folder with that name and save `SKILL.md` in it) into one of the tool's skills directories. The folder name must match the `name` field at the top of the file (`ruby-wrapper-configuration-assistant`), as the Agent Skills format requires; a tool may not load the skill if they differ.
132
+
133
+ | Tool | Project skills directory | User skills directory |
134
+ |---|---|---|
135
+ | Kiro | `.kiro/skills/` | `~/.kiro/skills/` |
136
+ | Cursor | `.cursor/skills/`, `.agents/skills/`, or `.claude/skills/` | `~/.cursor/skills/`, `~/.agents/skills/`, or `~/.claude/skills/` |
137
+ | Claude Code | `.claude/skills/` | `~/.claude/skills/` |
138
+ | GitHub Copilot in VS Code | `.github/skills/`, `.agents/skills/`, or `.claude/skills/` | `~/.copilot/skills/`, `~/.agents/skills/`, or `~/.claude/skills/` |
139
+
140
+ For example, to add the skill to a project for Claude Code:
141
+
142
+ ```bash
143
+ mkdir -p .claude/skills/ruby-wrapper-configuration-assistant
144
+ curl -fsSL -o .claude/skills/ruby-wrapper-configuration-assistant/SKILL.md \
145
+ https://raw.githubusercontent.com/aws/aws-advanced-ruby-driver-wrapper/v1.1.0/skills/ruby-wrapper-configuration-assistant/SKILL.md
146
+ ```
147
+
148
+ - **Claude Projects**: upload it as a project knowledge document. Claude reads project knowledge in full while it fits in the context window, but when a project's knowledge approaches that limit, Claude switches to searching it for passages that match each question, so the model may miss the instructions and cross-references the skill depends on. Keep the project's other knowledge small, or use a separate project.
149
+ - **ChatGPT custom GPT**: a custom GPT searches its knowledge files and passes the model only the passages that match each question, so the model may miss the instructions and cross-references the skill depends on. Paste the file into a plain chat instead (below).
150
+ - **Amazon Bedrock**: send the file as the system prompt of your `InvokeModel` or `Converse` request. Avoid attaching it to a Bedrock knowledge base: a knowledge base passes the model only the passages that match each question, so the model misses the instructions and cross-references the skill depends on.
151
+ - **Plain chat (ChatGPT, Claude, Gemini)**: paste it at the start of a new conversation, then ask your question. Start a new conversation for each new question: in a long conversation the pasted skill can be pushed out of the model's context, and ChatGPT drops the oldest messages first. In ChatGPT, the file is about 40,000 tokens, which is more than the Free plan's context window and leaves little room on the Go and Plus plans' Instant models, so choose a Thinking model in the model picker or use the Pro plan.
152
+ 3. Ask the AI for help. It will interview you when it needs more details, or give you a configuration straight away if you ask it to skip the interview.
153
+
154
+ #### Example prompts
155
+
156
+ The simplest way to start:
157
+
158
+ ```
159
+ Help me configure the AWS Advanced Ruby Driver Wrapper for my Rails app.
160
+ ```
161
+
162
+ Skip the interview when you already know what you want:
163
+
164
+ ```
165
+ Give me a default config/database.yml for Rails on Aurora PostgreSQL with failover and IAM authentication.
166
+ ```
167
+
168
+ Review an existing configuration:
169
+
170
+ ```
171
+ Review this database.yml entry and tell me what to change:
172
+
173
+ <paste your database.yml entry, or the Ruby code that opens the connection>
174
+ ```
175
+
176
+ Diagnose a configuration error:
177
+
178
+ ```
179
+ My Rails app on aws_postgresql fails at startup with "The failover plugin is not compatible with RDS Proxy endpoints".
180
+ What's wrong with my database.yml?
181
+ ```
182
+
183
+ The skill targets wrapper version 1.0.1 and later. If it doesn't know something, it says so and points you to the [Ruby wrapper documentation](https://aws.github.io/aws-advanced-wrapper-docs/ruby/overview).
184
+
185
+ ### Troubleshooting the Wrapper with AI Tools
186
+
187
+ A second skill, the troubleshooting assistant, helps an AI assistant find out why the wrapper isn't doing what you expect: installation and load errors, connection setup errors, IAM, Secrets Manager, AD FS and Okta authentication failures, failover that doesn't happen or fails, Active Record integration problems, the trilogy driver, Blue/Green, custom endpoints, Global Database, KMS encryption, telemetry, and performance. It works out whether the cause is your configuration, your environment (network, AWS permissions, TLS), a wrapper bug, or something outside the wrapper, helps you narrow it down and read the wrapper's logs, and drafts an issue report when the problem needs one.
188
+
189
+ The skill is [`skills/ruby-wrapper-troubleshooting-assistant/SKILL.md`](https://github.com/aws/aws-advanced-ruby-driver-wrapper/blob/v1.1.0/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md) (link to the latest release), about 30,000 tokens on Claude Opus 5.5 and Sonnet 5.5 (about 20,000 in ChatGPT). The two skills are independent: install either one or both. Add it to your AI tool the same way as the configuration assistant (see [Quick start](#quick-start)), using the folder name `ruby-wrapper-troubleshooting-assistant`. For example, for Claude Code:
190
+
191
+ ```bash
192
+ mkdir -p .claude/skills/ruby-wrapper-troubleshooting-assistant
193
+ curl -fsSL -o .claude/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md \
194
+ https://raw.githubusercontent.com/aws/aws-advanced-ruby-driver-wrapper/v1.1.0/skills/ruby-wrapper-troubleshooting-assistant/SKILL.md
195
+ ```
196
+
197
+ Then describe the problem, and include the error message and backtrace if you have one. Remove passwords and other secrets from anything you paste.
198
+
199
+ ```
200
+ My Rails app on Aurora PostgreSQL gets AwsAdvancedRubyDriverWrapper::Errors::FailoverSuccessError
201
+ a few times a day, but there's no failover in the RDS events. What's going on?
202
+ ```
203
+
204
+ ```
205
+ Failover fails with "The request to discover the new topology timed out or was unsuccessful".
206
+ Here are the wrapper's debug logs:
207
+
208
+ <paste the logs>
209
+ ```
210
+
211
+ The skill targets wrapper version 1.0.1 and later.
212
+
109
213
  ## Documentation
110
214
 
111
215
  Technical documentation regarding the functionality of the AWS Advanced Ruby Driver Wrapper is published at the [AWS Advanced Wrapper documentation site](https://aws.github.io/aws-advanced-wrapper-docs/ruby/overview). Since the wrapper requires an underlying Ruby driver, please refer to the individual driver's documentation for driver-specific information.
@@ -128,6 +232,11 @@ Technical documentation regarding the functionality of the AWS Advanced Ruby Dri
128
232
 
129
233
  ### Known Limitations
130
234
 
235
+ #### Trilogy MySQL Driver
236
+
237
+ - The KMS Encryption Plugin is not supported with `trilogy`, which has no prepared statements, so a bind parameter could only reach the server in plaintext. The plugin refuses to start on a `trilogy` connection.
238
+ - To authenticate with an IAM token, set `enable_cleartext_plugin: true` (and `ssl_mode`), since `trilogy` only sends the token with `mysql_clear_password` when that option is set.
239
+
131
240
  #### Amazon RDS Blue/Green Deployments
132
241
 
133
242
  Support for Blue/Green deployments using the wrapper requires specific metadata tables. Please refer to the plugin documentation for the supported database engine versions.
@@ -137,7 +246,7 @@ Support for Blue/Green deployments using the wrapper requires specific metadata
137
246
  If you encounter a bug with the AWS Advanced Ruby Driver Wrapper, we would like to hear about it.
138
247
  Please search the [existing issues](https://github.com/aws/aws-advanced-ruby-driver-wrapper/issues) to see if others are also experiencing the issue before reporting the problem in a new issue. GitHub issues are intended for bug reports and feature requests.
139
248
 
140
- When opening a new issue, please fill in all required fields in the issue template to help expedite the investigation process.
249
+ When opening a new issue, please fill in all required fields in the issue template to help expedite the investigation process. The [troubleshooting assistant skill](#troubleshooting-the-wrapper-with-ai-tools) can help you find the cause first, and draft the issue if it turns out to be a bug.
141
250
 
142
251
  For all other questions, please use [GitHub discussions](https://github.com/aws/aws-advanced-ruby-driver-wrapper/discussions).
143
252
 
data/THIRD-PARTY-LICENSES CHANGED
@@ -3,10 +3,10 @@ following third-party software. The applicable licenses and notices are
3
3
  reproduced below. Each dependency remains under its own license; nothing in
4
4
  this file modifies those terms.
5
5
 
6
- The underlying database drivers (pg, mysql2), ActiveRecord, pg_query, and the
7
- AWS SDK gems are optional dependencies that are installed by the user as needed;
8
- they are listed here because the wrapper is designed to load and run on top of
9
- them.
6
+ The underlying database drivers (pg, mysql2, trilogy), ActiveRecord, pg_query,
7
+ the OpenTelemetry gems, and the AWS SDK gems are optional dependencies that are
8
+ installed by the user as needed; they are listed here because the wrapper is
9
+ designed to load and run on top of them.
10
10
 
11
11
  ===============================================================================
12
12
 
@@ -40,6 +40,19 @@ SOFTWARE.
40
40
 
41
41
  -----------
42
42
 
43
+ The following Ruby gems are required runtime dependencies of this product.
44
+ Ruby no longer installs them by default from Ruby 3.4 (bigdecimal) and 4.0
45
+ (logger) on, so the wrapper declares them explicitly:
46
+
47
+ - bigdecimal@4.1.3
48
+ - logger@1.7.0
49
+
50
+ These packages are each distributed under the same Ruby license reproduced
51
+ below for the `pg` gem (the Ruby license or, at your option, the 2-clause
52
+ BSDL).
53
+
54
+ -----------
55
+
43
56
  The following Ruby gem may be used with this product (ActiveRecord adapters):
44
57
 
45
58
  - activerecord@8.1.4
@@ -131,9 +144,41 @@ SOFTWARE.
131
144
 
132
145
  -----------
133
146
 
147
+ The following Ruby gem may be used with this product (alternative MySQL driver;
148
+ the KMS Encryption plugin is not supported with trilogy):
149
+
150
+ - trilogy@2.13.2
151
+
152
+ This package contains the following license and notice below:
153
+
154
+ Copyright (c) 2012-2021 GitHub, Inc.
155
+
156
+ Permission is hereby granted, free of charge, to any person
157
+ obtaining a copy of this software and associated documentation
158
+ files (the "Software"), to deal in the Software without
159
+ restriction, including without limitation the rights to use,
160
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
161
+ copies of the Software, and to permit persons to whom the
162
+ Software is furnished to do so, subject to the following
163
+ conditions:
164
+
165
+ The above copyright notice and this permission notice shall be
166
+ included in all copies or substantial portions of the Software.
167
+
168
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
169
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
170
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
171
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
172
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
173
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
174
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
175
+ OTHER DEALINGS IN THE SOFTWARE.
176
+
177
+ -----------
178
+
134
179
  The following Ruby gem may be used with this product (PostgreSQL driver):
135
180
 
136
- - pg@1.6.3
181
+ - pg@1.7.0
137
182
 
138
183
  This package contains the following license and notice below:
139
184
 
@@ -224,7 +269,7 @@ SUCH DAMAGE.
224
269
  The following Ruby gem may be used with this product (SQL statement parsing
225
270
  for the KMS Encryption plugin):
226
271
 
227
- - pg_query@6.2.3
272
+ - pg_query@6.2.5
228
273
 
229
274
  This package contains the following license and notice below:
230
275
 
@@ -259,13 +304,27 @@ POSSIBILITY OF SUCH DAMAGE.
259
304
 
260
305
  -----------
261
306
 
307
+ The following OpenTelemetry for Ruby gems may be used with this product
308
+ (telemetry, when `enable_telemetry` is set). The wrapper loads these API gems;
309
+ the OpenTelemetry SDK and exporters that actually emit the traces and metrics
310
+ are supplied by the application:
311
+
312
+ - opentelemetry-api@1.11.1
313
+ - opentelemetry-metrics-api@0.10.0
314
+
315
+ These packages are each licensed under the Apache License, Version 2.0,
316
+ reproduced below (following the AWS SDK gems).
317
+
318
+ -----------
319
+
262
320
  The following AWS SDK for Ruby gems may be used with this product (AWS IAM
263
- Authentication, AWS Secrets Manager, Custom Endpoint, and KMS Encryption
264
- plugins):
321
+ Authentication, AWS Secrets Manager, Custom Endpoint, Federated Authentication,
322
+ Okta Authentication, and KMS Encryption plugins):
265
323
 
266
- - aws-sdk-kms@1.132.0
267
- - aws-sdk-rds@1.323.0
268
- - aws-sdk-secretsmanager@1.136.0
324
+ - aws-sdk-core@3.263.0
325
+ - aws-sdk-kms@1.138.0
326
+ - aws-sdk-rds@1.329.0
327
+ - aws-sdk-secretsmanager@1.141.0
269
328
 
270
329
  These packages are each licensed under the Apache License, Version 2.0,
271
330
  reproduced below:
@@ -53,7 +53,12 @@ Gem::Specification.new do |spec|
53
53
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
54
54
  spec.require_paths = ['lib']
55
55
 
56
+ # The wrapper requires bigdecimal and logger, and Ruby no longer installs them by default from 3.4
57
+ # (bigdecimal) and 4.0 (logger) on. Declaring them keeps a bundle that does not otherwise include
58
+ # them, such as an app using the drivers without Active Record, from failing to load the wrapper.
59
+ spec.add_dependency 'bigdecimal'
56
60
  spec.add_dependency 'concurrent-ruby', '~> 1.3', '>= 1.3.7'
61
+ spec.add_dependency 'logger'
57
62
 
58
63
  spec.post_install_message = <<~MSG
59
64
  ═══════════════════════════════════════════════════════════════
@@ -63,6 +68,10 @@ Gem::Specification.new do |spec|
63
68
  gem install mysql2
64
69
  require 'aws_advanced_ruby_driver_wrapper/mysql'
65
70
 
71
+ To use with MySQL through trilogy:
72
+ gem install trilogy
73
+ require 'aws_advanced_ruby_driver_wrapper/trilogy'
74
+
66
75
  To use with PostgreSQL:
67
76
  gem install pg
68
77
  require 'aws_advanced_ruby_driver_wrapper/postgresql'
@@ -63,23 +63,37 @@ module ActiveRecord
63
63
  superclass.native_database_types.merge(datetime: NATIVE_DATABASE_TYPES[datetime_type])
64
64
  end
65
65
 
66
+ # SQLSTATEs and FATAL-message signals for an authentication/authorization rejection (invalid
67
+ # password, PAM failure, pg_hba.conf rejection). A failed *connect* usually carries no result, so
68
+ # the message text is the reliable signal and the SQLSTATE is only a bonus when one is present.
69
+ AUTH_REJECTION_SQLSTATES = %w[28P01 28000].freeze
70
+ AUTH_REJECTION_MESSAGE = /password authentication failed|PAM authentication failed|pg_hba\.conf/
71
+
66
72
  # Note that this config includes wrapper properties.
67
73
  #
68
- # Translates connection errors the same way the parent adapter does, so ActiveRecord can tell a
69
- # missing database (which db:prepare creates) or rejected credentials from other failures.
74
+ # Mirrors the parent PostgreSQLAdapter.new_client so ActiveRecord can tell a missing database
75
+ # (which db:prepare creates) or rejected credentials from other failures.
70
76
  def self.new_client(config)
71
77
  AwsAdvancedRubyDriverWrapper::WrapperPgConnection.new(**config)
72
78
  rescue ::PG::Error => e
73
79
  dbname, user, host = config.values_at(:dbname, :user, :host)
74
80
  # The postgres maintenance database always exists, so a failure there is not a missing database.
75
81
  raise ActiveRecord::ConnectionNotEstablished, e.message if dbname == 'postgres'
76
- raise ActiveRecord::NoDatabaseError.db_error(dbname) if dbname && e.message.include?(dbname)
82
+ raise ActiveRecord::NoDatabaseError.db_error(dbname) if dbname && e.message.include?(dbname) && !auth_rejection?(e)
77
83
  raise ActiveRecord::DatabaseConnectionError.username_error(user) if user && e.message.include?(user)
78
84
  raise ActiveRecord::DatabaseConnectionError.hostname_error(host) if host && e.message.include?(host)
79
85
 
80
86
  raise ActiveRecord::ConnectionNotEstablished, e.message
81
87
  end
82
88
 
89
+ # @return [Boolean] whether the PG error is an authentication/authorization rejection, by SQLSTATE
90
+ # when the error carries a result and otherwise by its canonical FATAL text.
91
+ def self.auth_rejection?(error)
92
+ sqlstate = error.result&.error_field(PG::PG_DIAG_SQLSTATE)
93
+ AUTH_REJECTION_SQLSTATES.include?(sqlstate) || error.message.match?(AUTH_REJECTION_MESSAGE)
94
+ end
95
+ private_class_method :auth_rejection?
96
+
83
97
  def connect
84
98
  @connection_broken = false
85
99
  # Override @connection_parameters with the full config so the parent's
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License").
6
+ # You may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_record/connection_adapters/trilogy_adapter'
18
+ require_relative '../trilogy'
19
+ require_relative '../errors'
20
+ require_relative 'type_adapter_alias'
21
+ require_relative 'aws_connection_handler'
22
+
23
+ module ActiveRecord
24
+ module ConnectionAdapters
25
+ class AwsTrilogyAdapter < TrilogyAdapter
26
+ # Connects as the parent adapter does, through the wrapper instead of trilogy itself: the ssl_mode
27
+ # name is turned into the constant trilogy reads, and the whole config is passed on, since the
28
+ # wrapper takes its own properties out and trilogy ignores the ActiveRecord-only keys.
29
+ #
30
+ # Translates connection errors the same way the parent adapter does, so ActiveRecord can tell a
31
+ # missing database (which db:prepare creates) or rejected credentials from other failures.
32
+ def self.new_client(config)
33
+ config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
34
+ AwsAdvancedRubyDriverWrapper::WrapperTrilogyClient.new(config)
35
+ rescue ::Trilogy::Error => e
36
+ raise translate_connect_error(config, e)
37
+ end
38
+
39
+ def connect
40
+ @connection_broken = false
41
+ super
42
+ end
43
+
44
+ def reconnect
45
+ @connection_broken = false
46
+ super
47
+ end
48
+
49
+ def active?
50
+ return false if @connection_broken
51
+
52
+ super
53
+ end
54
+
55
+ def translate_exception(exception, message:, sql:, binds:)
56
+ return super unless exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::AwsError)
57
+
58
+ if exception.needs_reconfiguration
59
+ # The wrapper has reconnected this connection object to a new physical connection, where the
60
+ # session ActiveRecord configured on the old one does not exist. Forget what was cached about
61
+ # that connection and configure the new one.
62
+ clear_cache!(new_connection: true)
63
+ configure_connection
64
+ exception
65
+ elsif exception.is_a?(AwsAdvancedRubyDriverWrapper::Errors::FailoverFailedError)
66
+ @connection_broken = true
67
+ ActiveRecord::ConnectionFailed.new(message, sql:, binds:, connection_pool: @pool)
68
+ else
69
+ exception
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ ActiveRecord::ConnectionAdapters.register(
77
+ 'aws_trilogy',
78
+ 'ActiveRecord::ConnectionAdapters::AwsTrilogyAdapter',
79
+ 'aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter'
80
+ )
@@ -37,7 +37,7 @@ module AwsAdvancedRubyDriverWrapper
37
37
  # type explicitly registered for :aws_postgresql is normalized to :postgresql and so also applies
38
38
  # to the plain postgresql connections (and vice versa). This is documented in the CHANGELOG.
39
39
  module TypeAdapterAlias
40
- ADAPTER_ALIASES = { aws_postgresql: :postgresql, aws_mysql2: :mysql2 }.freeze
40
+ ADAPTER_ALIASES = { aws_postgresql: :postgresql, aws_mysql2: :mysql2, aws_trilogy: :trilogy }.freeze
41
41
 
42
42
  # Prepended onto ActiveRecord::Type::AdapterSpecificRegistry. Normalizing the adapter in lookup
43
43
  # covers both the framework path and a direct Type.lookup(..., adapter: :aws_postgresql); any
@@ -33,6 +33,17 @@ module AwsAdvancedRubyDriverWrapper
33
33
 
34
34
  DEFAULT_MONITORING_TIMEOUT_SEC = 5
35
35
 
36
+ # @return [String] the name of the Ruby driver gem this dialect drives
37
+ def name
38
+ raise NotImplementedError
39
+ end
40
+
41
+ # The database engine the driver talks to, which decides the database dialects that apply.
42
+ # @return [Symbol] +:mysql+ or +:postgresql+
43
+ def database_engine
44
+ raise NotImplementedError
45
+ end
46
+
36
47
  def connect(host_info, config)
37
48
  raise NotImplementedError
38
49
  end
@@ -138,6 +149,29 @@ module AwsAdvancedRubyDriverWrapper
138
149
  :user
139
150
  end
140
151
 
152
+ # Returns the property key the underlying driver expects for the TLS CA certificate file.
153
+ # Used by Blue/Green substitute routing for drivers that overload the host for both the socket
154
+ # address and the TLS server name (mysql2, trilogy): it tells whether TLS is active before
155
+ # deciding to connect by hostname rather than raw IP, avoiding a certificate-name mismatch.
156
+ # Drivers that can pin the socket separately (see #props_pinned_to_ip) do not use this.
157
+ # mysql2 names it +:sslca+ (the default); override where it differs (trilogy uses +:ssl_ca+).
158
+ def tls_ca_property_key
159
+ :sslca
160
+ end
161
+
162
+ # Blue/Green substitute routing must connect to a specific instance IP — so a DNS lookup during
163
+ # the switchover window cannot resolve to the old instance — while still presenting the original
164
+ # hostname for TLS certificate verification and IAM token generation. A driver that can pin the
165
+ # socket address separately from the TLS/auth server name returns a copy of +driver_props+ that
166
+ # connects to +ip+ but keeps the hostname for verification; a driver that overloads the host for
167
+ # both returns +nil+, and the routing falls back to the #tls_ca_property_key hostname check.
168
+ # @param driver_props [Hash]
169
+ # @param ip [String] the instance IP to pin the socket to
170
+ # @return [Hash, nil] props pinned to +ip+, or +nil+ when the driver cannot split socket from TLS name
171
+ def props_pinned_to_ip(_driver_props, _ip)
172
+ nil
173
+ end
174
+
141
175
  # Applies default socket/connect timeouts to monitoring connection driver props.
142
176
  # These ensure that a query or close on a dead connection raises a timeout error
143
177
  # rather than hanging indefinitely or segfaulting.
@@ -154,6 +188,15 @@ module AwsAdvancedRubyDriverWrapper
154
188
  def reported_in_transaction(_connection)
155
189
  nil
156
190
  end
191
+
192
+ # The server version that decides which versioned /*!80023 ... */ executable comments the server
193
+ # runs, as MySQL numbers it (8.0.39 is 80039). Only MySQL has executable comments.
194
+ # @param connection [Object]
195
+ # @return [Integer, nil] nil when the driver's SQL has no executable comments, or the version
196
+ # cannot be read
197
+ def executable_comment_version(_connection)
198
+ nil
199
+ end
157
200
  end
158
201
  end
159
202
  end
@@ -14,26 +14,33 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require_relative 'mysql_driver_dialect'
17
+ require_relative 'mysql2_driver_dialect'
18
18
  require_relative 'pg_driver_dialect'
19
+ require_relative 'trilogy_driver_dialect'
19
20
  require_relative '../errors'
20
21
  require_relative '../errors/mysql_error_handler'
21
22
  require_relative '../errors/pg_error_handler'
23
+ require_relative '../errors/trilogy_error_handler'
22
24
 
23
25
  module AwsAdvancedRubyDriverWrapper
24
26
  module DriverDialects
25
27
  module DriverDialectManager
26
- MYSQL_DIALECT = MysqlDriverDialect.new.freeze
28
+ MYSQL2_DIALECT = Mysql2DriverDialect.new.freeze
27
29
  PG_DIALECT = PgDriverDialect.new.freeze
30
+ TRILOGY_DIALECT = TrilogyDriverDialect.new.freeze
28
31
 
29
32
  REGISTRY = {
30
33
  mysql2: {
31
- driver_dialect: MYSQL_DIALECT,
32
- error_handler: Errors::MysqlErrorHandler.new(MYSQL_DIALECT)
34
+ driver_dialect: MYSQL2_DIALECT,
35
+ error_handler: Errors::MysqlErrorHandler.new(MYSQL2_DIALECT)
33
36
  },
34
37
  postgresql: {
35
38
  driver_dialect: PG_DIALECT,
36
39
  error_handler: Errors::PgErrorHandler.new(PG_DIALECT)
40
+ },
41
+ trilogy: {
42
+ driver_dialect: TRILOGY_DIALECT,
43
+ error_handler: Errors::TrilogyErrorHandler.new(TRILOGY_DIALECT)
37
44
  }
38
45
  }.freeze
39
46