fix(audit-g1): six one-liner drift fixes from 2026-06-02 audit
- BACKFILL_TIMEOUT_SECONDS 1800→1170: keep the subprocess timeout 30s below Celery's hard time_limit=1200 so SIGKILL doesn't beat TimeoutExpired (matched the tick 870s/900s rationale). Backfill runs that hit the cap let the next tick continue via the archive. - recover_interrupted_tasks orphan UPDATE now stamps finished_at; without it cleanup_old_tasks' WHERE finished_at<cutoff never reaped orphan-swept rows. recover_stalled_task_runs also now sets duration_ms (matches celery_signals.finalize's millisecond math). - ExtensionService.quick_add_source arms NEW_SOURCE_BACKFILL_RUNS=3 on Source creation, mirroring SourceService.create. Without it, Firefox quick-add on a creator with >20 unsynced posts walked the full feed until subprocess timeout. Renamed the constant from _NEW_SOURCE_BACKFILL_RUNS so it can be imported cross-module. - gallery_dl.verify() accepts TIER_LIMITED as auth-success alongside NO_NEW_CONTENT — the download path (line 712) already does, and TIER_LIMITED proves auth reached the post and was told it was tier-gated. Verify endpoint previously showed red on this and prompted operators to rotate working cookies. - prune_unused_tags now runs a single DELETE with the NOT-IN predicate find_unused_tags uses, instead of SELECT-ids → DELETE-WHERE-IN. Removes the psycopg 65535-param cliff that would have surfaced on a tag explosion (>65k unused tags). - credentials.upload() reflects the returned record into the store cache (`.set(platform, rec)`) instead of evicting it; previously the card briefly rendered "no credential" between upload and loadAll().
This commit is contained in:
@@ -7,7 +7,7 @@ from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
from sqlalchemy import and_, delete, or_, select, update
|
||||
from sqlalchemy import Integer, and_, cast, delete, func, or_, select, update
|
||||
|
||||
from ..celery_app import celery
|
||||
from ..models import (
|
||||
@@ -182,6 +182,11 @@ def recover_interrupted_tasks() -> int:
|
||||
.where(ImportTask.created_at < orphan_cutoff)
|
||||
.values(
|
||||
status="failed",
|
||||
# Without finished_at, cleanup_old_tasks (`WHERE
|
||||
# finished_at < cutoff`) never reaps these rows —
|
||||
# orphan-swept rows would become permanent table
|
||||
# tenants. Audit 2026-06-02.
|
||||
finished_at=now,
|
||||
error=(
|
||||
"orphan pending/queued swept by recover_interrupted_tasks "
|
||||
"(scanner likely crashed mid-enqueue); retry via "
|
||||
@@ -278,6 +283,14 @@ def recover_stalled_task_runs() -> int:
|
||||
f"no completion signal received within {minutes} min"
|
||||
),
|
||||
finished_at=now,
|
||||
# Matches celery_signals.finalize's
|
||||
# int((now - started_at).total_seconds() * 1000)
|
||||
# — sweep-closed rows now carry duration like
|
||||
# normally-finalized rows. Audit 2026-06-02.
|
||||
duration_ms=cast(
|
||||
func.extract("epoch", now - TaskRun.started_at) * 1000,
|
||||
Integer,
|
||||
),
|
||||
)
|
||||
)
|
||||
for w in extra_where:
|
||||
|
||||
Reference in New Issue
Block a user