Changeset 0.32.0 (#206)

This commit is contained in:
2026-03-19 18:50:27 +00:00
parent 6668e546fe
commit b1266b0d7c
283 changed files with 2187 additions and 1055 deletions

View File

@@ -2,11 +2,12 @@ package sqlite
import (
"context"
"database/sql"
"encoding/json"
"time"
"git.gobha.me/xcaliber/chat-switchboard/models"
"git.gobha.me/xcaliber/chat-switchboard/store"
"chat-switchboard/models"
"chat-switchboard/store"
)
type TaskStore struct{}
@@ -159,8 +160,20 @@ func (s *TaskStore) ListAll(ctx context.Context) ([]models.Task, error) {
return s.list(ctx, `ORDER BY created_at DESC`)
}
func (s *TaskStore) ListDue(ctx context.Context, limit int) ([]models.Task, error) {
return s.list(ctx, `WHERE is_active = 1 AND next_run_at <= datetime('now') ORDER BY next_run_at ASC LIMIT ?`, limit)
func (s *TaskStore) ClaimDueTask(ctx context.Context) (*models.Task, error) {
// SQLite: single-process, no contention. Select the oldest due task,
// then atomically clear next_run_at to mark it claimed.
t := &models.Task{}
row := DB.QueryRowContext(ctx,
`SELECT `+taskColumns+` FROM tasks
WHERE is_active = 1 AND next_run_at <= datetime('now')
ORDER BY next_run_at ASC LIMIT 1`)
if err := scanTask(row, t); err != nil {
return nil, err
}
_, _ = DB.ExecContext(ctx,
`UPDATE tasks SET next_run_at = NULL WHERE id = ?`, t.ID)
return t, nil
}
// ── Scheduler bookkeeping ──────────────────────
@@ -194,6 +207,34 @@ func (s *TaskStore) CreateRun(ctx context.Context, r *models.TaskRun) error {
return err
}
func (s *TaskStore) CreateRunExclusive(ctx context.Context, taskID string) (*models.TaskRun, error) {
// SQLite: check-then-insert. Single-process, no race.
var count int
err := DB.QueryRowContext(ctx, `
SELECT COUNT(*) FROM task_runs
WHERE task_id = ? AND status IN ('running', 'queued')`, taskID).Scan(&count)
if err != nil {
return nil, err
}
if count > 0 {
return nil, sql.ErrNoRows
}
r := &models.TaskRun{
ID: store.NewID(),
TaskID: taskID,
Status: "running",
StartedAt: time.Now().UTC(),
}
_, err = DB.ExecContext(ctx, `
INSERT INTO task_runs (id, task_id, status, started_at)
VALUES (?, ?, 'running', ?)`,
r.ID, taskID, r.StartedAt.UTC().Format("2006-01-02 15:04:05"))
if err != nil {
return nil, err
}
return r, nil
}
func (s *TaskStore) UpdateRun(ctx context.Context, id, status string, tokensUsed, toolCalls, wallClock int, errMsg string) error {
_, err := DB.ExecContext(ctx, `
UPDATE task_runs SET status = ?, tokens_used = ?, tool_calls = ?,