whippet/store/storage.go
2025-05-15 15:48:24 +02:00

121 lines
2.6 KiB
Go

package store
import (
"database/sql"
"git.espin.casa/albert/whippet/proto"
_ "github.com/mattn/go-sqlite3"
)
type Storage struct {
db *sql.DB
}
func NewStorage(path string) *Storage {
db, err := sql.Open("sqlite3", path)
if err != nil {
return nil
}
s := &Storage{db: db}
if err := s.initSchema(); err != nil {
return nil
}
return s
}
func (s *Storage) initSchema() error {
schema := `
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
topic TEXT,
msg_id TEXT,
payload BLOB,
timestamp INTEGER
);`
_, err := s.db.Exec(schema)
return err
}
// Save guarda un mensaje en la base de datos
func (s *Storage) Save(topic string, msg *proto.DataMessage) error {
_, err := s.db.Exec(`
INSERT INTO messages (topic, msg_id, payload, timestamp)
VALUES (?, ?, ?, ?)`,
topic, string(msg.Id()), msg.PayloadBytes(), msg.Timestamp(),
)
return err
}
// LoadSince carga mensajes desde un timestamp específico
func (s *Storage) LoadSince(topic string, sinceTimestamp uint64, max int) ([]*proto.DataMessage, error) {
rows, err := s.db.Query(`
SELECT msg_id, payload, timestamp
FROM messages
WHERE topic = ? AND timestamp > ?
ORDER BY timestamp ASC
LIMIT ?`,
topic, sinceTimestamp, max,
)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*proto.DataMessage
for rows.Next() {
var id string
var payload []byte
var timestamp uint64
err := rows.Scan(&id, &payload, &timestamp)
if err != nil {
return nil, err
}
// Reensamblar el FlatBuffer
msg := proto.GetRootAsDataMessage(payload, 0)
// Cuidado: esto apunta a datos en `payload` directamente
// Alternativa: clonar si necesitas preservar después
result = append(result, msg)
}
return result, nil
}
// LoadAll carga todos los mensajes de un tema específico
func (s *Storage) LoadAll(topic string) ([]*proto.DataMessage, error) {
rows, err := s.db.Query(`
SELECT msg_id, payload, timestamp
FROM messages
WHERE topic = ?
ORDER BY timestamp ASC
`, topic)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*proto.DataMessage
for rows.Next() {
var id string
var payload []byte
var timestamp uint64
err := rows.Scan(&id, &payload, &timestamp)
if err != nil {
return nil, err
}
// Reensamblar el FlatBuffer
msg := proto.GetRootAsDataMessage(payload, 0)
// Cuidado: esto apunta a datos en `payload` directamente
// Alternativa: clonar si necesitas preservar después
result = append(result, msg)
}
return result, nil
}
// LoadAllTopics carga todos los temas disponibles
func (s *Storage) Close() error {
return s.db.Close()
}