Skip to content

rpc: allow sharing the in-flight Semaphore across ExecutionContexts#7647

Merged
jkschneider merged 1 commit into
mainfrom
rpc-shared-in-flight-semaphore
May 11, 2026
Merged

rpc: allow sharing the in-flight Semaphore across ExecutionContexts#7647
jkschneider merged 1 commit into
mainfrom
rpc-shared-in-flight-semaphore

Conversation

@jkschneider
Copy link
Copy Markdown
Member

Summary

  • setMaxInFlight(int) from rpc: cap concurrent in-flight requests via ExecutionContext #7614 stored an int on the ExecutionContext and lazily built the Semaphore inside withInFlightSlot. Each independent ExecutionContext therefore ended up with its own Semaphore, so the cap was per-ctx, not host-wide.
  • Add setInFlightSemaphore(Semaphore) so callers that want a true host-wide cap can construct one Semaphore once at the orchestrator level and install the same instance on every participating context (e.g. one per repo task running in parallel).
  • Keep setMaxInFlight(int) as a single-ctx convenience but document that it is not host-wide.
  • withInFlightSlot is unthrottled when no Semaphore is installed, matching the prior "unbounded by default" baseline.

This unblocks Moderne's mod run and the SaaS recipe-worker from honoring a true process-wide rewrite-rpc concurrency cap; the wiring on those sides is in follow-up PRs.

Test plan

  • New RewriteRpcExecutionContextViewTest covers: no-op default, fresh-Semaphore-from-setMaxInFlight, per-ctx isolation (the misuse pattern callers hit today), true sharing across many ctx/threads, permit release on exception.
  • ./gradlew :rewrite-core:test --tests '*Rpc*' green locally.

The cap added in #7614 was scoped per-ExecutionContext: setMaxInFlight
stored an int in the ctx message map and withInFlightSlot lazily created
a Semaphore from it. Each independent ExecutionContext therefore got its
own Semaphore, which made the cap a per-ctx cap rather than the host-wide
cap callers like Moderne SaaS and the mod CLI expect when they create one
InMemoryExecutionContext per repo and run several in parallel.

Replace the int-message + lazy-create plumbing with a Semaphore-valued
message and an explicit setInFlightSemaphore(Semaphore) setter. Callers
that want a host-wide cap construct one Semaphore at the orchestrator
level and install the same instance on every participating context. The
old setMaxInFlight(int) is kept as a convenience for the single-ctx case
but its Javadoc now spells out that it is not host-wide. withInFlightSlot
runs the work unthrottled if no Semaphore is installed, preserving the
"unbounded by default" behavior.

Adds RewriteRpcExecutionContextViewTest covering: no-op default, fresh
Semaphore from setMaxInFlight, per-ctx isolation (the misuse pattern),
true sharing across many ctx/threads, and permit release on exception.
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite May 11, 2026
@jkschneider jkschneider merged commit 7094cba into main May 11, 2026
1 check passed
@jkschneider jkschneider deleted the rpc-shared-in-flight-semaphore branch May 11, 2026 12:41
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant