Skip to content

fix(query): apply queryTimeout to queryMeasurement endpoint - #701

Open
MrBeldum wants to merge 3 commits into
Basekick-Labs:mainfrom
MrBeldum:fix/308-query-measurement-timeout
Open

fix(query): apply queryTimeout to queryMeasurement endpoint#701
MrBeldum wants to merge 3 commits into
Basekick-Labs:mainfrom
MrBeldum:fix/308-query-measurement-timeout

Conversation

@MrBeldum

@MrBeldum MrBeldum commented Sep 4, 2026

Copy link
Copy Markdown

Summary

  • GET /api/v1/query/:measurement executed against context.Background() and db.Query() with no deadline, so configured queryTimeout never applied (high(query): queryMeasurement endpoint has no timeout #308).
  • Wrap c.UserContext() with queryTimeout (same pattern as POST /api/v1/query), pass the cancel func into the Arrow dispatch, and use QueryContext on the database/sql fallback.
  • Timeout now returns 504 "Query timed out" and increments timeout metrics. Stream and error paths cancel the context.

Fixes #308

Test plan

  • go test -tags=duckdb_arrow ./internal/api/ (full package, including new TestQueryMeasurementAppliesQueryTimeout)
  • Confirm a configured query_timeout actually 504s a slow GET /api/v1/query/:measurement in a running server (verified in review: 504 at 1.5s with query.timeout=1, timeout metric incremented; pre-fix build ran 9.5s past the timeout)

GET /api/v1/query/:measurement used context.Background() and Query()
without a deadline, so configured queryTimeout never applied. Wrap
UserContext with queryTimeout matching the POST /api/v1/query sibling.

Fixes Basekick-Labs#308
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA. Thanks!
Posted by the CLA Assistant Lite bot.

@xe-nvdk xe-nvdk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for taking #308. This is the right fix, and it verified out at every level I tested. Two administrative items block the merge, listed at the end.

What I verified:

Cancel ownership. The contract with executeArrowJSONQuery holds exactly as your comment states: every handled=true path releases the cancel func (immediate error paths directly, the success path inside the stream callback), and the handled=false driver-fallback path returns without cancelling, so the database/sql fallback receives a live context. On the fallback itself, every return path after the context is created releases cancel: the QueryContext error, the Columns error, and the stream writer callback. The ColumnTypes error deliberately falls through, so nothing leaks there either.

Pattern match. The wiring matches the established handlers: UserContext as the base so client disconnects propagate, ctx.Err() == context.DeadlineExceeded for the 504 classification, cancel called in the stream callback rather than deferred because SetBodyStreamWriter runs after the handler returns.

Tests. Full internal/api suite green under -race, with and without -tags=duckdb_arrow. TestQueryMeasurementAppliesQueryTimeout fails against the pre-fix handler, so the regression is pinned.

Live server. I ran the confirmation your test plan left unchecked. With query.timeout = 1 on a duckdb_arrow build, an expensive where subquery against GET /api/v1/query/cpu returned 504 "Query timed out" at 1.5s and bumped arc_query_timeouts_total from 0 to 1, through the Arrow path. The same query on a pre-fix build from main ran 9.5 seconds past the configured timeout and returned 200 with the counter untouched. Fast queries still return 200 in single-digit milliseconds under the timeout-aware code.

One optional note on the second test: TestQueryMeasurementNoTimeoutKeepsUserContext also passes against the pre-fix handler, because a nil-deadline context cannot be told apart from context.Background(). If you want it to pin UserContext propagation, inject a marked context in middleware (app.Use(func(c *fiber.Ctx) error { c.SetUserContext(ctxWithTestValue); return c.Next() })) and assert the value comes through. Fine to skip.

Blocking for merge, both quick:

  1. CLA. The CLA check is failing; signing is required on every PR. Please sign per the bot's instructions in this thread and comment recheck.
  2. Release notes. Community fixes get an entry in the current planned release file. Please add a short entry near the top of the Bug fixes section in RELEASE_NOTES_2026.09.2.md describing the fix, ending with the standard credit line you can copy from any neighboring entry.

@xe-nvdk

xe-nvdk commented Sep 7, 2026

Copy link
Copy Markdown
Member

@MrBeldum thank you for this fix — the review verified it end to end, including a live 504 A/B against a pre-fix build, and it is ready to merge from our side.

To move it along I have covered the release-notes item from my review myself: your branch now carries the 26.09.2 entry with your credit line, plus a merge with current main so everything is up to date. The only remaining step is yours: please sign the CLA per the bot's instructions in this thread and comment recheck. As soon as that check flips green, this merges (and it unblocks #705, which builds on your context wiring).

@MrBeldum

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@MrBeldum

Copy link
Copy Markdown
Author

recheck

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

high(query): queryMeasurement endpoint has no timeout

2 participants