-
Notifications
You must be signed in to change notification settings - Fork 623
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
CASSGO-4 Support of sending queries to the specific node #1793
base: trunk
Are you sure you want to change the base?
Conversation
b2f7e6f
to
0444ee3
Compare
Should the API allow for other routing preferences? For example only a single data center/rack? Or be extensible to allow targeting a specific shard in the scylladb/gocql fork? Should the API allow to route to a different host during retry, i.e. allow passing a |
In my opinion, re-routing queries bound to the specific hosts to others is not a good idea even during retries, at least as default behavior. Sending queries to a specific host is not a typical use case and if we try to do it, we assume that the specified host is reachable. Or, at least, we expect that the query was attempted to be sent to the specified host. The idea of this API being extensible sounds good, but I am not sure about implementation. May you have some advice or ideas on how to properly implement this? |
I think keeping this focused on the virtual table use case is best. Other routing preferences like shard awareness for scylla should probably be handled at the If a user sets the host using In the future if we add a way to provide a |
The discussion around the |
query_executor.go
Outdated
@@ -83,7 +83,28 @@ func (q *queryExecutor) speculate(ctx context.Context, qry ExecutableQuery, sp S | |||
} | |||
|
|||
func (q *queryExecutor) executeQuery(qry ExecutableQuery) (*Iter, error) { | |||
hostIter := q.policy.Pick(qry) | |||
type hostGetter interface { |
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.
How about adding a private interface like:
type cqlQuery interface {
ExecutableQuery
getHost() *HostInfo
}
And make gocql internal code reference cqlQuery
(name subject to change?) instead of ExecutableQuery
so that we don't have to worry about breaking the public ExecutableQuery
interface when we add new functions to Query
or Batch
?
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.
Alternatively, we could just add new functions to ExecutableQuery
because there's no place where a user can provide a custom implementation of ExecutableQuery
to the driver is there? If the driver API doesn't expose any function that receives an object of type ExecutableQuery
then we should be fine changing this interface since there's no real use case where a user might implement it on their application.
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.
From a quick glance at the code, ExecutableQuery
is provided to implementations of HostSelectionPolicy
but it's the driver that calls HostSelectionPolicy.Pick(ExecutableQuery)
with Query
or Batch
objects as parameters so I don't see an issue in adding GetHost
to ExecutableQuery
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 don't mind extending ExecutableQuery
interface, but adding private methods is not the best thing to me. The driver exposes HostSelectionPolicy
interface and allows user to provide their own implementations, but users cannot properly test them because Pick()
accepts ExecutableQuery
that cannot be mocked for testing purposes due to private methods inside... Ofc they can just pass Query
and Batch
objects, but I'm unsure if it is enough for testing
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.
These private methods would not be used in HostSelectionPolicy
because HostSelectionPolicy
declares the parameter as ExecutableQuery
not cqlQuery
or whatever the name would be for the private interface.
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.
what private methods are you referencing?
Such methods as execute()
, attempt()
, etc.
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.
Oh you're right, I didn't notice them. 👍 So it wouldn't actually make much of a difference if we added a private getHosts method there but we can keep it public
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.
The only issue of making GetHost()
public is a requirement to implement it for Batch
only to satisfy the interface. So there will be a public API Batch.GetHost()
which actually does noop. Maybe the first approach with internal query interface for internal use and the public one for exposing is better...
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 think it's fine if Batch.GetHost()
does a noop honestly, there's also a possibility that we might make it possible to set the host on batch queries in the future
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.
Then let's leave this one as it is for now
d8ebae3
to
c1e46be
Compare
|
||
var lastErr error | ||
var iter *Iter | ||
for selectedHost != nil { | ||
host := selectedHost.Info() | ||
if host == nil || !host.IsUp() { | ||
if (host == nil || !host.IsUp()) && specifiedHost == nil { | ||
selectedHost = hostIter() | ||
continue | ||
} |
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.
we should probably add another if
here to exit right away if specified host is != nil
and the host is down
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.
It makes sense not to send the query if the host is down. I added a check before this if that immediately returns an ErrNoConnections
when the specified host is down.
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.
👍
c1e46be
to
d83e8a2
Compare
d83e8a2
to
33730fa
Compare
Query.SetHost() allows users to specify on which node the Query will be executed. It is not a tipycal use case, but it makes sense with virtual tables which are available since C* 5.0.0. Patch by Bohdan Siryk; Reviewed by João Reis for CASSGO-4
33730fa
to
63c6f5d
Compare
Force pushed due to conflicts with the trunk |
Overview
This PR provides a mechanism that allows users to specify on which node the query will be executed. It is not a typical use case, but it makes sense with virtual tables.
For example, when we want to retrieve metrics for a specific node, we have to send queries to the associated system view of this node.
Implementation Overview
A new method
SetHost()
for theQuery
allows users to specify the host (node) on which the driver must send the query. It is implemented by adding aGetHost()
to theExecutableQuery
interface. When the host is specified for the query the driver ignores any retry, speculative, and host selection policies.Usage Example
Here is an example of retrieving metrics from system_view.cql_metrics for each node of the cluster: