Fix spec303 flaky failure in ordered publisher TCK tests by andimarek · Pull Request #4293 · graphql-java/graphql-java · GitHub
Skip to content

Fix spec303 flaky failure in ordered publisher TCK tests#4293

Merged
andimarek merged 1 commit into
masterfrom
fix/ordered-tck-spec303-flaky
Mar 5, 2026
Merged

Fix spec303 flaky failure in ordered publisher TCK tests#4293
andimarek merged 1 commit into
masterfrom
fix/ordered-tck-spec303-flaky

Conversation

@andimarek

Copy link
Copy Markdown
Member

Summary

  • Fixes the intermittent spec303_mustNotAllowUnboundedRecursion failure on Java 11 in CompletionStageMappingOrderedPublisherTckVerificationTest
  • Root cause: the ordered subscriber's drain loop (emptyInFlightQueueIfWeCan) calls onNext for every completed CF in a while loop. With per-element executors (one newSingleThreadExecutor() per mapper call), multiple CFs complete concurrently on different threads. When the drain loop runs, it finds several completed CFs and calls onNext multiple times on the same thread — the TCK flags this as a spec303 violation.
  • Fix: use a shared single-thread executor per publisher. CFs now complete sequentially, so when the drain loop runs on the executor thread, no other CFs can complete (they're queued), and the loop only processes one item at a time.

Test plan

  • Ran testngWithJava11 5 times locally — all pass (190 tests each)
  • Verified the fix applies to both CompletionStageMappingOrderedPublisherTckVerificationTest and CompletionStageMappingOrderedPublisherRandomCompleteTckVerificationTest

🤖 Generated with Claude Code

The ordered subscriber's drain loop (emptyInFlightQueueIfWeCan) calls
onNext for every completed CF in a while loop. With per-element
executors, multiple CFs can complete concurrently, so the drain loop
calls onNext multiple times on the same thread — the TCK flags this as
a spec303 (unbounded recursion) violation.

Fix: use a shared single-thread executor per publisher instead of a new
executor per element. This ensures CFs complete sequentially, so when
the drain loop runs on the executor thread, no other CFs can complete
(they're queued behind it), and the loop only processes one item.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

@andimarek andimarek merged commit e533fec into master Mar 5, 2026
9 checks passed
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.

1 participant