database_service.hpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #pragma once
  2. #include "document.hpp"
  3. #include "memory_store.hpp"
  4. #include "database_grpc_impl.hpp"
  5. #include "persistence/persistence_manager.hpp"
  6. #include "encryption/encryption_manager.hpp"
  7. #include "events/event_manager.hpp"
  8. #include "files/file_manager.hpp"
  9. #include "replication/replication_manager.hpp"
  10. #include "migrations/migration_runner.hpp"
  11. #include "views/view_manager.hpp"
  12. #include "config/collection_config_manager.hpp"
  13. #include <nlohmann/json.hpp>
  14. #include <atomic>
  15. #include <filesystem>
  16. #include <memory>
  17. #include <mutex>
  18. #include <string>
  19. #include <thread>
  20. namespace grpc {
  21. class Server;
  22. }
  23. namespace smartbotic::database {
  24. /**
  25. * Main storage service application.
  26. * Coordinates all components and manages the gRPC server.
  27. */
  28. class DatabaseService {
  29. public:
  30. struct Config {
  31. std::string nodeId = "storage-1";
  32. std::string bindAddress = "0.0.0.0";
  33. uint16_t rpcPort = 9004;
  34. // Bootstrap/service registration
  35. std::string webapiUrl;
  36. std::string serviceKey;
  37. uint32_t heartbeatIntervalSec = 30;
  38. std::filesystem::path dataDirectory;
  39. std::filesystem::path keyFilePath;
  40. // Memory eviction settings
  41. uint64_t maxMemoryMb = 800; // Max memory before eviction
  42. uint32_t evictionThresholdPercent = 80; // Start evicting at this %
  43. uint32_t evictionTargetPercent = 60; // Evict down to this %
  44. uint32_t evictionCheckIntervalMs = 5000; // How often to check
  45. // NEW v1.7.0 eviction tuning — mirrors MemoryStore::Config fields.
  46. // Plumbed here so the config loader can set them and setupComponents()
  47. // can copy them into the MemoryStore. Schema-only in T2; behavior lands
  48. // in T3/T4.
  49. uint32_t evictionChunkSize = 1000;
  50. uint32_t evictionChunkPauseMs = 50;
  51. uint32_t maxEvictionPassesPerTrigger = 20;
  52. uint32_t hotWriteFloorMs = 30000;
  53. uint32_t memorySoftPercent = 70;
  54. uint32_t memoryHardPercent = 85;
  55. uint32_t memoryEmergencyPercent = 95;
  56. // v1.7.0 T10 — eviction burst event threshold (docs per tick).
  57. uint32_t evictionBurstThreshold = 10000;
  58. // Persistence settings
  59. uint32_t walSyncIntervalMs = 100;
  60. uint32_t snapshotIntervalSec = 3600;
  61. bool compressionEnabled = true;
  62. // Full persistence manager config (recovery mode, etc.).
  63. // DatabaseService::setupComponents() overlays the simpler fields above
  64. // onto this struct before constructing PersistenceManager.
  65. PersistenceManager::Config persistenceConfig;
  66. // File storage settings
  67. uint64_t maxFileSizeMb = 500;
  68. std::vector<std::string> allowedFileTypes;
  69. uint32_t fileCleanupIntervalSec = 3600;
  70. // Encryption settings
  71. bool encryptionEnabled = true;
  72. bool autoGenerateKey = true;
  73. // Replication settings
  74. bool replicationEnabled = true;
  75. std::vector<std::string> peerAddresses;
  76. std::string conflictResolution = "last_writer_wins";
  77. // Migration settings
  78. struct MigrationsConfig {
  79. bool enabled = true;
  80. std::filesystem::path directory;
  81. bool autoApply = true;
  82. bool failOnError = true;
  83. } migrations;
  84. // gRPC server settings (v1.6.2 — concurrency cap + configurable sizes)
  85. struct GrpcConfig {
  86. uint32_t maxReceiveMessageSizeMb = 100;
  87. uint32_t maxSendMessageSizeMb = 100;
  88. uint32_t resourceQuotaMemoryMb = 256;
  89. uint32_t maxConcurrentSubscribeStreams = 50;
  90. uint32_t maxConcurrentFileStreams = 10;
  91. };
  92. GrpcConfig grpc;
  93. };
  94. explicit DatabaseService(Config config);
  95. ~DatabaseService();
  96. /**
  97. * Initialize the service.
  98. * Loads configuration, initializes components, and prepares for startup.
  99. */
  100. bool initialize();
  101. /**
  102. * Start the service.
  103. * Starts the gRPC server and all background threads.
  104. */
  105. void start();
  106. /**
  107. * Stop the service.
  108. * Gracefully shuts down all components.
  109. */
  110. void stop();
  111. /**
  112. * Wait for the service to stop.
  113. */
  114. void wait();
  115. /**
  116. * Check if the service is running.
  117. */
  118. [[nodiscard]] bool isRunning() const { return running_; }
  119. /**
  120. * Signal the service to stop (for signal handlers).
  121. */
  122. void signalStop();
  123. /**
  124. * Get service statistics.
  125. */
  126. [[nodiscard]] nlohmann::json getStats() const;
  127. /**
  128. * Access the view manager (for RPC handlers, migrations, etc.).
  129. */
  130. ViewManager& viewManager() { return *view_manager_; }
  131. /** Current read-only state (atomic, lock-free read). */
  132. bool isReadOnly() const { return read_only_.load(std::memory_order_acquire); }
  133. /** Human-readable reason the DB is read-only (empty when writable). */
  134. std::string readOnlyReason() const;
  135. /** Toggle read-only state. Called by SetReadOnly RPC and startup logic. */
  136. void setReadOnly(bool value, const std::string& reason);
  137. /** Recovery outcome from the last recover() call. Used by GetReadOnlyStatus RPC. */
  138. const RecoveryOutcome& recoveryOutcome() const { return recovery_outcome_; }
  139. /** Set the force-readwrite flag (from --force-readwrite CLI arg). */
  140. void setForceReadwrite(bool value) { force_readwrite_ = value; }
  141. /**
  142. * Load configuration from a JSON file.
  143. */
  144. static Config loadConfig(const std::filesystem::path& configPath);
  145. /**
  146. * Parse configuration from an already-loaded JSON object. Used by the
  147. * conf.d drop-in loader (see config/config_loader.hpp) after it has
  148. * merged /etc/smartbotic-database/config.json with every *.json in
  149. * /etc/smartbotic-database/conf.d/.
  150. */
  151. static Config parseConfig(const nlohmann::json& json);
  152. private:
  153. void setupComponents();
  154. void startGrpcServer();
  155. void stopGrpcServer();
  156. void applyReplicatedEntry(const databasepb::ReplicationEntry& entry);
  157. bool runMigrations();
  158. Config config_;
  159. std::atomic<bool> running_{false};
  160. std::atomic<bool> stopRequested_{false};
  161. // Components
  162. std::unique_ptr<MemoryStore> store_;
  163. std::unique_ptr<PersistenceManager> persistence_;
  164. std::unique_ptr<EncryptionManager> encryption_;
  165. std::unique_ptr<EventManager> events_;
  166. std::unique_ptr<FileManager> files_;
  167. std::unique_ptr<ReplicationManager> replication_;
  168. std::unique_ptr<ViewManager> view_manager_;
  169. std::unique_ptr<CollectionConfigManager> config_manager_;
  170. // gRPC
  171. std::unique_ptr<DatabaseGrpcImpl> storageImpl_;
  172. std::unique_ptr<DatabaseReplicationGrpcImpl> replicationImpl_;
  173. std::unique_ptr<grpc::Server> grpcServer_;
  174. std::thread serverThread_;
  175. // Migration runner
  176. std::unique_ptr<MigrationRunner> migrationRunner_;
  177. // Read-only runtime state (v1.6.1 — auto-readonly on non-trivial recovery)
  178. std::atomic<bool> read_only_{false};
  179. mutable std::mutex reason_mutex_;
  180. std::string read_only_reason_;
  181. RecoveryOutcome recovery_outcome_;
  182. bool force_readwrite_ = false;
  183. };
  184. } // namespace smartbotic::database