diff --git a/Builder/src/main.cpp b/Builder/src/main.cpp index 8c83e4c..298ca15 100644 --- a/Builder/src/main.cpp +++ b/Builder/src/main.cpp @@ -217,6 +217,7 @@ int main(int argc, char *argv[]) { // Attempt to close connection try { + Logger::debug("Attempting normal close"); client_stream.close(websocket::close_code::normal); } catch (...) { Logger::error("Failed to cleanly close the WebSocket"); diff --git a/BuilderQueue/include/BuilderQueue.h b/BuilderQueue/include/BuilderQueue.h index beaac37..82be1a7 100644 --- a/BuilderQueue/include/BuilderQueue.h +++ b/BuilderQueue/include/BuilderQueue.h @@ -34,7 +34,6 @@ class BuilderQueue { BuilderQueue &operator=(BuilderQueue &&) = delete; - // Add the specified handler to the queue // When a builder is ready the handler will be called and passed the builder template @@ -61,6 +60,8 @@ class BuilderQueue { create_reserve_builders(); } + // Return a json formatted string representing the status of the queue + std::string status_json(); private: asio::io_context &io_context; diff --git a/BuilderQueue/include/Connection.h b/BuilderQueue/include/Connection.h index d055dc7..b94bac4 100644 --- a/BuilderQueue/include/Connection.h +++ b/BuilderQueue/include/Connection.h @@ -35,6 +35,8 @@ class Connection : public std::enable_shared_from_this { void request_builder(); + void request_queue_stats(); + void builder_ready(BuilderData builder); void wait_for_close(); diff --git a/BuilderQueue/src/BuilderQueue.cpp b/BuilderQueue/src/BuilderQueue.cpp index f0986c3..6a358fa 100644 --- a/BuilderQueue/src/BuilderQueue.cpp +++ b/BuilderQueue/src/BuilderQueue.cpp @@ -1,5 +1,37 @@ #include "BuilderQueue.h" #include "OpenStack.h" +#include +#include + +std::string BuilderQueue::status_json() { + pt::ptree status_tree; + + // Insert active builders + pt::ptree active_tree; + for (auto builder : active_builders) { + pt::ptree builder_node; + builder_node.add("id", builder.id); + builder_node.add("host", builder.host); + builder_node.add("port", builder.port); + active_tree.push_back(std::make_pair("", builder_node)); + } + status_tree.add_child("active", active_tree); + + // Insert reserve builders + pt::ptree reserve_tree; + for (auto builder : reserve_builders) { + pt::ptree builder_node; + builder_node.add("id", builder.id); + builder_node.add("host", builder.host); + builder_node.add("port", builder.port); + reserve_tree.push_back(std::make_pair("", builder_node)); + } + status_tree.add_child("reserve", reserve_tree); + + std::stringstream tree_stream; + boost::property_tree::json_parser::write_json(tree_stream, status_tree); + return tree_stream.str(); +} void BuilderQueue::return_builder(BuilderData builder) { Logger::info("Attempting to destroy builder: " + builder.id); diff --git a/BuilderQueue/src/Connection.cpp b/BuilderQueue/src/Connection.cpp index bed4e83..b491d76 100644 --- a/BuilderQueue/src/Connection.cpp +++ b/BuilderQueue/src/Connection.cpp @@ -33,12 +33,12 @@ void Connection::builder_ready(BuilderData builder) { std::string request_string(serialized_builder); Logger::info("Writing builder: " + builder.id); - stream.async_write(asio::buffer(request_string), [this, self, builder](beast::error_code error, std::size_t bytes) { + stream.async_write(asio::buffer(request_string), [this, self, request_string](beast::error_code error, std::size_t bytes) { boost::ignore_unused(bytes); if (!error) { wait_for_close(); } else { - Logger::error("Error writing builder: " + builder.id); + Logger::error("Error writing builder: " + request_string); } }); } @@ -55,6 +55,22 @@ void Connection::request_builder() { }); } +void Connection::request_queue_stats() { + // Persist this connection + auto self(shared_from_this()); + + Logger::info("Request for queue stats made"); + auto status = queue.status_json(); + Logger::info("Writing queue stats"); + + stream.async_write(asio::buffer(status), [this, self, status](beast::error_code error, std::size_t bytes) { + boost::ignore_unused(bytes); + if (error) { + Logger::error("Wrote job stats"); + } + }); +} + void Connection::read_request_string() { // Persist this connection auto self(shared_from_this()); @@ -67,6 +83,8 @@ void Connection::read_request_string() { buffer.consume(buffer.size()); if (request == "checkout_builder_request") { request_builder(); + } else if(request == "queue_status_request") { + request_queue_stats(); } else { Logger::error("Bad initial request string: " + request); } diff --git a/Client/src/main.cpp b/Client/src/main.cpp index 5735cc0..e6afb7e 100644 --- a/Client/src/main.cpp +++ b/Client/src/main.cpp @@ -278,7 +278,7 @@ int main(int argc, char *argv[]) { std::cout.setf(std::ios::unitbuf); // Catch ctrl-c and restore cursor - std::signal(SIGINT, [](int signal){ std::cout << "Aborting\n"; show_cursor(); std::abort();}); + std::signal(SIGINT, [](int signal){ throw std::runtime_error("User requested interrupt"); }); hide_cursor(); @@ -339,10 +339,17 @@ int main(int argc, char *argv[]) { // Attempt to disconnect from builder and queue try { + Logger::debug("Attempting normal close of builder"); builder_stream.close(websocket::close_code::normal); + } catch (...) { + Logger::debug("Failed to cleanly close the WebSocket to builder"); + } + + try { + Logger::debug("Attempting normal close of queue"); queue_stream.close(websocket::close_code::normal); } catch (...) { - Logger::debug("Failed to cleanly close the WebSockets"); + Logger::debug("Failed to cleanly close the WebSocket to queue"); } show_cursor();