-
Notifications
You must be signed in to change notification settings - Fork 25.6k
SQL: Allow text formats to work in async mode #73729
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
SQL: Allow text formats to work in async mode #73729
Conversation
|
Pinging @elastic/es-ql (Team:QL) |
matriv
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.
Thanks Bogdan, left some comments, mostly worrying about flakiness because of the async nature of things.
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.
Is this time value safe for any case?
Could it be better to make use of some other async test mechanism like assertBusy to make sure that it's robust?
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.
This particular value has been c&p'ed from the similar EQL tests.
But the way the test works is to get exceptions when the "other" user tries to get to this async request. For that to work, the async task would only need to be created. Which is checked both by asserting an OK answer to the initial request, as well as by getting its status, subsequently. So the task wouldn't even have to be finished, just started, which is guaranteed by the first checks.
So the "10s" aren't actually relevant for the outcome of the test.
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.
Great, thx!
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.
Is this the correct place to count the elapsed time for the request?
(just asking)
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 how we counted before -- it's pretty much when the request enters SQL, but yeh, otherwise maybe "a bit" later than when it enters ES.
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.
ok, thx!
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.
This seems strange, why do we return the Delimiter?
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 used to signal that this param can be checked on, but not consumed. BaseRestHandler.java#prepareRequest and responseParams() details how that works.
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.
nit: extra empty line.
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.
Thx, will remove.
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.
Removed.
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.
nit: extra empty line
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.
Removed.
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'm worrying again here and for the rest of the aysnc tests about flakiness. Should we use the assertBusy mechanism to make sure that it always works?
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 assertBusy could be used in this case, true (tho with extra complexity). How would you see it failing in a flaky way?
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.
Not easy to achieve I guess, If you want to just check locally maybe try a simple Thread.sleep() somewhere in the SQL chain (e.g. Analyzer), so that the execution is delayed for let's say 5secs.
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.
IIUC your suggestion, the (merged) local cancellation tests do that, they start a task and make sure it blocks at certain stages along its execution.
The tests here are all remote ones though, that are only mean to check the correct response formatting of the textual answers. The timing is irrelevant, it makes no difference between "10s" or "1d", for as long as the query finishes. But even if it doesn't finish, or the query goes wrong, it'd result in a failed test due to mismatch between expected and returned answer. That's why I wasn't sure how you see it failing in a flaky way.
Using assertBusy to check on task's actual completion before checking its result is possible, but don't think it's necessary. But let me know if you see it differently still.
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.
@bpintea Thx Bogdan, I was confused with the functionality here.
Since we have the waitForCompletionTimeout that ensures that we have the response (or a timeout if the test runs for 1 day :D) when we try to assert it, so no need for the assertBusy.
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.
maybe a better name is runSqlWithFormat
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.
Makes sense, will change.
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.
Changed. to runSqlAsTextWithFormat since there are existing runSqlAsText methods and only text formats need to be provided (as it checks for a Cursor header, only available with those formats).
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.
LGTM. I left a comment on two methods that seem to share code.
The sync/async code paths complicate things though I don't have any good advice on how to move forward without splitting the code apart.
We just have to be careful and use proper formatting to delimitate the two and where possible use different methods.
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.
👍
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 wonder if using different class hierarchy instead of dedicated properties might help encapsulate the difference in response between sync/async better.
The hasId is obscure - is it used anywhere else?
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 wonder if using different class hierarchy instead of dedicated properties might help encapsulate the difference in response between sync/async better.
That'd be ideal, but I didn't find a way to cross the hierarchies.
The hasId is obscure - is it used anywhere else?
hasId() is also used in SqlResponseFormatter and TextFormat, yes. It is a bit obscure and I hesitated using it, but eventually did since there is a hasCursor() (which returns the cursor field) and there is already the id() method. Now the id() method is maybe also generic, but I wanted to keep the symmetry with EqlSearchResponse.
(We could change them in both classes to something like asyncId() & co., but I'd do that subsequently, if needed.)
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.
This method should delegate to the one above or vice-versa.
The URL_PARAM_FORMAT & co is shared across the two.
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 check on URL_PARAM_FORMAT needs to stay in both functions, since the functions are called from different context and need to act differently on its presence. But I've refactored the functions to avoid the double check.
matriv
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.
LGTM, thx!
|
@elasticmachine run elasticsearch-ci/rest-compatibility |
astefan
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.
Looks good in general. Left few comments.
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 understand why you are comparing these two. assertEquals is about comparing a (actual) value to something that's expected. Comparing something from the response with something else from the response breaks this contract. If both are true then it should be assertEquals(true, response.....) or assertTrue(response.get....). Just few lines above you used the right way for these assertions: https://github.com/elastic/elasticsearch/pull/73729/files#diff-6f95aacef2988567618b4250a265a6eadcebe2eb971653f7267a1a86c8e73c4fR1243-R1244
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.
assertEquals is about comparing a (actual) value to something that's expected.
Not sure, I might have taken editor's suggestion to "simplify" the code. The documentation is not "contractual" enough, IMO, but parameter naming might support your case. :-) So I see your point and I've refactored to assertTrue() (tho maybe a bit less easy to read).
Just few lines above you used the right way for these assertions
This case differs from above since both "true" or "false" are valid, as long as both headers have the same value.
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.
Is there a danger here of this for not existing and running into a test suite timeout?
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 would require the server so somehow hang with the search task alive (which I guess would also trigger a timeout).
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.
If I understand this well, you use the default delimiter (,) but depending on a randomBoolean you change that (and is set explicitly) to ;. I would move Character csvDelimiter = ','; closer to this randomBoolean. If I wouldn't have put the code in the IDE and look at what happens with the csvDelimiter it would have been more difficult to see what the logic is.
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 randomBoolean() splits between passing the format as a URL parameter or HTTP header. Then, if the chosen branch is to use the parameter and the format - also randomly chosen - is csv then the splitting character is changed.
The randomBoolean() isn't solely responsible for the delimiter char, so not sure how to make it clearer, but if you have a suggestion I'll apply it.
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 am not sure I agree with this code being "externalized" in a separate class that is a RestResponseListener called SqlResponseFormatter. If it's a Listener, this should be reflected in its name imo. Also, why its a separate class? Maybe an internal class in RestSqlQueryAction if you really like to refactor the code (to me it looks like a forced refactoring without any real benefit, maybe it's just me)?
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.
[...] class that is a RestResponseListener called SqlResponseFormatter
Good point, I've renamed it to SqlResponseListener.
why its a separate class?
The listener is used by both RestSqlQueryAction and RestSqlAsyncGetResultsAction.
astefan
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.
LGTM. Thank you for addressing my review.
This extends the async implementation to support working with the text formats (txt, csv, tsv). A test validating the administrator operation of a user with the "manage" permission has also been added.
- refactor media type calculation to avoid redundant check on URL param. - rename methods in tests. - remove empty lines.
- renamed listener; - minor test refactorings.
e955d30 to
ea85d2b
Compare
- Fix Nullable and TimeValue imports after classes relocation.
This extends the async implementation to support working with the text
formats (txt, csv, tsv).
A test validating the administrator operation of a user with the
"manage" permission has also been added.