Skip to content

fix(impala): end SQL Lab runs that hit a time limit instead of hanging - #45845

Open
aminghadersohi wants to merge 14 commits into
masterfrom
impala-sqllab-timeout-hang
Open

aminghadersohi wants to merge 14 commits into
masterfrom
impala-sqllab-timeout-hang

Conversation

@aminghadersohi

@aminghadersohi aminghadersohi commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

SUMMARY

At bb609de, signal-interrupted HiveServer2 replies cause the real cursor and connection to be abandoned before driver cleanup runs, rather than triggering another cancellation RPC.

  • A shared generated-client guard handles execute, lazy metadata, polling, logs, rows and cleanup; real-transport regressions are in tests/unit_tests/db_engine_specs/test_impala_transport.py and tests/unit_tests/db_engine_specs/test_hive_transport.py.
  • Impala's driver-internal transport reopen is rejected after abandonment; test_driver_close_timeout_prevents_transport_reopen exercises the CloseOperation-to-CloseSession exception path.
  • SQLAlchemy connection hooks include direct dialect pings and prequeries; test_sqlalchemy_ping_abandons_before_dialect_cursor_cleanup exercises both Impala and PyHive without calling spec.execute().
  • Row-limit probes propagate time-limit exceptions instead of treating them as partial results; test_row_limited_fetch_sends_nothing_after_a_skipped_cancel exercises the real cursor behind the wrapper.

An explicit Stop and the local Impala polling deadline still request cancellation on an uninterrupted transport. After a signal-interrupted reply, no further RPC is attempted; an abandoned operation relies on server-side query/session timeouts. Cleanup failures are logged without replacing the original limit.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — backend exception and transport lifecycle changes.

TESTING INSTRUCTIONS

Run narrow files with PYTHONPATH=.:superset-core/src pytest -q <file> -m 'not manual and not llm_compliance':

  • tests/unit_tests/db_engine_specs/test_impala.py
  • tests/unit_tests/db_engine_specs/test_impala_pending.py
  • tests/unit_tests/db_engine_specs/test_impala_transport.py
  • tests/unit_tests/db_engine_specs/test_hive.py
  • tests/unit_tests/db_engine_specs/test_hive_transport.py
  • tests/unit_tests/db_engine_specs/test_base.py
  • tests/unit_tests/db_engine_specs/test_presto.py
  • Each tests/unit_tests/sql/execution/test_*.py file separately.
  • tests/unit_tests/sql_lab_test.py
  • tests/unit_tests/models/core_test.py -k 'prequeries or get_raw_connection'

The transport fixtures run local HiveServer2 stand-ins with real Thrift buffered, SASL PLAIN and HTTP transports. They interrupt replies after the header so unread bytes remain, then assert exception identity and the absence of subsequent RPCs. The starting-head verifier probe produced 16 failures; the same 16 cases pass with the shared guard. Full before/after file counts and sibling audit are recorded in the review-thread reply.

Pre-commit, including mypy, passed on this branch's changed files at bb609de.

Remaining: real Impala was not run, so server-side operation/admission-slot release and LDAP/GSSAPI negotiation are not proven. Threaded synchronous execution still has no SIGALRM enforcement, and the existing hardcoded Celery task limits are unchanged. No real-model checks were run.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in [SIP-59] Proposal for Database migration standards #13351 )
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

A SQL Lab time limit is raised once into whatever the worker is executing:
the synchronous SQLLAB_TIMEOUT alarm raises SupersetTimeoutException and the
Celery soft limit raises SoftTimeLimitExceeded. Impala's handle_cursor only
treated the soft limit specially, so:

- a synchronous timeout raised while polling fell into the broad
  `except Exception` and was swallowed, and the Run kept waiting for the whole
  query before failing from fetch_data's own deadline;
- either limit raised while the progress log was fetched was swallowed as a
  failed GetLog() call, and with the limit already spent nothing stopped the
  query until the hard limit;
- a limit raised while fetch_data waited on the operation left it running on
  the coordinator.

Both limits are now cancelled and propagated from handle_cursor, including from
the progress log call and the cancel helper, and fetch_data cancels the
operation before propagating them. Hive's handle_cursor had the same swallow
around fetch_logs and now lets the limits through. Presto and Trino do not
wrap their polling in a broad except.
@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.64474% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.70%. Comparing base (5735bdb) to head (8c8604e).
⚠️ Report is 62 commits behind head on master.

Files with missing lines Patch % Lines
superset/db_engine_specs/impala.py 59.71% 54 Missing and 2 partials ⚠️
superset/utils/hive.py 85.13% 7 Missing and 4 partials ⚠️
superset/db_engine_specs/hive.py 94.23% 3 Missing ⚠️
superset/db_engine_specs/base.py 95.45% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #45845       +/-   ##
===========================================
+ Coverage   65.38%   84.70%   +19.32%     
===========================================
  Files        3069     3070        +1     
  Lines      205465   206055      +590     
  Branches    48310    48394       +84     
===========================================
+ Hits       134336   174535    +40199     
+ Misses      68043    28215    -39828     
- Partials     3086     3305      +219     
Flag Coverage Δ
hive 34.52% <45.72%> (-0.01%) ⬇️
mysql 52.55% <32.23%> (?)
postgres 52.56% <32.89%> (?)
presto 36.21% <31.57%> (-0.06%) ⬇️
python 87.73% <76.31%> (+35.30%) ⬆️
sqlite 52.32% <32.23%> (-0.01%) ⬇️
unit 82.50% <69.73%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aminghadersohi

Copy link
Copy Markdown
Contributor Author

Product acceptance at 85ef2d19eb32be18d0531806302f5312320ce037 against real Impala 4.5.2 (one admission slot), MySQL 8.0 metadata DB, Celery prefork and gunicorn, compared with the merge-base 5735bdb991ba501c3883c312b1264760407be78f.

Works as described for the phases the PR covers (a limit that lands while the operation is running or admission-queued):

Case This PR merge-base
Async, Celery soft limit 12 s (running / queued) 6/6 failed at 12.2–12.4 s, Impala Cancelled 4/4 same timing on this fixture
Sync main-thread, SQLLAB_TIMEOUT 10 s (running / queued) 6/6 failed at 10.2 s, "The query exceeded the 10 seconds timeout.", Impala Cancelled 4/4 failed at 20.2 s, "Timed out waiting for the Impala operation"
Limit lands inside GetLog() (3 s delay injected into get_log) async 3/3 and sync 3/3 end at the limit, Impala Cancelled async 2/2 killed at the hard limit with the row left running; sync 1/1 no response at 60 s
Fast queries, query under the limit, analysis / parse / runtime errors same status and messages as merge-base —
Stop (async, sync, admission-queued, gthread) 12/12 stopped, Impala Cancelled 8/8 same

Gap in ImpalaEngineSpec.fetch_data (pre-existing, same at the merge-base): when the limit lands while rows are being fetched (Impala already reports FINISHED and keeps producing rows), the run ends failed on time but the Impala query stays open: 5/5 here, 2/2 at the merge-base. It was still in flight 2 min 21 s later and held the admission slot, so the next SQL Lab query queued behind it and timed out too. return super().fetch_data(cursor, limit) sits outside the new except TIME_LIMIT_EXCEPTIONS, so nothing cancels the operation, and closing the impyla connection only closes the transport (Impala keeps the session until disconnected_session_timeout, 900 s by default). Wrapping that call in the same cancel-and-re-raise handler would cover it.

Unchanged and pre-existing, as the description says: a threaded sync request (gthread) still has no time limit (no response at 45 s, here and at the merge-base).

Not covered: the Hive change was not run against a live Hive server.

Testing note: Impala's sleep() is not interruptible, so after a cancel the CloseOperation call blocks until the sleep ends. A sleep()-based query makes a timeout look like a hang both here and at the merge-base, so these runs use a cancellable cross-join query instead.

@github-actions github-actions Bot added the doc Namespace | Anything related to documentation label Oct 30, 2026
@netlify

netlify Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 9c6a373
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6ae6266611e911185d80819c
😎 Deploy Preview https://deploy-preview-45845--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@aminghadersohi
aminghadersohi marked this pull request as ready for review October 30, 2026 12:13
Comment thread superset/db_engine_specs/impala.py Resolved
@codeant-ai-for-open-source

codeant-ai-for-open-source Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

CodeAnt  CodeAnt PR Risk

🟢  Low Risk

  • The PR appears safe to merge; failed Impala cancellation no longer prevents operation cleanup or masks the deadline timeout.
  • A regression test covers a rejected cancellation reply and verifies that both operation and cursor cleanup are attempted.

Assessed commit: 8c8604ec5640

@rebenitez1802 rebenitez1802 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Request changes: the fix is right and well tested (16 of 17 new tests fail on master; on real Impala 4.5.2 a sync timeout now ends the run at the limit instead of about 20 s later), but the new cancel in the row-fetch time-limit handler can hang the worker. Details and a live-validated fix are inline.

Comment thread superset/db_engine_specs/impala.py Resolved
…imit

impyla's reconnect() only closes and reopens the socket or HTTP
connection. TBufferedTransport and TSaslClientTransport keep their read
and write buffers across close and open, so the unread rest of an
interrupted status, log or row reply was parsed as the CancelOperation
reply: on the binary and SASL transports the cancel blocked until the
socket timeout and impyla resent it, and over HTTP it failed outright.

Reset the transport instead: check every layer of the stack, close it,
replace each layer's buffers with empty ones and reopen it. If the stack
is not recognised or the reset fails, no cancel RPC is sent on it.

Tests drive impyla over real binary, SASL PLAIN and HTTP transports
against a local HiveServer2 stand-in, with the time limit raised right
after a reply header is read.
When the transport reset is skipped or fails, the cancel RPC was not
sent, but impyla's cursor close() (reached through closing() in the
executor) and its finalizer still sent CloseOperation and CloseSession,
reopening the transport with the interrupted reply still buffered. Mark
the cursor closed on that path, and on a second time limit during the
reset, so neither sends anything.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc Namespace | Anything related to documentation size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants