Skip to content

Send heartbeats while the caller consumes fetched rows - #632

Open
hashhar wants to merge 3 commits into
trinodb:masterfrom
hashhar:hashhar/463-query-stuck-finishing
Open

Send heartbeats while the caller consumes fetched rows#632
hashhar wants to merge 3 commits into
trinodb:masterfrom
hashhar:hashhar/463-query-stuck-finishing

Conversation

@hashhar

@hashhar hashhar commented Aug 18, 2026

Copy link
Copy Markdown
Member

Description

Fixes #463.

The client makes no requests between fetch() calls. A caller holding a batch of rows for longer than query.client.timeout gets the query abandoned by the coordinator.

TrinoQuery now runs _RequestHeartbeat between fetch() calls. fetch() stops it on entry and restarts it before returning, so the heartbeat never overlaps a request on the same HTTP session. The heartbeat stops on completion and cancel(), and exits via a weakref check when the TrinoQuery is garbage collected.

The per-download heartbeat wiring is removed, the query-level heartbeat covers segment downloads. Follow-up commits make the pre-existing heartbeat tests deterministic (semaphore waits and thread joins instead of sleeps, client-side HEAD counting instead of polling server logs) and move heartbeat construction behind TrinoRequest.heartbeat(), dropping SegmentIterator's request/heartbeat_interval parameters so the request layer is the single owner of the mechanism.

heartbeat_interval (default 30s) controls the interval, None disables it. Servers without HEAD support on the statement endpoint (older than Trino 475) keep the old abandonment behavior.

Non-technical explanation

The client pings the coordinator between fetches, so slow consumers no longer fail with "Query was abandoned by the client".

Release notes

( ) This is not user-visible or docs only and no release notes are required.
(x) Release notes are required, please propose a release note for me.
( ) Release notes are required, with the following suggested text:

@cla-bot cla-bot Bot added the cla-signed label Aug 18, 2026
@hashhar
hashhar force-pushed the hashhar/463-query-stuck-finishing branch from 2cd7679 to 904d56e Compare August 19, 2026 21:40
@hashhar hashhar changed the title Send heartbeats during general result iteration, not just spooled downloads Send heartbeats while the caller consumes fetched rows Aug 19, 2026
The client made no requests between fetch() calls. A caller holding a
batch of rows for longer than query.client.timeout got the query
abandoned by the coordinator. Run the heartbeat between fetch() calls.
It stops on cancel and completion, and exits when the TrinoQuery is
garbage collected. Remove the per-download heartbeat wiring, the
query-level heartbeat covers segment downloads.
The unit tests slept for a fixed 0.1s and asserted heartbeat call
counts, which is racy on loaded machines. Serve scripted HEAD responses
from a recording request, wait on a semaphore and join the heartbeat
thread instead. The spooled download integration test polled the
coordinator's http-request.log for up to 9s. Count HEAD requests
client-side through the http_session.
SegmentIterator took paired request and heartbeat_interval arguments and
validated the pairing itself, while TrinoQuery dug the interval out of
private session state. Add TrinoRequest.heartbeat() returning a
configured heartbeat or None when disabled. TrinoQuery is the only
caller. Drop SegmentIterator's heartbeat parameters and the unused
context-manager protocol on _RequestHeartbeat.
@hashhar
hashhar force-pushed the hashhar/463-query-stuck-finishing branch from 459267d to 46d44b8 Compare August 20, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Queries stuck in FINISHING time

1 participant