From a9f56c1279fef33b132fc3ac34f535430cf7f756 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Tue, 23 Sep 2025 21:03:13 +0200 Subject: [PATCH] fix: tasks endpoint response --- include/spore/types/ApiResponse.h | 18 +++++++++++- include/spore/types/ClusterResponse.h | 3 +- include/spore/types/NodeResponse.h | 3 +- include/spore/types/TaskInfoSerializable.h | 5 +++- include/spore/types/TaskResponse.h | 33 ++++++++++++++++++---- src/spore/services/TaskService.cpp | 5 +++- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/include/spore/types/ApiResponse.h b/include/spore/types/ApiResponse.h index ba87392..5dc7744 100644 --- a/include/spore/types/ApiResponse.h +++ b/include/spore/types/ApiResponse.h @@ -57,7 +57,23 @@ public: * @param item The serializable item to add */ void addItem(const util::JsonSerializable& item) { - JsonArray arr = doc[collectionKey].to(); + if (!doc[collectionKey].is()) { + doc[collectionKey] = JsonArray(); + } + JsonArray arr = doc[collectionKey].as(); + JsonObject obj = arr.add(); + item.toJson(obj); + } + + /** + * Add a serializable item to the collection (move version) + * @param item The serializable item to add + */ + void addItem(util::JsonSerializable&& item) { + if (!doc[collectionKey].is()) { + doc[collectionKey] = JsonArray(); + } + JsonArray arr = doc[collectionKey].as(); JsonObject obj = arr.add(); item.toJson(obj); } diff --git a/include/spore/types/ClusterResponse.h b/include/spore/types/ClusterResponse.h index ae5f21b..c39ae4d 100644 --- a/include/spore/types/ClusterResponse.h +++ b/include/spore/types/ClusterResponse.h @@ -19,8 +19,7 @@ public: * @param node The NodeInfo to add */ void addNode(const NodeInfo& node) { - NodeInfoSerializable serializable(const_cast(node)); - addItem(serializable); + addItem(NodeInfoSerializable(const_cast(node))); } /** diff --git a/include/spore/types/NodeResponse.h b/include/spore/types/NodeResponse.h index 3713a54..2706f0b 100644 --- a/include/spore/types/NodeResponse.h +++ b/include/spore/types/NodeResponse.h @@ -60,8 +60,7 @@ public: * @param endpoint The EndpointInfo to add */ void addEndpoint(const EndpointInfo& endpoint) { - EndpointInfoSerializable serializable(endpoint); - addItem(serializable); + addItem(EndpointInfoSerializable(endpoint)); } /** diff --git a/include/spore/types/TaskInfoSerializable.h b/include/spore/types/TaskInfoSerializable.h index a2de430..9d7a9f1 100644 --- a/include/spore/types/TaskInfoSerializable.h +++ b/include/spore/types/TaskInfoSerializable.h @@ -12,13 +12,16 @@ namespace types { */ class TaskInfoSerializable : public util::JsonSerializable { private: - const String& taskName; + String taskName; const JsonObject& taskData; public: TaskInfoSerializable(const String& name, const JsonObject& data) : taskName(name), taskData(data) {} + TaskInfoSerializable(const std::string& name, const JsonObject& data) + : taskName(name.c_str()), taskData(data) {} + /** * Serialize task info to JsonObject */ diff --git a/include/spore/types/TaskResponse.h b/include/spore/types/TaskResponse.h index 9e904b2..5244373 100644 --- a/include/spore/types/TaskResponse.h +++ b/include/spore/types/TaskResponse.h @@ -30,7 +30,10 @@ public: */ void addTask(const String& taskName, const JsonObject& taskData) { TaskInfoSerializable serializable(taskName, taskData); - JsonArray tasksArr = doc["tasks"].to(); + if (!doc["tasks"].is()) { + doc["tasks"] = JsonArray(); + } + JsonArray tasksArr = doc["tasks"].as(); JsonObject taskObj = tasksArr.add(); serializable.toJson(taskObj); } @@ -41,8 +44,11 @@ public: * @param taskData Task data as JsonObject */ void addTask(const std::string& taskName, const JsonObject& taskData) { - TaskInfoSerializable serializable(String(taskName.c_str()), taskData); - JsonArray tasksArr = doc["tasks"].to(); + TaskInfoSerializable serializable(taskName, taskData); + if (!doc["tasks"].is()) { + doc["tasks"] = JsonArray(); + } + JsonArray tasksArr = doc["tasks"].as(); JsonObject taskObj = tasksArr.add(); serializable.toJson(taskObj); } @@ -93,6 +99,9 @@ public: * @param taskStatuses Vector of pairs of task name to task data */ void buildCompleteResponse(const std::vector>& taskStatuses) { + // Clear the document first since getAllTaskStatuses creates a root array + doc.clear(); + // Set summary size_t totalTasks = taskStatuses.size(); size_t activeTasks = 0; @@ -103,9 +112,23 @@ public: } setSummary(totalTasks, activeTasks); - // Add all tasks + // Add all tasks - extract data before clearing to avoid invalid references + JsonArray tasksArr = doc["tasks"].to(); for (const auto& pair : taskStatuses) { - addTask(pair.first, pair.second); + // Extract data from JsonObject before it becomes invalid + String taskName = pair.first.c_str(); + unsigned long interval = pair.second["interval"]; + bool enabled = pair.second["enabled"]; + bool running = pair.second["running"]; + bool autoStart = pair.second["autoStart"]; + + // Create new JsonObject in our document + JsonObject taskObj = tasksArr.add(); + taskObj["name"] = taskName; + taskObj["interval"] = interval; + taskObj["enabled"] = enabled; + taskObj["running"] = running; + taskObj["autoStart"] = autoStart; } // Set system info diff --git a/src/spore/services/TaskService.cpp b/src/spore/services/TaskService.cpp index b67d01d..2700499 100644 --- a/src/spore/services/TaskService.cpp +++ b/src/spore/services/TaskService.cpp @@ -36,10 +36,13 @@ void TaskService::registerEndpoints(ApiServer& api) { } void TaskService::handleStatusRequest(AsyncWebServerRequest* request) { + TaskStatusResponse response; + + // Get task statuses using a separate document to avoid reference issues JsonDocument scratch; auto taskStatuses = taskManager.getAllTaskStatuses(scratch); - TaskStatusResponse response; + // Build the complete response with the task data response.buildCompleteResponse(taskStatuses); request->send(200, "application/json", response.toJsonString()); }