-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Allow to pass metadata in ActiveRecord::Result #38660
Conversation
@@ -740,6 +740,13 @@ def arel_visitor | |||
|
|||
def build_statement_pool | |||
end | |||
|
|||
def metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those who wanted to leverage metadata support would patch or subclass from another adapter, for instance:
class MyAdapter < ActiveRecord::ConnectionAdapters::Mysql2Adapter
def metadata
system_variables = @connection.session_track(Mysql2::Client::SESSION_TRACK_SYSTEM_VARIABLES)
return unless system_variables
JSON.parse(system_variables)
end
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the abstract implementation default to returning an empty hash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good idea. Would you prefer that we freeze an empty hash and use that as a default to reduce allocations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I'd do, but I'm not familiar enough with the design of this part of Rails to know wether it would be expected or not.
Also if the default is frozen, it would be preferable that the actual implementation is frozen as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does any other database provides this kind of information?
8a71fe3
to
d798493
Compare
Not to my [limited] knowledge of Postgres or sqlite. I roughly scanned Postgres protocol spec for anything that would resemble MySQL's session tracking but I wasn't able to find. Although this |
As for the next things that could be based on having metadata on Let me know if this looks like a wrong direction. |
d798493
to
d220b23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like ActiveRecord::Result (and eventually maybe records themselves) to retain that metadata so that we can link it to records and instrument with ActiveSupport::Notifications.
My instinct is to demonstrate this system first, and separately, before introducing a generic way to provide Result metadata.
Connection session tracking may be seen as metadata about the connection and server state, or even as server notifications, since they may be registered as observation of state changes. Carrying this information along with the resultset may be natural, and it's straightforward to decorate the Result to do it; on its own, this would not merit introduction of general-purpose metadata.
Furthermore, result metadata suggests it's descriptive of the resultset itself. Things like affected row count, column types, generated warnings, and such. These metadata are already returned from the drivers and represented in AR.
Related, mysql2 exposes status flags as well:
result.server_flags[:no_good_index_used]
@jeremy thanks for your feedback! Here's an example how metadata on Result could be leveraged in next steps: kirs@10ff02d I don't know if having shop = Shop.find(1)
shop._metadata
=> { replication_delay: 0.01, ... }
# if replication_delay is within a healthy range, we're good to cache this shop record. Otherwise we shouldn't cache stale data (btw I'm good with calling it whatever and not metadata if we think there's a better name) Or maybe we don't bother to injecting all of metadata into the AR object, and we should instead hook into |
In PostgreSQL AFAIK you can introduce connection variables through plperl or similar scripts as a global variable. Anyway I do not see any benefit in this change. In majority of applications this will result in empty hash in each Any chance to elaborate more on this and explain how this can be used (any usecase)? If I understand this well you need to inherit adapter (which is IMHO non-standard approach) to make any benefit of this change. Initial value is useless and you need to override it in custom adapter. What's the reason to make it general than? |
At Shopify, we're about to leverage mysql's client session tracking (brianmario/mysql2#1092) and pass around some metadata from MySQL server to the client. That metadata is per connection and is fetched with something like
@connection.session_track(Mysql2::Client::SESSION_TRACK_SYSTEM_VARIABLES)
.I'd like
ActiveRecord::Result
(and eventually maybe records themselves) to retain that metadata so that we can link it to records and instrument with ActiveSupport::Notifications.I've took a stab at trying to abstract it in a way that it's not tied to MySQL. I'm open to suggestions for what would be a better design.
cc @bibstha @sirupsen @rafaelfranca @Edouard-chin @byroot