main.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include <spdlog/spdlog.h>
  2. #include <atomic>
  3. #include <csignal>
  4. #include <cstdlib>
  5. #include <string>
  6. #include "smartbotic/common.hpp"
  7. #include "smartbotic/database/config.hpp"
  8. #include "smartbotic/database/grpc/server.hpp"
  9. namespace {
  10. // Global server pointer for signal handling
  11. smartbotic::database::grpc::GrpcServer* g_server = nullptr;
  12. // Atomic flag for shutdown tracking
  13. std::atomic<bool> g_shutdown_requested{false};
  14. void SignalHandler(int signal) {
  15. if (g_shutdown_requested.exchange(true)) {
  16. // Second signal - force exit
  17. spdlog::warn("Received second signal {}, forcing immediate exit", signal);
  18. std::_Exit(1);
  19. }
  20. const char* signal_name = (signal == SIGINT) ? "SIGINT" : "SIGTERM";
  21. spdlog::info("Received {} ({}), initiating graceful shutdown...", signal_name, signal);
  22. if (g_server != nullptr) {
  23. g_server->Stop();
  24. }
  25. }
  26. auto SetLogLevel(smartbotic::database::LogLevel level) {
  27. switch (level) {
  28. case smartbotic::database::LogLevel::kTrace:
  29. spdlog::set_level(spdlog::level::trace);
  30. break;
  31. case smartbotic::database::LogLevel::kDebug:
  32. spdlog::set_level(spdlog::level::debug);
  33. break;
  34. case smartbotic::database::LogLevel::kInfo:
  35. spdlog::set_level(spdlog::level::info);
  36. break;
  37. case smartbotic::database::LogLevel::kWarn:
  38. spdlog::set_level(spdlog::level::warn);
  39. break;
  40. case smartbotic::database::LogLevel::kError:
  41. spdlog::set_level(spdlog::level::err);
  42. break;
  43. case smartbotic::database::LogLevel::kCritical:
  44. spdlog::set_level(spdlog::level::critical);
  45. break;
  46. case smartbotic::database::LogLevel::kOff:
  47. spdlog::set_level(spdlog::level::off);
  48. break;
  49. }
  50. }
  51. } // namespace
  52. int main(int argc, char* argv[]) {
  53. // Initialize common logging first (with default settings)
  54. smartbotic::common::Initialize("smartbotic-db");
  55. spdlog::info("SmartBotic Database Service starting...");
  56. // Load configuration from file, environment, and command line
  57. auto config = smartbotic::database::ConfigLoader::Load(argc, argv);
  58. // Apply configured log level
  59. SetLogLevel(config.log_level);
  60. // Print configuration
  61. smartbotic::database::ConfigLoader::PrintConfig(config);
  62. // Convert DatabaseConfig to ServerConfig for the gRPC server
  63. smartbotic::database::ServerConfig server_config;
  64. server_config.address = config.address;
  65. server_config.port = config.port;
  66. server_config.data_dir = config.data_dir;
  67. // Create and start the server
  68. smartbotic::database::grpc::GrpcServer server(server_config);
  69. g_server = &server;
  70. // Set up signal handlers for graceful shutdown (SIGTERM/SIGINT)
  71. struct sigaction sa{};
  72. sa.sa_handler = SignalHandler;
  73. sigemptyset(&sa.sa_mask);
  74. sa.sa_flags = 0;
  75. if (sigaction(SIGINT, &sa, nullptr) == -1) {
  76. spdlog::error("Failed to set SIGINT handler");
  77. smartbotic::common::Shutdown();
  78. return 1;
  79. }
  80. if (sigaction(SIGTERM, &sa, nullptr) == -1) {
  81. spdlog::error("Failed to set SIGTERM handler");
  82. smartbotic::common::Shutdown();
  83. return 1;
  84. }
  85. spdlog::info("Signal handlers registered for SIGINT and SIGTERM");
  86. if (!server.Start()) {
  87. spdlog::error("Failed to start server");
  88. smartbotic::common::Shutdown();
  89. return 1;
  90. }
  91. // Wait for server to stop (either by signal or error)
  92. server.Wait();
  93. spdlog::info("SmartBotic Database Service shutdown complete");
  94. g_server = nullptr;
  95. smartbotic::common::Shutdown();
  96. return 0;
  97. }