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

Add support for batches #65

Merged
merged 8 commits into from
Jan 24, 2022
Merged

Add support for batches #65

merged 8 commits into from
Jan 24, 2022

Conversation

mpenick
Copy link
Contributor

@mpenick mpenick commented Jan 13, 2022

Adds support for batches, both the batch CQL native protocol request and the BEGIN BATCH ... APPLY BATCH CQL query string.

This also includes some fixes for retries and adds tests for retries of prepared statements.

Fixes: #55

@mpenick mpenick changed the base branch from main to retries January 19, 2022 14:45
@mpenick mpenick marked this pull request as ready for review January 19, 2022 15:02
@mpenick mpenick changed the title Add support for batches (draft) Add support for batches Jan 19, 2022
Copy link
Collaborator

@joao-r-reis joao-r-reis left a comment

Choose a reason for hiding this comment

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

Looks good, added some questions (sorry, I'm not familiar with the codebase yet 😅)

proxy/request.go Outdated
var hash [16]byte
copy(hash[:], q)
if maybeIdempotent, ok := r.client.preparedIdempotence.Load(hash); !ok {
return false, errors.New("unable to determine if prepared statement in batch is idempotent")
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this fails, the proxy logs this error and continues processing the request assuming idempotent == false? It might be worth implementing a mechanism to return UNPREPARED when a cache miss occurs on the proxy (or re-preparing on the fly like the drivers do).

However, repreparing / returning UNPREPARED might be an issue if an error occured with the query parsing when processing the PREPARE message... Retrying in this case is pointless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, there's something off here.

It might be worth implementing a mechanism to return UNPREPARED when a cache miss occurs on the proxy (or re-preparing on the fly like the drivers do).

It does do this, but maybe not for batches.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, never mind. We are caching prepared statements and re-preparing automatically. This was added as part of this PR:
#28

The relevant code is here: https://github.com/datastax/cql-proxy/blob/v0.0.4/proxycore/clientconn.go#L293-L328

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This error case is possible, but is highly unlikely to happen.

Copy link
Collaborator

@joao-r-reis joao-r-reis Jan 20, 2022

Choose a reason for hiding this comment

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

So it's safe to assume that if this particular look up fails then we have to handle it (by assuming idempotent == false) without repreparing because it was probably caused by something that would not get fixed by repreparing?

Copy link
Contributor Author

@mpenick mpenick Jan 21, 2022

Choose a reason for hiding this comment

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

I see a better way to do this using the existing prepared cache instead of having yet another map. Trying to think of a way to make it clean-ish.

Copy link
Contributor Author

@mpenick mpenick Jan 24, 2022

Choose a reason for hiding this comment

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

So it's safe to assume that if this particular look up fails then we have to handle it (by assuming idempotent == false) without repreparing because it was probably caused by something that would not get fixed by repreparing?

It could happen if the proxy receives a prepared ID that it's never seen before, but I think that would be an application bug.

I see a better way to do this using the existing prepared cache instead of having yet another map. Trying to think of a way to make it clean-ish.

This shouldn't be done, because idempotent state cannot expire; otherwise, the proxy wouldn't be able to determine idempotence without having to have the driver re-prepare the request. This information is tiny and a huge number of variations in prepared queries is an anti-pattern. Also, I discovered a bug, the prepared idempotence cache should be global so that a prepare on one connection propagates its information to other "EXECUTE" requests on other connections. This cannot be tied to each client connection.

parser/parser.go Show resolved Hide resolved
proxy/codecs.go Show resolved Hide resolved
Base automatically changed from retries to main January 20, 2022 14:56
@mpenick mpenick merged commit aa6ddc1 into main Jan 24, 2022
@mpenick mpenick deleted the batches branch January 24, 2022 22:32
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.

Add support for batches
2 participants