Skip to content

Emit static responses exactly once regardless of subscriber demand shape#636

Merged
slinkydeveloper merged 2 commits into
restatedev:mainfrom
nikhiln64:fix/http-vertx-response-backpressure
Jul 14, 2026
Merged

Emit static responses exactly once regardless of subscriber demand shape#636
slinkydeveloper merged 2 commits into
restatedev:mainfrom
nikhiln64:fix/http-vertx-response-backpressure

Conversation

@nikhiln64

@nikhiln64 nikhiln64 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

StaticResponseRequestProcessor (discovery, health responses) re-emits the whole response body and re-signals onComplete on every request() call, violating Reactive Streams rules 1.7/2.12.

Today this is masked because both current subscribers issue request(Long.MAX_VALUE) exactly once. The moment any subscriber uses bounded per-item requests, the discovery response gets duplicated hundreds of times — reproduced E2E while prototyping #614: the runtime received a 2.39 MB discovery body (~1000 copies of the JSON) and rejected it with trailing characters at line 1 column 1180. Fixed with a single-emission guard.

Context in #614 (comment) — the response-side backpressure work itself is on hold pending a design decision on RequestProcessorImpl's output demand semantics.

(This PR originally also carried a request-side pause/fetch change in sdk-http-vertx; reverted per review.)

Testing

  • New StaticResponseRequestProcessorTest: exactly-once emission under bounded and unbounded demand, error on non-positive demand.
  • :sdk-testing:test (testcontainers, real runtime) green.

Developed with AI assistance (Claude Code), reviewed and driven by a human.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Test Results

   29 files  +   21     29 suites  +21   56s ⏱️ - 2m 36s
1 289 tests +1 229  1 284 ✅ +1 224  5 💤 +5  0 ❌ ±0 
1 289 runs  +1 022  1 284 ✅ +1 017  5 💤 +5  0 ❌ ±0 

Results for commit c412475. ± Comparison against base commit a5f770d.

This pull request removes 60 and adds 1289 tests. Note that renamed tests count towards both.
dev.restate.sdktesting.tests.CallOrdering ‑ ordering(boolean[], Client)[1]
dev.restate.sdktesting.tests.CallOrdering ‑ ordering(boolean[], Client)[2]
dev.restate.sdktesting.tests.CallOrdering ‑ ordering(boolean[], Client)[3]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromAdminAPI(BlockingOperation, Client, URI)[1]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromAdminAPI(BlockingOperation, Client, URI)[2]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromAdminAPI(BlockingOperation, Client, URI)[3]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromContext(BlockingOperation, Client)[1]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromContext(BlockingOperation, Client)[2]
dev.restate.sdktesting.tests.Cancellation ‑ cancelFromContext(BlockingOperation, Client)[3]
dev.restate.sdktesting.tests.Combinators ‑ awakeableOrTimeoutUsingAwaitAny(Client)
…
RestateRequestIdentityVerifierTest ‑ parseKey()
dev.restate.bytebuddy.proxysupport.ByteBuddyProxyFactoryTest ‑ Final class should fail
dev.restate.bytebuddy.proxysupport.ByteBuddyProxyFactoryTest ‑ Final method should fail
dev.restate.bytebuddy.proxysupport.ByteBuddyProxyFactoryTest ‑ Invoking non restate method should fail
dev.restate.bytebuddy.proxysupport.ByteBuddyProxyFactoryTest ‑ Package private method should fail
dev.restate.client.kotlin.ScopedClientTest ‑ scope returns the platform ScopedClient, not a Kotlin-specific type()
dev.restate.client.kotlin.ScopedClientTest ‑ scoped call encodes scope in the path()
dev.restate.client.kotlin.ScopedClientTest ‑ scoped keyed send encodes scope, key and send verb in the path()
dev.restate.client.kotlin.ScopedClientTest ‑ scoped send with limit key uses the limit-key query param()
dev.restate.client.kotlin.ScopedClientTest ‑ scoped service proxy routes the call within the scope()
…

♻️ This comment has been updated with latest results.

@nikhiln64 nikhiln64 changed the title Bound the HTTP request buffer queue and emit static responses exactly once (#614 partial) Emit static responses exactly once regardless of subscriber demand shape Jul 14, 2026
… once

Two demand-handling fixes surfaced by restatedev#614:

1. HttpRequestFlowAdapter pushed every incoming buffer into an unbounded
   ArrayDeque regardless of subscriber demand. Pause the request stream
   on construction and mirror subscriber demand into Vert.x pull-mode
   fetch(), so buffers are only delivered (and queued) as requested.

2. StaticResponseRequestProcessor (discovery/health responses) re-emitted
   the whole response body and re-signalled onComplete on every request()
   call, violating Reactive Streams rules 1.7/2.12. This is currently
   masked by subscribers requesting Long.MAX_VALUE exactly once: any
   subscriber using bounded per-item requests duplicates the discovery
   response until the runtime rejects it as undecodable JSON. Emit
   exactly once.

Verified with the sdk-testing testcontainers suite against a real
runtime, plus new unit tests for both classes.
Keep only the StaticResponseRequestProcessor exactly-once fix and its
test.
@nikhiln64 nikhiln64 force-pushed the fix/http-vertx-response-backpressure branch from 40806ca to c412475 Compare July 14, 2026 14:01
@nikhiln64

Copy link
Copy Markdown
Contributor Author

recheck

@slinkydeveloper

Copy link
Copy Markdown
Contributor

@nikhiln64 can you follow this? #636 (comment)

@nikhiln64

nikhiln64 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

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

@nikhiln64

Copy link
Copy Markdown
Contributor Author

recheck

@slinkydeveloper

Copy link
Copy Markdown
Contributor

this works, great!

@slinkydeveloper slinkydeveloper merged commit af854ba into restatedev:main Jul 14, 2026
8 of 9 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 14, 2026
@slinkydeveloper

Copy link
Copy Markdown
Contributor

Thanks for the contribution, we'll release this on the next patch release of the sdk

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants