Files
docker-agent/pkg/memory/database/sqlite/sqlite.go
T
Trung Nguyen 77ae3630cf Fix SQLite database locking issues with concurrent access
Configure SQLite connections with proper concurrency handling to prevent
"database is locked" errors when multiple operations access the database
simultaneously.

Changes:
- Add busy_timeout (5s) to wait for locks instead of failing immediately
- Enable WAL mode for better concurrent read/write performance
- Configure connection pool to serialize writes (SQLite best practice)

Fixes session store and memory database SQLite implementations.
2025-10-17 11:20:05 +02:00

72 lines
1.9 KiB
Go

package sqlite
import (
"context"
"database/sql"
_ "modernc.org/sqlite"
"github.com/docker/cagent/pkg/memory/database"
)
type MemoryDatabase struct {
db *sql.DB
}
func NewMemoryDatabase(path string) (database.Database, error) {
// Add query parameters for better concurrency handling
// _busy_timeout: Wait up to 5 seconds if database is locked
// _journal_mode=WAL: Enable Write-Ahead Logging for better concurrent access
db, err := sql.Open("sqlite", path+"?_busy_timeout=5000&_journal_mode=WAL")
if err != nil {
return nil, err
}
// Configure connection pool to serialize writes (SQLite limitation)
// This prevents "database is locked" errors from concurrent writes
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
db.SetConnMaxLifetime(0)
_, err = db.ExecContext(context.Background(), "CREATE TABLE IF NOT EXISTS memories (id TEXT PRIMARY KEY, created_at TEXT, memory TEXT)")
if err != nil {
return nil, err
}
return &MemoryDatabase{db: db}, nil
}
func (m *MemoryDatabase) AddMemory(ctx context.Context, memory database.UserMemory) error {
if memory.ID == "" {
return database.ErrEmptyID
}
_, err := m.db.ExecContext(ctx, "INSERT INTO memories (id, created_at, memory) VALUES (?, ?, ?)",
memory.ID, memory.CreatedAt, memory.Memory)
return err
}
func (m *MemoryDatabase) GetMemories(ctx context.Context) ([]database.UserMemory, error) {
rows, err := m.db.QueryContext(ctx, "SELECT id, created_at, memory FROM memories")
if err != nil {
return nil, err
}
defer rows.Close()
var memories []database.UserMemory
for rows.Next() {
var memory database.UserMemory
err := rows.Scan(&memory.ID, &memory.CreatedAt, &memory.Memory)
if err != nil {
return nil, err
}
memories = append(memories, memory)
}
return memories, nil
}
func (m *MemoryDatabase) DeleteMemory(ctx context.Context, memory database.UserMemory) error {
_, err := m.db.ExecContext(ctx, "DELETE FROM memories WHERE id = ?", memory.ID)
return err
}