Commit c9102a9
feat(redshift-mcp-server): long poll the Data API for statement status (#4560)
* feat(redshift-mcp-server): long poll the Data API for statement status
Every statement waited for completion by calling DescribeStatement once per
second, and each execute_query runs three statements (BEGIN READ ONLY, user
SQL, ROLLBACK), so a warm read-only query cost at least 8 Data API calls: 3
ExecuteStatement, 4 DescribeStatement and 1 GetStatementResult.
The Data API now supports long polling. WaitTimeSeconds (1-30) holds the
request open until the statement reaches a terminal status or the wait
elapses, and is accepted on both ExecuteStatement and DescribeStatement.
- Send WaitTimeSeconds, from the new QUERY_LONG_POLL constant, on
ExecuteStatement and on every DescribeStatement poll. Setting it to 0
restores plain QUERY_POLL_INTERVAL polling.
- Collapse the completion wait into a single loop that evaluates whichever
response came last, since both operations report Status identically.
- Return the terminal statement response from _execute_statement rather than
just the id, so _create_session_with_app_name reads SessionId and
_execute_protected_statement reads HasResultSet off it. Both callers drop
their own DescribeStatement call.
- Track the timeout with time.monotonic(), since accumulated sleeps stop
approximating elapsed time once a call blocks server-side.
- Fall back to plain polling on ActiveWaitingRequestsExceededException, which
the service raises when too many requests wait on one statement.
- Require boto3/botocore >= 1.43.55, the first release carrying
WaitTimeSeconds in the redshift-data service model.
- Cover long polling, the terminal-status shortcut, the disabled path and the
waiter-limit fallback in TestExecuteStatement.
A warm read-only query now costs 4 calls, and a statement with no result set
costs 1. Only a failing statement still needs a DescribeStatement, to read the
Error field that ExecuteStatement does not carry.
Verified end-to-end against live provisioned and serverless clusters.
* fix(redshift-mcp-server): run Data API calls off the event loop
boto3 is synchronous, so long polling turned each Data API call into an event
loop stall of up to WaitTimeSeconds. Measured against a live cluster, a 79s
query blocked the loop for 48s in one stretch and let a 50ms heartbeat tick
once rather than the ~1579 times expected, which serialized every other
in-flight tool call and stalled MCP protocol traffic. Before long polling the
same calls blocked only for a short HTTP round trip.
- Run execute_statement and both describe_statement calls in _execute_statement
through asyncio.to_thread.
- Add a regression test that fails when a blocking Data API call starves a
concurrent coroutine.
The same query now yields 1552 heartbeat ticks with a 0.05s worst gap.
Reported by Copilot on #4560.
---------
Co-authored-by: Sergey Konoplev <sergkono@amazon.com>
Co-authored-by: Laith Al-Saadoon <9553966+theagenticguy@users.noreply.github.com>1 parent 6d6067c commit c9102a9
5 files changed
Lines changed: 334 additions & 131 deletions
File tree
- src/redshift-mcp-server
- awslabs/redshift_mcp_server
- tests
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
Lines changed: 52 additions & 30 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
| |||
206 | 207 | | |
207 | 208 | | |
208 | 209 | | |
209 | | - | |
| 210 | + | |
210 | 211 | | |
211 | 212 | | |
212 | 213 | | |
213 | 214 | | |
214 | 215 | | |
215 | 216 | | |
216 | 217 | | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
| 218 | + | |
221 | 219 | | |
222 | 220 | | |
223 | 221 | | |
| |||
296 | 294 | | |
297 | 295 | | |
298 | 296 | | |
299 | | - | |
| 297 | + | |
300 | 298 | | |
301 | 299 | | |
302 | 300 | | |
| |||
316 | 314 | | |
317 | 315 | | |
318 | 316 | | |
319 | | - | |
| 317 | + | |
320 | 318 | | |
321 | 319 | | |
322 | 320 | | |
323 | | - | |
| 321 | + | |
324 | 322 | | |
325 | 323 | | |
326 | 324 | | |
| |||
357 | 355 | | |
358 | 356 | | |
359 | 357 | | |
360 | | - | |
361 | | - | |
362 | | - | |
363 | | - | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
364 | 362 | | |
365 | 363 | | |
366 | | - | |
367 | | - | |
| 364 | + | |
| 365 | + | |
368 | 366 | | |
369 | 367 | | |
370 | 368 | | |
| |||
381 | 379 | | |
382 | 380 | | |
383 | 381 | | |
384 | | - | |
| 382 | + | |
| 383 | + | |
385 | 384 | | |
386 | 385 | | |
387 | 386 | | |
| |||
394 | 393 | | |
395 | 394 | | |
396 | 395 | | |
| 396 | + | |
397 | 397 | | |
398 | 398 | | |
399 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
400 | 403 | | |
401 | 404 | | |
402 | 405 | | |
| |||
423 | 426 | | |
424 | 427 | | |
425 | 428 | | |
426 | | - | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
427 | 436 | | |
428 | 437 | | |
429 | 438 | | |
430 | 439 | | |
431 | 440 | | |
432 | 441 | | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
438 | 447 | | |
439 | 448 | | |
440 | 449 | | |
441 | | - | |
| 450 | + | |
442 | 451 | | |
443 | | - | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
444 | 459 | | |
445 | 460 | | |
446 | 461 | | |
447 | | - | |
448 | | - | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
449 | 465 | | |
450 | | - | |
451 | | - | |
452 | | - | |
| 466 | + | |
453 | 467 | | |
454 | | - | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
455 | 477 | | |
456 | 478 | | |
457 | 479 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
0 commit comments