#pragma once #include "IService.hpp" #include #include #include #include #include #include #include struct sqlite3; struct sqlite3_stmt; namespace aissia { /** * @brief Storage Service - SQLite persistence * * Handles all database operations synchronously in main thread. * Uses prepared statements to prevent SQL injection. * * Subscribes to: * - "storage:save_session" : { taskName, durationMinutes, hyperfocus } * - "storage:save_app_usage" : { sessionId, appName, durationSeconds, productive } * - "storage:save_conversation" : { role, content, provider, model, tokens } * - "storage:update_metrics" : { focusMinutes, breaks, hyperfocusCount } * - "storage:query" : { sql, params[] } * * Publishes: * - "storage:ready" : Database initialized * - "storage:session_saved": { sessionId } * - "storage:error" : { message } */ class StorageService : public IService { public: StorageService(); ~StorageService() override; bool initialize(grove::IIO* io) override; void process() override; void shutdown() override; std::string getName() const override { return "StorageService"; } bool isHealthy() const override { return m_isConnected; } /// Open database with config bool openDatabase(const std::string& dbPath, const std::string& journalMode = "WAL", int busyTimeoutMs = 5000); /// Get last inserted session ID int getLastSessionId() const { return m_lastSessionId; } private: // Database sqlite3* m_db = nullptr; std::string m_dbPath; bool m_isConnected = false; int m_lastSessionId = 0; int m_totalQueries = 0; // Prepared statements sqlite3_stmt* m_stmtSaveSession = nullptr; sqlite3_stmt* m_stmtSaveAppUsage = nullptr; sqlite3_stmt* m_stmtSaveConversation = nullptr; sqlite3_stmt* m_stmtUpdateMetrics = nullptr; // Services grove::IIO* m_io = nullptr; std::shared_ptr m_logger; // Database operations bool initializeSchema(); bool prepareStatements(); void finalizeStatements(); // Message handlers void processMessages(); void handleSaveSession(const grove::IDataNode& data); void handleSaveAppUsage(const grove::IDataNode& data); void handleSaveConversation(const grove::IDataNode& data); void handleUpdateMetrics(const grove::IDataNode& data); // Helpers bool executeSQL(const std::string& sql); void publishError(const std::string& message); }; } // namespace aissia