fix: don't double-send status to command requester

load_graph/stop_node/start_node each called notify() (push to all
clients) and then sent a direct response — the requesting client
got two identical messages, breaking test recv sequencing.

Use thread_local tl_requester to skip the requesting connection
in the push. notify() is called synchronously from the command,
so the thread_local is visible from the status_cb. Other clients
still receive the push; the requester gets only the direct response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
JohannesItten
2026-07-07 22:39:09 +03:00
parent 59b2ee437c
commit 6c6225d831
+10 -2
View File
@@ -45,11 +45,17 @@ int main(int argc, char* argv[]) {
std::mutex ws_mutex;
std::unordered_set<crow::websocket::connection*> clients;
// Push status to every connected client (called without manager mutex held).
// Push status to every connected client except the one whose command triggered
// the change — that client gets the direct response from the handler instead.
// tl_requester is thread-local: notify() is called synchronously from within
// the manager command, so it runs on the same thread as onmessage.
thread_local crow::websocket::connection* tl_requester = nullptr;
manager.on_status_change([&](nlohmann::json status) {
std::lock_guard lk(ws_mutex);
const std::string msg = status.dump();
for (auto* c : clients) c->send_text(msg);
for (auto* c : clients)
if (c != tl_requester) c->send_text(msg);
});
CROW_WEBSOCKET_ROUTE(app, "/ws")
@@ -76,6 +82,7 @@ int main(int argc, char* argv[]) {
nlohmann::json response;
const std::string type = j.value("type", "");
tl_requester = &conn;
try {
if (type == "load_graph") response = manager.load_graph(j.at("graph"));
else if (type == "stop_node") response = manager.stop_node(j.at("id"));
@@ -85,6 +92,7 @@ int main(int argc, char* argv[]) {
} catch (const std::exception& e) {
response = {{"type","error"},{"message", e.what()}};
}
tl_requester = nullptr;
conn.send_text(response.dump());
});