diff --git a/backend/internal/asynqqueue/consumer.go b/backend/internal/asynqqueue/consumer.go index 09979fd..71d40b6 100644 --- a/backend/internal/asynqqueue/consumer.go +++ b/backend/internal/asynqqueue/consumer.go @@ -10,14 +10,13 @@ import ( // Consumer wraps the PocketBase-backed Consumer for result write-back only. // -// When using Asynq, the runner no longer polls for work — Asynq delivers -// tasks via the ServeMux handlers. The only Consumer operations the handlers -// need are: -// - FinishAudioTask / FinishScrapeTask — write result back to PocketBase -// - FailTask — mark PocketBase record as failed +// 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, HeartbeatTask, and ReapStaleTasks -// are all no-ops here because Asynq owns those responsibilities. +// ClaimNextAudioTask, ClaimNextScrapeTask are no-ops here because Asynq owns +// those responsibilities. type Consumer struct { pb taskqueue.Consumer // underlying PocketBase consumer (for write-back) } @@ -55,10 +54,18 @@ func (c *Consumer) ClaimNextAudioTask(_ context.Context, _ string) (domain.Audio return domain.AudioTask{}, false, nil } -func (c *Consumer) ClaimNextTranslationTask(_ context.Context, _ string) (domain.TranslationTask, bool, error) { - return domain.TranslationTask{}, 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) } -func (c *Consumer) HeartbeatTask(_ context.Context, _ string) error { return nil } +func (c *Consumer) HeartbeatTask(ctx context.Context, id string) error { + return c.pb.HeartbeatTask(ctx, id) +} -func (c *Consumer) ReapStaleTasks(_ context.Context, _ time.Duration) (int, error) { return 0, nil } +// 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) +} diff --git a/homelab/runner/docker-compose.yml b/homelab/runner/docker-compose.yml index 1bc381b..33a333e 100644 --- a/homelab/runner/docker-compose.yml +++ b/homelab/runner/docker-compose.yml @@ -28,20 +28,13 @@ services: volumes: - libretranslate_models:/home/libretranslate/.local/share/argos-translate - libretranslate_db:/app/db - healthcheck: - test: ["CMD", "python3", "-c", "import urllib.request,sys; urllib.request.urlopen('http://localhost:5000/languages'); sys.exit(0)"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 120s runner: image: kalekber/libnovel-runner:latest restart: unless-stopped stop_grace_period: 135s depends_on: - libretranslate: - condition: service_healthy + - libretranslate environment: # ── PocketBase ────────────────────────────────────────────────────────── POCKETBASE_URL: "https://pb.libnovel.cc"