Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate new error classes #24

Conversation

adrianna-chang-shopify
Copy link
Collaborator

Related to: trilogy-libraries/trilogy#15

Updates the adapter code to work with the changes made to Trilogy's error classes (see above PR).
The diff is pretty minimal -- we change DatabaseError to ProtocolError in a couple of spots, and the base Trilogy::Error is now Trilogy::BaseError.

Curious about the release process -- do we make the changes to the Trilogy Ruby bindings, release a new version X, and then merge these changes in a new version of activerecord-trilogy-adapter that specifies X as the minimum required version for trilogy?

cc @composerinteralia @casperisfine

@adrianna-chang-shopify adrianna-chang-shopify requested a review from a team as a code owner January 6, 2023 18:48
@@ -75,7 +75,7 @@ class << self
def new_client(config)
config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
::Trilogy.new(config)
rescue Trilogy::DatabaseError => error
rescue Trilogy::ProtocolError => error
Copy link
Contributor

@composerinteralia composerinteralia Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like ER_ACCESS_DENIED_ERROR = 1045 will be a BaseConnectionError instead of a ProtocolError, which I think means it's no longer getting translated the same way. We are probably missing a test for this case...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't think I've quite wrapped my head around what happens to the BaseConnectionErrors here in general. They used to get translated into ActiveRecord::ConnectionNotEstablished, but now are they getting raised as is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes thank you! I'll add a test case and ensure that we're also rescuing connection errors when initializing the client here 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops sorry, wrote my comment before seeing your second one!

Actually I don't think I've quite wrapped my head around what happens to the BaseConnectionErrors here in general. They used to get translated into ActiveRecord::ConnectionNotEstablished, but now are they getting raised as is?

I definitely think we'd want to translate them here. Maybe we should only be rescuing BaseConnectionError and not ProtocolError at all though? Is it worth running this branch with only BaseConnectionErrors rescued against GH's CI to see if there are any edge cases we're missing where we'd expect a non-BaseConnectionError to be translated to ConnectionNotEstablished?

There's also some interesting behaviour right now if a bad host is supplied -- would love your thoughts on that, see comment below :D

Copy link
Contributor

@composerinteralia composerinteralia Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this method has explicit translation for a few more errors:

ER_BAD_DB_ERROR = 1049
ER_CONN_HOST_ERROR = 2003
ER_UNKNOWN_HOST_ERROR = 2005

and the trilogy PR has those all as ProtocolError. So I think we still need to rescue ProtocolError unless we're planning to turn those specific ones into BaseConnectionError. I don't know all these errors too well, so I don't have any strong opinions to offer. Rescuing both seems safest for now to match the current behavior, but that doesn't necessarily make it the most correct. 🤷🏻‍♂️

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍 I think we may want ER_CONN_HOST_ERROR and ER_UNKNOWN_HOST_ERROR to show up as connection errors, but I don't think we even see these right now in Trilogy because host-related errors are being surfaced as QueryErrors ..? Either way, ER_BAD_DB_ERROR is indeed a ProtocolError, so we def need to rescue that!


test ".new_client on host error" do
configuration = @configuration.merge(host: "unknown")
assert_raises ActiveRecord::DatabaseConnectionError do
Copy link
Collaborator Author

@adrianna-chang-shopify adrianna-chang-shopify Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@composerinteralia this fails right now, because we raise this as a query error so it's not being rescued and translated.

ActiveRecord::ConnectionAdapters::TrilogyAdapterTest#test_.new_client_on_host_error [/Users/adriannachang/src/github.com/activerecord-trilogy-adapter/test/lib/active_record/connection_adapters/trilogy_adapter_test.rb:51]:
[ActiveRecord::DatabaseConnectionError] exception expected, not
Class: <Trilogy::QueryError>
Message: <"trilogy_connect - unable to connect to unknown:3306: TRILOGY_DNS_ERR">

But on main currently, this type of error shows up as a Trilogy::Error and not a Trilogy::DatabaseError, so I don't believe it's being translated as intended right now either 🤔 :

ActiveRecord::ConnectionAdapters::TrilogyAdapterTest#test_.new_client_on_host_error [/Users/adriannachang/src/github.com/activerecord-trilogy-adapter/test/lib/active_record/connection_adapters/trilogy_adapter_test.rb:32]:
[ActiveRecord::NoDatabaseError] exception expected, not
Class: <Trilogy::Error>
Message: <"trilogy_connect - unable to connect to unknown:3306: TRILOGY_DNS_ERR">

This ought to be raised as a BaseConnectionError right (on the Trilogy side)?

Copy link
Contributor

@composerinteralia composerinteralia Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree QueryError doesn't quite make sense for this one, since that is meant "for invalid queries or parameters". We could add a case for that to handle_trilogy_error. BaseConnectionError is for "potentially transient network errors", correct? Does that fit this DNS error?

This does make me wonder if there are other trilogy errors that are going to turn up as QueryErrors but maybe make more sense as something else.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BaseConnectionError is for "potentially transient network errors", correct? Does that fit this DNS error?

I think so 👍 It's the network refusing the connection, and Mysql2 treats these as ConnectionErrors so it seems reasonable for us to do the same.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so I started looking at this in the Trilogy client, but I'm a little stuck on which layer to change the error 😅 We could change the #initialize logic to raise BaseConnectionError directly instead of calling #handle_trilogy_error, but there's no relevant error code to set... The host errors (CR_CONN_HOST_ERROR => 2003 and CR_UNKNOWN_HOST => 2005) on Mysql2's end (I think) come from the libmysqlclient library, so we wouldn't expect to see these in Trilogy either way, only server errors.

So I guess we have a couple options:

  1. Continue to raise this type of error as a query error, update the adapter to rescue appropriately based on the error message instead of looking for an error code
  2. Convert this to a BaseConnectionError in the Ruby bindings for Trilogy, update the adapter to rescue based on the error message
  3. Something else..?

Either way, perhaps it makes sense to skip the host test for now so that we can get this initial work shipped, and then I'll investigate what we should be doing in a follow up. WDYT?

cc @casperisfine do you have any opinions here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jean and I chatted IRL -- seems like the most appropriate solution is just to add all of the relevant error code ints to #handle_trilogy_error and have those raised as connection errors. TRILOGY_DNS_ERR for one, but also TRILOGY_EOF and TRILOGY_PROTOCOL_VIOLATION (as evidenced in the connection tests that fails with MySQL8 right now)

@HParker HParker merged commit b975205 into trilogy-libraries:main Feb 2, 2023
composerinteralia added a commit that referenced this pull request Mar 2, 2023
We're already using some of the new error constants from that release
(see #24) so
we need to bump.
adrianna-chang-shopify pushed a commit to paarthmadan/activerecord-trilogy-adapter that referenced this pull request Mar 16, 2023
We're already using some of the new error constants from that release
(see trilogy-libraries#24) so
we need to bump.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants