Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

63 lines
2.1 KiB
Go

package jobs
import (
"context"
"fmt"
"log"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
// Queue enqueues processing and feed-sync work for the worker poller (SKIP LOCKED claim).
// ASSUMPTION: full River client + river migrations are deferred; Postgres pending
// jobs + FOR UPDATE SKIP LOCKED is the production queue for P0-4 MVP.
type Queue struct {
Pool *pgxpool.Pool
}
func NewQueue(pool *pgxpool.Pool) *Queue {
return &Queue{Pool: pool}
}
// EnqueueProcessingJob ensures the job is pending and wakes listeners via NOTIFY.
func (q *Queue) EnqueueProcessingJob(ctx context.Context, jobID uuid.UUID) error {
if q == nil || q.Pool == nil {
return fmt.Errorf("jobs queue not configured")
}
ct, err := q.Pool.Exec(ctx, `
UPDATE processing_jobs
SET status = 'pending', updated_at = now(),
error = CASE WHEN status = 'failed' THEN NULL ELSE error END
WHERE id = $1 AND status IN ('pending', 'failed')`, jobID)
if err != nil {
return err
}
if ct.RowsAffected() == 0 {
// Already running/completed/cancelled — still notify in case worker is idle.
var status string
_ = q.Pool.QueryRow(ctx, `SELECT status FROM processing_jobs WHERE id = $1`, jobID).Scan(&status)
log.Printf("jobs: enqueue %s status=%s (no status change)", jobID, status)
}
_, _ = q.Pool.Exec(ctx, `SELECT pg_notify('processing_jobs', $1)`, jobID.String())
return nil
}
// EnqueueFeedSyncJob wakes listeners for an already-pending feed_sync_jobs row.
// Row creation + mapping gates live in feeds.EnqueueSync; this mirrors processing NOTIFY.
func (q *Queue) EnqueueFeedSyncJob(ctx context.Context, jobID uuid.UUID) error {
if q == nil || q.Pool == nil {
return fmt.Errorf("jobs queue not configured")
}
var status string
err := q.Pool.QueryRow(ctx, `SELECT status FROM feed_sync_jobs WHERE id = $1`, jobID).Scan(&status)
if err != nil {
return err
}
if status != "pending" && status != "running" {
log.Printf("jobs: feed sync enqueue %s status=%s (notify only)", jobID, status)
}
_, _ = q.Pool.Exec(ctx, `SELECT pg_notify('feed_sync_jobs', $1)`, jobID.String())
return nil
}