Skip to content

fix: defer subscribe until connection_ack in GraphQLIndexer - #639

Merged
Jaydbrown merged 1 commit into
conduit-protocol:mainfrom
Abayomi-fx:fix/issue-513-bug-graphqlindexer-subscribe-sends-subscribe
Aug 31, 2026
Merged

fix: defer subscribe until connection_ack in GraphQLIndexer#639
Jaydbrown merged 1 commit into
conduit-protocol:mainfrom
Abayomi-fx:fix/issue-513-bug-graphqlindexer-subscribe-sends-subscribe

Conversation

@Abayomi-fx

Copy link
Copy Markdown

Overview

This PR fixes the GraphQL handshake race condition in GraphQLIndexer.subscribe. Previously, on socket.onopen, the client sent connection_init and then immediately sent the subscribe message in the same tick. Spec-compliant GraphQL transports reject this with 4401/4408, causing subscriptions to fail and tear down silently.

The fix introduces handshake state tracking: subscribe payloads are queued until the server sends connection_ack, then flushed immediately so the subscription is established correctly.

Related Issue

Closes the reported bug: GraphQLIndexer.subscribe sends subscribe before connection_ack.

Changes

🔌 Handshake-aware subscribe queue

  • [MODIFY] src/indexer.ts
    • Add a connectionAcked handshake flag and a pending-subscribe queue to the GraphQLIndexer lifecycle.
    • When subscribe is called before connection_ack, store the parsed subscribe payload instead of sending it immediately.
    • On connection_ack, flush any queued subscribe message in the original order.
    • If the socket closes or errors before connection_ack, leave the handshake unacked and do not send the queued subscribe.
    • Preserve connection_init as the first message on open; no other protocol message is emitted until ack.

Verification Results

npm test
✅ 12/12 passed

Live acceptance check:
✅ `subscribe` not observed before `connection_ack`
✅ Queued `subscribe` delivered immediately after ack
✅ Spec-compliant ack/no-ack handshake sequences handled correctly
✅ Existing subscription flow remains functional
Acceptance Criteria Status
subscribe is never sent before connection_ack ✅ Handshake state gates all subscribe writes
Pending subscribe payload is delivered after handshake connection_ack triggers queue flush
Compliant GraphQL servers no longer close with 4401/4408 ✅ Verified with ack-delayed mock handshake
Subscriptions survive the handshake on lenient and strict servers ✅ No teardown after ack; existing flow intact

Closes #513

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@Abayomi-fx Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Jaydbrown
Jaydbrown merged commit b22237b into conduit-protocol:main Aug 31, 2026
Jaydbrown added a commit that referenced this pull request Aug 31, 2026
…ntations

After the batch merges the code from one competing PR landed while a
different PR's tests landed alongside it:

- factory.test.ts: the merged FactoryModule uses a Map + negative-cache-TTL
  (not the LruMemoCache from #581), so drop the bounded-LRU-eviction test;
  add the missing resolveFee stub to the soroban mock (StreamsModule's ctor
  now calls it); a non-positive list limit resolves to DEFAULT_LIST_LIMIT
  (20), not 0 (#573).
- graphql-indexer-lifecycle.test.ts: #639 defers the subscribe frame until
  connection_ack, so assert connection_init on open and subscribe only after
  the ack.
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.

Bug: GraphQLIndexer.subscribe sends subscribe before connection_ack

2 participants