#include #include #include namespace dmf_engine { NodeId Graph::add_node(const std::string& type, const nlohmann::json& config) { std::string id; if (config.contains("id") && config["id"].is_string()) { id = config["id"].get(); } else { id = type + "_" + std::to_string(next_node_num_++); } GraphNode node; node.id = id; node.type = type; node.config = config; node.state = NodeState::Stopped; nodes_[id] = std::move(node); spdlog::info("Graph: added node '{}' type='{}'", id, type); return id; } bool Graph::remove_node(const NodeId& node_id) { auto it = nodes_.find(node_id); if (it == nodes_.end()) { spdlog::warn("Graph: node '{}' not found", node_id); return false; } std::vector edges_to_remove; for (const auto& [eid, edge] : edges_) { if (edge.from_node == node_id || edge.to_node == node_id) { edges_to_remove.push_back(eid); } } for (const auto& eid : edges_to_remove) { edges_.erase(eid); spdlog::info("Graph: removed edge '{}' (connected to removed node '{}')", eid, node_id); } nodes_.erase(it); spdlog::info("Graph: removed node '{}'", node_id); return true; } const GraphNode* Graph::get_node(const NodeId& node_id) const { auto it = nodes_.find(node_id); return it != nodes_.end() ? &it->second : nullptr; } std::vector Graph::get_nodes() const { std::vector result; for (const auto& [_, node] : nodes_) { result.push_back(node); } return result; } EdgeId Graph::add_edge(const NodeId& from_node, const PortId& from_port, const NodeId& to_node, const PortId& to_port, const FlowId& flow_id, const nlohmann::json& flow_def) { auto id = from_node + ":" + from_port + "->" + to_node + ":" + to_port; GraphEdge edge; edge.id = id; edge.from_node = from_node; edge.from_port = from_port; edge.to_node = to_node; edge.to_port = to_port; edge.flow_id = flow_id; edge.flow_def = flow_def; edges_[id] = std::move(edge); spdlog::info("Graph: added edge '{}' flow_id={}", id, flow_id); return id; } bool Graph::remove_edge(const EdgeId& edge_id) { auto it = edges_.find(edge_id); if (it == edges_.end()) { spdlog::warn("Graph: edge '{}' not found", edge_id); return false; } edges_.erase(it); spdlog::info("Graph: removed edge '{}'", edge_id); return true; } std::vector Graph::get_edges() const { std::vector result; for (const auto& [_, edge] : edges_) { result.push_back(edge); } return result; } std::vector Graph::get_edges_for_node(const NodeId& node_id) const { std::vector result; for (const auto& [_, edge] : edges_) { if (edge.from_node == node_id || edge.to_node == node_id) { result.push_back(edge); } } return result; } nlohmann::json Graph::serialize() const { auto j = nlohmann::json::object(); auto nodes_arr = nlohmann::json::array(); for (const auto& [id, node] : nodes_) { nodes_arr.push_back({ {"id", node.id}, {"type", node.type}, {"config", node.config}, {"state", static_cast(node.state)}, {"control_port", node.control_port}, {"pid", node.pid}, }); } j["nodes"] = nodes_arr; auto edges_arr = nlohmann::json::array(); for (const auto& [id, edge] : edges_) { edges_arr.push_back({ {"id", edge.id}, {"from_node", edge.from_node}, {"from_port", edge.from_port}, {"to_node", edge.to_node}, {"to_port", edge.to_port}, {"flow_id", edge.flow_id}, }); } j["edges"] = edges_arr; return j; } } // namespace dmf_engine