#include #include #include #include #include #include "smartbotic/common.hpp" #include "smartbotic/database/config.hpp" #include "smartbotic/database/grpc/server.hpp" namespace { // Global server pointer for signal handling smartbotic::database::grpc::GrpcServer* g_server = nullptr; // Atomic flag for shutdown tracking std::atomic g_shutdown_requested{false}; void SignalHandler(int signal) { if (g_shutdown_requested.exchange(true)) { // Second signal - force exit spdlog::warn("Received second signal {}, forcing immediate exit", signal); std::_Exit(1); } const char* signal_name = (signal == SIGINT) ? "SIGINT" : "SIGTERM"; spdlog::info("Received {} ({}), initiating graceful shutdown...", signal_name, signal); if (g_server != nullptr) { g_server->Stop(); } } auto SetLogLevel(smartbotic::database::LogLevel level) { switch (level) { case smartbotic::database::LogLevel::kTrace: spdlog::set_level(spdlog::level::trace); break; case smartbotic::database::LogLevel::kDebug: spdlog::set_level(spdlog::level::debug); break; case smartbotic::database::LogLevel::kInfo: spdlog::set_level(spdlog::level::info); break; case smartbotic::database::LogLevel::kWarn: spdlog::set_level(spdlog::level::warn); break; case smartbotic::database::LogLevel::kError: spdlog::set_level(spdlog::level::err); break; case smartbotic::database::LogLevel::kCritical: spdlog::set_level(spdlog::level::critical); break; case smartbotic::database::LogLevel::kOff: spdlog::set_level(spdlog::level::off); break; } } } // namespace int main(int argc, char* argv[]) { // Initialize common logging first (with default settings) smartbotic::common::Initialize("smartbotic-db"); spdlog::info("SmartBotic Database Service starting..."); // Load configuration from file, environment, and command line auto config = smartbotic::database::ConfigLoader::Load(argc, argv); // Apply configured log level SetLogLevel(config.log_level); // Print configuration smartbotic::database::ConfigLoader::PrintConfig(config); // Convert DatabaseConfig to ServerConfig for the gRPC server smartbotic::database::ServerConfig server_config; server_config.address = config.address; server_config.port = config.port; server_config.data_dir = config.data_dir; // Create and start the server smartbotic::database::grpc::GrpcServer server(server_config); g_server = &server; // Set up signal handlers for graceful shutdown (SIGTERM/SIGINT) struct sigaction sa{}; sa.sa_handler = SignalHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGINT, &sa, nullptr) == -1) { spdlog::error("Failed to set SIGINT handler"); smartbotic::common::Shutdown(); return 1; } if (sigaction(SIGTERM, &sa, nullptr) == -1) { spdlog::error("Failed to set SIGTERM handler"); smartbotic::common::Shutdown(); return 1; } spdlog::info("Signal handlers registered for SIGINT and SIGTERM"); if (!server.Start()) { spdlog::error("Failed to start server"); smartbotic::common::Shutdown(); return 1; } // Wait for server to stop (either by signal or error) server.Wait(); spdlog::info("SmartBotic Database Service shutdown complete"); g_server = nullptr; smartbotic::common::Shutdown(); return 0; }