- Create 4 infrastructure services (LLM, Storage, Platform, Voice) - Refactor all modules to pure business logic (no HTTP/SQLite/Win32) - Add bundled SQLite amalgamation for MinGW compatibility - Make OpenSSL optional in CMake configuration - Fix topic naming convention (colon format) - Add succession documentation Build status: CMake config needs SQLite C language fix (documented) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
92 lines
2.6 KiB
C++
92 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include "IService.hpp"
|
|
|
|
#include <grove/IIO.h>
|
|
#include <grove/JsonDataNode.h>
|
|
#include <spdlog/spdlog.h>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <queue>
|
|
#include <mutex>
|
|
|
|
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<spdlog::logger> 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
|