-
Notifications
You must be signed in to change notification settings - Fork 642
CASSGO-22 CASSGO-73 Changes to Query and Batch to make them safely reusable #1868
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
Conversation
worryg0d
left a comment
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.
Hello @joao-r-reis,
I spent some time reviewing your PR. Great work! It simplifies public query and batch API which is pretty good.
Removing queryPool is a good idea. If anyone really needs this, it can be handled on their application side.
I left some minor comments but overall implementation is well.
I am only a bit concerned about the changes this PR provides to the driver internals, especially the conn part which overlaps with #1822.
Yeah I'll have to spend some time rebasing this branch and even writing some tests, for now it's good enough if reviewers can provide feedback on the current state of the PR especially the public API changes |
query_executor.go
Outdated
|
|
||
| // ExecutableQuery is an interface that represents a query or batch statement that | ||
| // exposes the correct functions for the HostSelectionPolicy to operate correctly. | ||
| type ExecutableQuery 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 do you think about renaming type to HostPolicyQuery?
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 posted a comment about the renaming of this interface below in a response to James
query_executor.go
Outdated
| qryOpts *queryOptions | ||
| pageState []byte | ||
| metrics *queryMetrics | ||
| refCount uint32 |
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.
Unused?
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.
Good catch, leftover from a copy paste
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.
still persist. but changed its position 😅
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.
oops, maybe I added it back during rebase, fixed
session.go
Outdated
| // Iter executes a batch operation and returns an Iter object | ||
| // that can be used to access properties related to the execution like Iter.Attempts and Iter.Latency | ||
| func (b *Batch) Iter() *Iter { | ||
| return b.session.executeBatch(b) |
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 feel that people may execute sequence of Exec() and Iter(). Shall we make an assertion that only one of the is invoked?
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.
Hmm, I see what you mean but I don't think we can lock them into one or another if we want it to be reusable.
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 feel that people may execute sequence of
Exec()andIter(). Shall we make an assertion that only one of the is invoked?
They can't execute sequence (Exec().Iter()) unless they do it like:
err := b.Exec()
iter := b.Iter()
Which I believe is already something that can be done with the current API and it will trigger two requests. We can try to improve documentation if this is a concern.
+1 to what James said
Note that Yugabyte lets you iterate over the row status from a batch operation. |
Why not just remove it? Seems like any |
|
I don't want to bikeshed about names but |
query_executor.go
Outdated
| } | ||
|
|
||
| type batchOptions struct { | ||
| Type BatchType |
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.
Any reason why some of these are 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 type itself is not public and it is never exposed so it wasn't a deliberate choice, just a result of copy paste. I can make them all private for consistency
|
What about making the methods |
Hmm I don't think
I kept |
I like the idea but I think it would be too much to ask of users when upgrading since it would affect every single statement on their app... I'd be down to adding an overload and deprecating |
We can add a type alias to leave the // Deprecated: Will be removed in the future major release.
// Please use Statement instead.
type ExecutableQuery = Statement
type Statement interface {
...
}I tested it on go 1.19.13 and it works fine |
Well, we can use the common Context suffix for those overloads, like it is done in sql package from standard lib - https://pkg.go.dev/database/sql#Conn.QueryContext |
|
I've addressed all PR comments, I'll work on rebasing the branch now and then I'll work on the change mentioned here. |
26570d6 to
4ad60b6
Compare
|
Rebase is done, it was a bit more complex than I thought it would be so I'd appreciate if you guys could take a look again @jameshartig @lukasz-antoniak @worryg0d |
query_executor.go
Outdated
| qryOpts *queryOptions | ||
| pageState []byte | ||
| metrics *queryMetrics | ||
| refCount uint32 |
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.
still persist. but changed its position 😅
|
@jameshartig @worryg0d do you guys have some free time to take a look at this again during the next few days? |
4691ddd to
0f09a6d
Compare
Before this change queries were mutated while being executed (the query metrics and the consistency for example). Instead copy query properties to an internal query object and move query metrics to Iter. This allows users to reuse Query and Batch objects. Query object pooling was also removed. Some query and batch properties were not accessible via ObservedBatch and ObservedQuery. Added the original Batch and Query objects to ObservedBatch and ObservedQuery to fix this. Patch by João Reis; reviewed by James Hartig and Stanislav Bychkov for CASSGO-22 and CASSGO-73
828d72f to
68e805a
Compare
API Changes
ExecutableQueryExecutableQueryis currently an interface thatQueryandBatchimplements (and is referenced byHostSelectionPolicy). However, it is also used in driver internals so the interface contains private methods which makes it impossible for users to "mock" the interface for testing purposes.In this PR,
ExecutableQueryis changed so it contains only public methods and is no longer implemented byQueryandBatch. Now,ExecutableQueryis used exclusively as a "hook" inHostSelectionPolicy. This does mean that users can no longer attempt to cast anExecutableQuerytoQueryorBatchbut I've added a new method that provides this functionality (Statement).StatementThis is the new interface that represents (and is implemented by)
QueryandBatch. In this PR it's only referenced byExecutableQuery.internalRequestNew interface that is used by driver internals to decouple the public API of Query/Batch from the internal API.
When creating an internal request object the driver now copies most if not all of the query/batch properties so that users can submit a Query/Batch for execution and then re-use immediately without having to be concerned about the object being modified by the driver execution. It also makes it less error prone because the driver is free to modify these properties (e.g. page state, consistency, query metrics) without causing a change on the objects that the users are using.
Query Metrics (i.e.
Query/Batch.Attempts(),Query/Batch.Latency())This functionality makes the API a bit awkward because the user submits a query for execution and then inspects the query object to retrieve the side effects of that execution after it's done. It's a better design (imo) to have this kind of data available in the
Iterobject since this is the type that represents the return value of a query/batch.Due to this,
AddAttempts(),Attempts(),Latency()andAddLatency()have been removed fromQueryandBatch.Latency()andAttempts()have been added toIterand a newBatch.Iter()method has been added so that users can obtain theIterobject when executing a batch (even though it doesn't make a lot of sense conceptually due to the name butIteris what the driver uses to return data about a request so it's not just about "iterating").queryPoolQueryobjects were allocated from async.Poolbut I don't see the gain of keeping it especially now thatqueryMetricshave been moved toIter. Also users can create these query objects once and store them if they are worried about memory/GC.Query/Batch.GetRoutingKey()Having this method as part of the public API of
QueryandBatchmakes it difficult to manage from the driver maintainer POV, it's supposed to be an internal method that can be called by implementations ofHostSelectionPolicybut sinceExecutableQuerywas implemented byQueryandBatchthis meant that these two types had to have this method on their public API as well.With this PR, this method is deprecated on
QueryandBatchsince these two types no longer implementExecutableQueryso we can keep theQuery/BatchAPI much simpler.