sadpandajoe opened a new pull request, #43889:
URL: https://github.com/apache/superset/pull/43889
## SUMMARY
Stopping a SQL Lab query before its DB engine "cancel handle" has been
obtained (e.g.
it's still validating RLS/table checks, or the engine's connection hasn't
opened yet)
previously raised `SupersetCancelQueryException` without changing the
query's stored
status, silently leaving it at `Running` forever if the underlying statement
never
completes on its own. This matches reports going back years (#17011, #20950,
#29475,
#31814) where the Stop button appeared to do nothing.
`superset/sql_lab.py::cancel_query()` now records the same "early cancel"
intent that
`db_engine_specs/trino.py`'s own `prepare_cancel_query()` already uses for a
harder
version of this problem (Trino can only obtain a real cancel handle after
the query
starts) as the *default* fallback, instead of requiring each engine to opt
in.
`execute_sql_statements()` now honors that signal at every point before the
statement
would actually run, so the query is correctly marked `Stopped` instead of
silently
continuing to execute.
Once a query has genuinely been dispatched to the database and the engine
still can't
supply a cancel handle, Stop still raises `SupersetCancelQueryException`
exactly as
before — this change does not claim to cancel a query on an engine with no
real
cancellation support; it only fixes the case where nothing was ever actually
sent to
the database yet.
## BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A — backend-only change, no UI change.
## TESTING INSTRUCTIONS
Covered by `tests/unit_tests/dao/test_query_stop_race.py` (new) and updates
to
`tests/unit_tests/sql_lab_test.py`. These deterministically simulate the
race using
separate scoped SQLAlchemy sessions and a real SQLite-backed
`Query`/`Database` pair
(the actual `cancel_query()`/`execute_sql_statements()` code, not mocked),
rather than
relying on real wall-clock timing:
```
pytest tests/unit_tests/dao/test_query_stop_race.py -v
pytest tests/unit_tests/sql_lab_test.py tests/unit_tests/dao/
tests/unit_tests/models/sql_lab_test.py tests/unit_tests/sql/execution/
tests/unit_tests/commands/sql_lab/ -v
```
Manual repro (needs a database with `allow_run_async` enabled and a
validation step
slow enough to create a window before the connection opens, e.g.
`RLS_IN_SQLLAB`):
run a query from a fresh SQL Lab tab and click Stop immediately after
submitting.
## ADDITIONAL INFORMATION
- [ ] Has associated issue: related to (already closed, but the underlying
gap
remains on master) #17011, #20950, #29475, #31814
- [ ] Requires DB Migration
- [ ] Confirm your changes are compatible with databases that are officially
supported by Superset
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API
## Known limitations (disclosed, not fixed in this PR)
- **A narrow check-to-commit race remains.** This change closes the
previously
unconditional "no cancel handle = permanently stuck, and the user isn't
told the
truth" failure mode, but it does not add database-level row locking or
optimistic-concurrency versioning. A stop request landing in the brief
window
between one of several status checks and its corresponding commit
(execution
startup, immediately before building the result payload, in the
results-backend-write-failure path, and in `cancel_query()`'s own
dispatched-key
read) can still, rarely, be missed. Closing that fully needs real
row-level locking
verified against a production-shaped database (Postgres/MySQL) — not
verifiable
against SQLite — and is deferred rather than shipped unverified.
- **The newer async SQL execution framework (`superset/sql/execution/`) has
the
identical gap and is unfixed here.** `SQLExecutor._cancel_query()`
(`superset/sql/execution/executor.py`) is a separate implementation from
`superset.sql_lab.cancel_query()` and isn't touched by this PR.
- Tests are verified against SQLite with thread-based simulation of
concurrent
requests, not a real multi-process/multi-connection database under load.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]