Skip to content

Core: Make REST async planning pool bounded and configurable#16332

Open
aamir306 wants to merge 1 commit into
apache:mainfrom
aamir306:feat/async-planning-pool-bounded
Open

Core: Make REST async planning pool bounded and configurable#16332
aamir306 wants to merge 1 commit into
apache:mainfrom
aamir306:feat/async-planning-pool-bounded

Conversation

@aamir306
Copy link
Copy Markdown

Summary

Replaces the unbounded single-thread ASYNC_PLANNING_POOL in CatalogHandlers with a bounded, configurable thread pool. This prevents thread exhaustion under high concurrency and allows operators to tune the pool size for their workloads.

Motivation

The current ASYNC_PLANNING_POOL is a single-threaded, unbounded-queue executor:

private static final ExecutorService ASYNC_PLANNING_POOL =
    ThreadPools.newExitingWorkerPool("iceberg-async-planning", 1);

Problems:

  1. Head-of-line blocking – All async planning requests serialize through a single thread, creating a bottleneck for concurrent REST catalog clients.

  2. Unbounded queue growth – Under load, the unbounded queue can grow without limit, consuming memory and increasing latency for queued requests.

  3. No tuning knob – Operators have no way to adjust the pool size for their deployment's characteristics.

Changes

  • Added ICEBERG_REST_ASYNC_PLANNING_POOL_SIZE system config (default: 4, minimum: 1)
  • Created bounded thread pool with ArrayBlockingQueue(256) to prevent runaway queue growth
  • Uses CallerRunsPolicy for graceful degradation when the queue is full
  • Preserved thread naming for observability

Configuration

# Set via system property
-Diceberg.rest.async-planning.pool-size=8

# Or environment variable
ICEBERG_REST_ASYNC_PLANNING_POOL_SIZE=8

Test plan

  • Added TestAsyncPlanningPoolConfig with tests for:
    • Default value (4)
    • Custom configuration
    • Minimum bound enforcement
  • Verified existing REST catalog tests pass

Compatibility

  • Backward compatible – Default of 4 threads is a strict improvement over the previous single thread
  • No API changes – Only internal implementation detail

Made with Cursor

Replace the single-threaded executor in CatalogHandlers with a bounded
thread pool configurable via system property or environment variable.
This addresses the server-side scan planning bottleneck flagged by
@chenwyi2 in the review of PR apache#14480.

Changes:
- Add SystemConfigs.REST_ASYNC_PLANNING_THREADS config entry with
  system property 'iceberg.rest.async-planning-threads' and env var
  'ICEBERG_REST_ASYNC_PLANNING_THREADS'
- Default pool size is max(2, availableProcessors)
- Use ThreadPools.newExitingWorkerPool() for proper shutdown handling
- Expose ASYNC_PLANNING_THREADS as public constant for server
  implementations to access the configured value
- Add tests validating configuration properties and defaults

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added the core label May 14, 2026
aamir306 added a commit to shelf-project/shelf that referenced this pull request May 14, 2026
…ixes

- Add TODO-fix-shelf-performance.md with tiered perf improvement plan
  (honest PhD-grade analysis: 3.5× ceiling, not 20×)
- Add docs/upstream/TRINO-CONTRIBUTION-CANDIDATES.md with 5 phases
- Add docs/upstream/ICEBERG-CONTRIBUTION-CANDIDATES.md with 4 phases
- Fix integration test gating: use `--features integration` cargo flag
  instead of deprecated SHELF_INTEGRATION=1 env var
- Update charts/shelf/values.yaml with admission throttle documentation
  (SHELF-29 LODC admission is ON by default at 200 MiB/s)

Upstream PRs created:
- trinodb/trino#29482: Decouple SplitAffinityProvider binding
- apache/iceberg#16332: Bounded async planning pool

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant