Repository navigation
Conversation
Async submit-timeout and GET responses now carry the rows the query has produced so far. The root ResultSet only emits final rows in final order, so buildResultSet publishes each converted row as it is read and every response is a complete view whose rows are a prefix of the final result; composite pages become visible the same way. Blocking plans return no rows until they finish, timewrap publishes none, and rows are discarded if execution fails or falls back to the legacy engine. QueryRunner exposes currentResult(); QueryJobStatus and Running carry it only while RUNNING. Submit and GET RUNNING bodies are rendered by the same formatter, and a query job's GET body now uses PPL type names and warnings, matching the sync response. Resolves opensearch-project#5798 Signed-off-by: Kai Huang <ahkcs@amazon.com>
PR Reviewer Guide 🔍(Review updated until commit 9db3b41)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 9db3b41 Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit da78e9d
Suggestions up to commit 81b5c13
Suggestions up to commit 146638b
Suggestions up to commit 927a191
Suggestions up to commit 1122f45
|
- Discard buffered rows on any execution failure, not only one raised while reading rows, so a fallback never shows stale Calcite rows. - Add QueryRunner.close(), called once the job is terminal, so a retained job releases the progress tracker and its buffered rows. - Build the snapshot schema once and reuse the snapshot until a row is added. - Mark query-job responses explicitly instead of inferring them from progress, through AsyncQueryResult.forQueryJob. - Test that composite pages return rows early and that a blocking plan returns rows only after reading its input; document both and the fallback case. Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit 1122f45 |
- Drop the cancellation hook in PPLQueryRunner.close(): it captured the query task, which kept the tracker and its buffered rows reachable. - Fail the request instead of leaving it unanswered if rendering the submit response throws. - Log at debug when reading a running job's progress or rows fails. - Update the QueryResult Javadoc for Running's progress and rows. Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit 927a191 |
- Format a RUNNING submit response on the generic pool: a wait timeout completes on the JVM-wide CompletableFuture timer thread, which must not serialize thousands of rows. Fail only on a formatting error, so a later listener failure cannot send a second response. - Carry warnings such as an unanswered shard on running rows, as the final response does. - Sample a job's rows before its progress, so rows never come with a progress older than the work behind them. - Test a failure after rows were visible instead of one that fails before any row. Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit 146638b |
- Fail the submit request if the generic pool rejects formatting a RUNNING response, instead of leaving it unanswered. - Re-read warnings for running rows only when their count changes, not on every row. - Add QueryResult.Rows.EMPTY and unpack a running job's rows once per response. - Qualify the documented append-only guarantee by the fallback case. Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit 81b5c13 |
- Always return the job id on a RUNNING submit: if the rows cannot be formatted, or the generic pool rejects the task, respond without rows instead of failing a request whose job keeps running. - Publish a row's warnings before the row, so it is never visible without them. - Build drainWarnings on peekWarnings, so warnings are de-duplicated in one place. Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit da78e9d |
Codecov Report❌ Patch coverage is ❌ Your project check has failed because the head coverage (75.53%) is below the target coverage (99.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #5920 +/- ##
============================================
+ Coverage 75.51% 75.53% +0.01%
- Complexity 10439 10474 +35
============================================
Files 969 970 +1
Lines 41306 41446 +140
Branches 4711 4724 +13
============================================
+ Hits 31193 31306 +113
- Misses 8788 8812 +24
- Partials 1325 1328 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Signed-off-by: Kai Huang <ahkcs@amazon.com>
|
Persistent review updated to latest commit 9db3b41 |
Description
Async PPL responses now return the rows a query has produced so far: the submit response when
wait_for_completion_timeoutexpires, andGET /_plugins/_async_query/{id}while the job isRUNNING.{"id": "<opaque-id>", "status": "RUNNING", "progress": {"fraction_done": 0.42}, "schema": [{"name": "n", "type": "int"}], "datarows": [[0], [1], [2]], "total": 3, "size": 3}How it works
The rows a Calcite root
ResultSetemits are already final rows in final order; they are never retracted. So no plan classification is needed:OpenSearchExecutionEngine.buildResultSetappends each converted row to aPartialRowsbuffer held by the async query's tracker (the same object that holds progress since [Feature][PPL] Report progress for asynchronous Calcite queries #5910). Sync queries have no tracker and are unchanged.buildColumns, extracted). It is published only after the first row, so its schema equals the final schema. The buffer stops at the query size limit, as the final result does.stats ... by) pages reach the root as they are fetched, so they become visible without a composite-specific adapter.eventstats,statswithoutby, asortthat is not pushed down) returns rows only after it has read its whole input; a pushed-downsortstreams like a scan.timewrapreshapes all rows at the end, so it publishes none while running.Every response is a complete replacement view; there is no delta protocol.
Lifecycle seam (
core/job)QueryRunner.currentResult()(default empty), sampled outside the job monitor likeprogress().QueryJobStatus.current()andQueryResult.Running.current()carry the snapshot, present only whileRUNNING.QueryRunner.close()(default no-op, idempotent), called once the job is terminal. The PPL runner drops its progress and rows suppliers and its cancellation hook (which holds the query task), so a job retained forkeep_aliveno longer holds the buffer.Responses
RUNNINGbodies are now rendered by the same formatter (AsyncQueryResultResponseFormatter, with anidfield set only on submit), so they cannot drift. Query-job responses are built throughAsyncQueryResult.forQueryJoband marked explicitly, rather than inferred from other fields.PARTIAL_RESULTwhen a shard did not answer), as the final response does.CompletableFuturetimer thread, so theRUNNINGsubmit body, which can now hold thousands of rows, is formatted on the generic pool.Behavior changes to flag
bigint, notlong;int, notinteger.AsyncPPLQueryLifecycleITandAsyncPPLMultiNodeRoutingITdocumented the old difference on purpose and are updated.SUCCEEDEDbodies now includewarningswhen present.warnings.RUNNINGnow includesschema,datarows,total, andsize(empty when there are no rows yet). The submitRUNNINGbody gainssize.Observed
AsyncPPLPartialRowsIT,source=<fixture> | fields n(10,000 rows, 1,000 PIT pages), rows perRUNNINGresponse polled every 20 ms:0, 0, 789, 2057, 3179, 4699, 6329, 7939, 9769, thenSUCCEEDEDwith all 10,000, equal to sync.Tests
AsyncPPLPartialRowsIT(new): scan and row-localeval/wherereturn rows early; composite with 100-bucket pages returns rows before the last page; blockingeventstatsreturns rows only after reading all input; size limit 500;timewrap; failure after rows were visibleCalciteCrossClusterAsyncProgressIT, with a new remote partial-rows caseAsyncPPLProgressITAsyncPPLMultiNodeRoutingIT(asyncMultiNodeIT)AsyncPPLSecurityITAsyncPPLQueryLifecycleITcheckforcore,opensearch,ppl,async-query-core,async-query, and the pluginEach
AsyncPPLPartialRowsITcase asserts that the final schema and rows equal sync, and that everyRUNNINGresponse is a complete view whose rows are a prefix of the final rows, never shrink, and carry the final schema. New unit tests cover the job seam,PartialRows(including a concurrent writer/reader prefix check), the runner, routing, and the formatter.AsyncPPLQueryLifecycleIT: oneparity_*case fails per run, a different one each time. The same failure reproduces on a cleanupstream/main, so it is pre-existing and not caused by this PR. Withwait_for_completion_timeout=0, a fast analysis error now completes before the wait starts and is returned inline, instead of theRUNNINGid the test expects. This likely changed with #5915; I'll follow up separately.Related Issues
Resolves #5798
Part of #5765
Check List
--signoffor-s.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.