| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- #include <spdlog/spdlog.h>
- #include <atomic>
- #include <csignal>
- #include <cstdlib>
- #include <string>
- #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<bool> 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;
- }
|