Files
kandev/apps/backend/internal/analytics/repository/sqlite/repository.go
T
2026-02-16 12:00:54 +00:00

97 lines
2.9 KiB
Go

// Package sqlite provides SQLite-based analytics repository implementations.
package sqlite
import "database/sql"
// Repository provides SQLite-based analytics operations.
type Repository struct {
db *sql.DB
}
// NewWithDB creates a new analytics repository with an existing database connection.
// It automatically creates performance indexes for stats queries.
func NewWithDB(dbConn *sql.DB) (*Repository, error) {
repo := &Repository{db: dbConn}
if err := repo.ensureStatsIndexes(); err != nil {
return nil, err
}
return repo, nil
}
// Close is a no-op because this repository does not own the database connection.
func (r *Repository) Close() error {
return nil
}
// ensureStatsIndexes creates performance indexes for stats queries if they don't already exist.
// Query planner statistics are maintained by PRAGMA optimize on connection close (see persistence/provider.go).
func (r *Repository) ensureStatsIndexes() error {
indexes := []string{
// Tasks table indexes
`CREATE INDEX IF NOT EXISTS idx_tasks_workspace_created
ON tasks(workspace_id, created_at)`,
`CREATE INDEX IF NOT EXISTS idx_tasks_workflow_state
ON tasks(workflow_step_id, state)`,
`CREATE INDEX IF NOT EXISTS idx_tasks_updated
ON tasks(workspace_id, updated_at)`,
// Task sessions indexes
`CREATE INDEX IF NOT EXISTS idx_sessions_task_started
ON task_sessions(task_id, started_at)`,
`CREATE INDEX IF NOT EXISTS idx_sessions_agent_started
ON task_sessions(agent_profile_id, started_at)`,
`CREATE INDEX IF NOT EXISTS idx_sessions_repo
ON task_sessions(repository_id)`,
// Task session turns indexes
`CREATE INDEX IF NOT EXISTS idx_turns_session_times
ON task_session_turns(task_session_id, started_at, completed_at)`,
`CREATE INDEX IF NOT EXISTS idx_turns_task
ON task_session_turns(task_id)`,
// Task session messages indexes
`CREATE INDEX IF NOT EXISTS idx_messages_session_created
ON task_session_messages(task_session_id, created_at)`,
`CREATE INDEX IF NOT EXISTS idx_messages_author_type
ON task_session_messages(task_session_id, author_type, type)`,
`CREATE INDEX IF NOT EXISTS idx_messages_turn
ON task_session_messages(turn_id)`,
// Task session commits indexes
`CREATE INDEX IF NOT EXISTS idx_commits_session_time
ON task_session_commits(session_id, committed_at)`,
// Task repositories indexes
`CREATE INDEX IF NOT EXISTS idx_task_repos_task
ON task_repositories(task_id, repository_id)`,
`CREATE INDEX IF NOT EXISTS idx_task_repos_repo
ON task_repositories(repository_id, task_id)`,
// Repositories indexes (with soft delete filter)
`CREATE INDEX IF NOT EXISTS idx_repos_workspace
ON repositories(workspace_id)
WHERE deleted_at IS NULL`,
// Workflow steps indexes
`CREATE INDEX IF NOT EXISTS idx_workflow_steps_type
ON workflow_steps(id, step_type)`,
}
for _, idx := range indexes {
if _, err := r.db.Exec(idx); err != nil {
return err
}
}
return nil
}