package asynqqueue import ( "context" "time" "github.com/libnovel/backend/internal/domain" "github.com/libnovel/backend/internal/taskqueue" ) // Consumer wraps the PocketBase-backed Consumer for result write-back only. // // When using Asynq, the runner no longer polls for scrape/audio work — Asynq // delivers those tasks via the ServeMux handlers. However translation tasks // live in PocketBase (not Redis), so ClaimNextTranslationTask and HeartbeatTask // still delegate to the underlying PocketBase consumer. // // ClaimNextAudioTask, ClaimNextScrapeTask are no-ops here because Asynq owns // those responsibilities. type Consumer struct { pb taskqueue.Consumer // underlying PocketBase consumer (for write-back) } // NewConsumer wraps an existing PocketBase Consumer. func NewConsumer(pb taskqueue.Consumer) *Consumer { return &Consumer{pb: pb} } // ── Write-back (delegated to PocketBase) ────────────────────────────────────── func (c *Consumer) FinishScrapeTask(ctx context.Context, id string, result domain.ScrapeResult) error { return c.pb.FinishScrapeTask(ctx, id, result) } func (c *Consumer) FinishAudioTask(ctx context.Context, id string, result domain.AudioResult) error { return c.pb.FinishAudioTask(ctx, id, result) } func (c *Consumer) FinishTranslationTask(ctx context.Context, id string, result domain.TranslationResult) error { return c.pb.FinishTranslationTask(ctx, id, result) } func (c *Consumer) FinishImportTask(ctx context.Context, id string, result domain.ImportResult) error { return c.pb.FinishImportTask(ctx, id, result) } func (c *Consumer) FailTask(ctx context.Context, id, errMsg string) error { return c.pb.FailTask(ctx, id, errMsg) } // ── No-ops (Asynq owns claiming / heartbeating / reaping) ─────────────────── func (c *Consumer) ClaimNextScrapeTask(_ context.Context, _ string) (domain.ScrapeTask, bool, error) { return domain.ScrapeTask{}, false, nil } func (c *Consumer) ClaimNextAudioTask(_ context.Context, _ string) (domain.AudioTask, bool, error) { return domain.AudioTask{}, false, nil } // ClaimNextTranslationTask delegates to PocketBase because translation tasks // are stored in PocketBase (not Redis/Asynq) and must still be polled directly. func (c *Consumer) ClaimNextTranslationTask(ctx context.Context, workerID string) (domain.TranslationTask, bool, error) { return c.pb.ClaimNextTranslationTask(ctx, workerID) } // ClaimNextImportTask delegates to PocketBase because import tasks // are stored in PocketBase (not Redis/Asynq) and must still be polled directly. func (c *Consumer) ClaimNextImportTask(ctx context.Context, workerID string) (domain.ImportTask, bool, error) { return c.pb.ClaimNextImportTask(ctx, workerID) } func (c *Consumer) HeartbeatTask(ctx context.Context, id string) error { return c.pb.HeartbeatTask(ctx, id) } // ReapStaleTasks delegates to PocketBase so stale translation tasks are reset // to pending and can be reclaimed. func (c *Consumer) ReapStaleTasks(ctx context.Context, staleAfter time.Duration) (int, error) { return c.pb.ReapStaleTasks(ctx, staleAfter) }