[fix] recover initial MCP signaling connections and preserve failure reasons

This commit is contained in:
dijunkun
2026-11-06 20:02:52 +08:00
parent 09ef60dc6f
commit 2535a04d2b
10 changed files with 83 additions and 17 deletions
+12 -3
View File
@@ -14,6 +14,17 @@ std::string DiagnosticEvent(const spdlog::details::log_msg &message) {
const std::string_view text(message.payload.data(), message.payload.size());
if (source == "controller_session.cpp")
return std::string(text); // Local states/counters only at these call sites.
if (source == "ws_client.cpp") {
if (text == "WebSocket connection opened") return std::string(text);
// These call sites contain library category names, numeric codes and retry
// counters. Keep free-form errors, server close reasons and URLs filtered.
for (const std::string_view prefix : {
"Signaling transport failure: category=",
"Signaling transport closed: code=",
"Scheduling signaling reconnect: attempt=",
"Will retry connection after "})
if (text.substr(0, prefix.size()) == prefix) return std::string(text);
}
if (source == "ice_transport.cpp") {
const auto marker = text.rfind("state_change: ");
if (marker != std::string_view::npos) {
@@ -70,10 +81,8 @@ private:
void InitializeControllerDiagnostics(const std::string &directory) {
auto sink = std::make_shared<DiagnosticSink>(directory);
minirtc::InitLogger(directory);
minirtc::InitLogger(directory, std::move(sink));
auto logger = minirtc::get_logger();
// Connect calls this after the previous peer and its callbacks stop.
logger->sinks() = {std::move(sink)};
logger->set_level(spdlog::level::info);
}
} // namespace crossdesk
+13 -4
View File
@@ -168,6 +168,10 @@ void ControllerSession::Tick() {
Fail("control_event_overflow");
return;
}
if (!Connected() && std::chrono::steady_clock::now() >= deadline_) {
Fail(state_ == "registering" ? "signaling_timeout" : "connection_timeout");
return;
}
for (auto &e : pending) {
if (Finished())
break;
@@ -181,6 +185,13 @@ void ControllerSession::Tick() {
Fail("signaling_login_failed");
break;
}
// The initial signaling transport can recover before a remote join is
// sent. Keep its backoff worker alive within the original deadline.
if (e.code == SignalReconnecting && state_ == "registering") {
SPDLOG_LOGGER_INFO(minirtc::get_logger(),
"Initial signaling retry within connection deadline");
continue;
}
if (e.code == SignalClosed || e.code == SignalServerClosed ||
e.code == SignalReconnecting) {
Fail("signaling_disconnected");
@@ -258,9 +269,6 @@ void ControllerSession::Tick() {
FreeRemoteAction(a);
}
}
if (!Connected() && !Finished() &&
std::chrono::steady_clock::now() > deadline_)
Fail("connection_timeout");
}
bool ControllerSession::Send(const char *stream, const std::string &payload) {
return peer_ && Connected() && !payload.empty() &&
@@ -282,7 +290,8 @@ void ControllerSession::ClosePeers() {
password_.clear();
}
void ControllerSession::Fail(const char *reason) {
SPDLOG_LOGGER_INFO(minirtc::get_logger(), "Session failed: {}", reason);
SPDLOG_LOGGER_INFO(minirtc::get_logger(), "Session failed: {} (stage {})",
reason, state_);
ReleaseInput();
error_ = reason;
state_ = "failed";