Add PingMiddleware for keepalive connections#2838
Conversation
WalkthroughThis PR adds a new PingMiddleware class to send periodic pings and keep client connections alive. The middleware accepts a configurable interval parameter (defaulting to 30,000 milliseconds) and validates that the interval is positive. Upon receiving the first message from a session, it initiates a background ping task using the session's subscription task group. The ping loop executes repeatedly at the configured interval until the session terminates, at which point the session is removed from active tracking. Thread-safe initialization is ensured via an internal lock. The implementation is exported in the middleware module's \ 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (4)docs/**/*.mdx📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)
Files:
docs/**/*.{md,mdx,json}📄 CodeRabbit inference engine (AGENTS.md)
Files:
docs/**/*.{md,mdx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
src/fastmcp/**/*.py📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2025-12-25T15:53:07.656ZApplied to files:
🧬 Code graph analysis (2)src/fastmcp/server/middleware/ping.py (2)
src/fastmcp/server/middleware/__init__.py (2)
🪛 Ruff (0.14.10)src/fastmcp/server/middleware/ping.py37-37: Avoid specifying long messages outside the exception class (TRY003) ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
🔇 Additional comments (5)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30b7c74bf3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if session_id not in self._active_sessions: | ||
| # _subscription_task_group is added by MiddlewareServerSession | ||
| tg = session._subscription_task_group # type: ignore[attr-defined] | ||
| if tg is not None: | ||
| self._active_sessions.add(session_id) |
There was a problem hiding this comment.
Guard ping-loop creation against concurrent messages
Incoming messages are handled concurrently (see LowLevelServer.run starting each message in its own task), so two overlapping requests from the same session can both pass this session_id not in _active_sessions check before the set is updated, spawning multiple ping loops and sending duplicate pings for that session. This can happen when a client issues concurrent requests on a single connection. Consider synchronizing this check/add (e.g., an anyio.Lock or a per-session flag) so only one ping task starts.
Useful? React with 👍 / 👎.
Adds
PingMiddlewarethat sends periodic server-to-client pings to keep long-lived connections alive. This addresses the issue where clients drop connections unnecessarily when servers don't periodically ping.The middleware starts a background ping task on first message from each session, using the session's existing task group for automatic cleanup when the session ends.
Closes #1212