-
Notifications
You must be signed in to change notification settings - Fork 711
fix(streamable_http): ensure graceful shutdown to prevent close reque… #477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…st errors Added sync.WaitGroup to wait for asynchronous session cleanup goroutine to finish wg.Add(1) is used before spawning the goroutine; wg.Done() is called upon completion wg.Wait() ensures Close() blocks until the cleanup finishes, preserving correct shutdown order Fixes an issue in tests where closing the client and server in quick succession could lead to connection refused errors due to the client's asynchronous close attempting to reach a server that has already shut down Removed redundant blank lines to streamline the code structure
WalkthroughA sync.WaitGroup field was introduced to the StreamableHTTP struct to synchronize the completion of a session close notification goroutine in the Close() method. The Close() method now waits for the notification goroutine to finish before returning. Several unnecessary blank lines were also removed from various methods. Changes
Suggested reviewers
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
client/transport/streamable_http.go (1)
186-206: Close() now blocks correctly, but the wait group is very specificThe added
wg.Add/Done/Waitpattern correctly serialises the async DELETE, 👍.
Two nits you may want to address:
Scope: the WG only tracks the session-close goroutine; other long-lived goroutines (
listenForever, SSE readers) can still be alive whenClose()returns and may leak if the caller expects full shutdown.Clarity: naming the field
closeWg(or similar) would make its intent crystal clear.Neither issue is blocking, but clarifying would improve maintainability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
client/transport/streamable_http.go(3 hunks)
🔇 Additional comments (1)
client/transport/streamable_http.go (1)
117-118: Beware of struct copying after embedding a sync.WaitGroupEmbedding
wg sync.WaitGroupdirectly makes the wholeStreamableHTTPstruct non-copyable after first use (the sync package panics on WaitGroup misuse when copied). The current API always hands out a*StreamableHTTP, but nothing prevents downstream code from taking a value copy (e.g.,val := *client).
Consider documenting this explicitly or embedding a pointer (wg *sync.WaitGroup) to hard-prevent accidental copies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for fixing this @sunerpy
…st errors
newTestMCPServer return a *httptest.Server like:
console errors:
2025/07/09 10:32:34 ERROR: failed to send close request: Delete "http://127.0.0.1:43485/mcp": dial tcp 127.0.0.1:43485: connect: connection refused
Description
Added sync.WaitGroup to wait for asynchronous session cleanup goroutine to finish
wg.Add(1) is used before spawning the goroutine; wg.Done() is called upon completion
wg.Wait() ensures Close() blocks until the cleanup finishes, preserving correct shutdown order
Fixes an issue in tests where closing the client and server in quick succession could lead to connection refused errors due to the client's asynchronous close attempting to reach a server that has already shut down
Removed redundant blank lines to streamline the code structure
Type of Change
Checklist
Additional Information
This PR fixes a race condition in
StreamableHTTP.Close()where the asynchronous close request may be sent after the server is already shut down, leading toconnection refusederrors in tests.Summary by CodeRabbit
Bug Fixes
Style