Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

Add timeout and fallback logging for closeGracefully() to prevent hanging shutdown

未關閉
#635 1 則留言 1 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
50/100
Issue 類型
功能
描述清晰度
基本清楚
活躍度
停滯
技術堆疊
java
領域
api

研究方向

先閱讀 McpAsyncClient.closeGracefully(),接著檢查 initializer.closeGracefully() 和 transport.closeGracefully(),以了解它們的完成行為。確認 timeout 處理、警告和作為 fallback 的強制關閉、錯誤處理以及最終完成,能讓關閉流程具有限制,同時不改變預期的 graceful 路徑。

由索引模型根據 Issue 內容生成。

描述

enhancement needs repro

Problem

When using McpAsyncClient.closeGracefully(), the client executes:

return this.initializer.closeGracefully()
        .then(transport.closeGracefully());

Both initializer.closeGracefully() and transport.closeGracefully() return Mono<Void>.
However, if either of them hangs—for example:

  • The underlying transport (HTTP/SSE/WebSocket) never completes
  • The server doesn’t respond to shutdown
  • A Reactor pipeline remains open (no onComplete)

then the returned Mono never completes, causing the application to hang indefinitely during shutdown.

This results in JVMs or containers that never terminate, blocking CI/CD or production deployments.


Goal

Add a timeout and fallback mechanism to ensure that the client always terminates safely, even when the transport or initializer fails to complete.


Proposed Change

1. Wrap shutdown calls with timeout and fallback

Use Reactor’s timeout(Duration, fallbackMono) operator to guarantee a bounded shutdown duration.

public Mono<Void> closeGracefully() {
    return Mono.defer(() -> {
        long start = logger.isDebugEnabled() ? System.nanoTime() : 0L;
        Duration timeout = Duration.ofSeconds(
                Integer.getInteger("mcp.shutdown.timeout.seconds", 10));

        Mono<Void> graceful = this.initializer.closeGracefully()
            .then(transport.closeGracefully());

        Mono<Void> fallback = Mono.fromRunnable(() -> {
                logger.warn("closeGracefully() timed out after {} seconds; proceeding with best-effort shutdown.", timeout.getSeconds());
                try {
                    this.transport.close(); // force-close if needed
                } catch (Throwable t) {
                    logger.warn("Fallback forced close encountered error: {}", t.toString());
                }
            })
            .then();

        return graceful
            .timeout(timeout, fallback)
            .doOnError(e -> logger.warn("closeGracefully() failed: {}", e.toString()))
            .onErrorResume(e -> Mono.empty()) // ensure app doesn't hang
            .doFinally(sig -> {
                if (logger.isDebugEnabled()) {
                    long durationMs = (System.nanoTime() - start) / 1_000_000;
                    logger.debug("closeGracefully() finished with signal={}, took {} ms", sig, durationMs);
                }
            });
    });
}

Summary

Introduce a timeout and fallback mechanism for closeGracefully() to guarantee reliable termination, preventing hanging shutdowns when the transport or lifecycle initializer fails to complete.


主要語言
Java
星號
3.7k
分支
1.1k
平均合併
1 天 15 小時
30 天內合併 PR
9

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

modelcontextprotocol/java-sdk 的其他 Issue

查看 modelcontextprotocol/java-sdk 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。