Removes the OpenCLIP-on-ONNX classifier and everything that fed or
consumed it:
- backend: app/services/vision/, app/tasks/vision.py,
app/services/feature_flags.py, app/routers/features.py — all
deleted; admin AI/feature-flag endpoints and the worker-vision
bootstrap call gone. Photo.needs_review and its index dropped.
- frontend: AI Settings tab, useFeaturesQuery hook, FeatureFlag
types, "Needs Review" sidebar entry + filter, needs_review filter
URL param all gone.
- infra: worker-vision compose service + models_data volume deleted;
worker-light command no longer runs bootstrap_models; the db
image switches from pgvector/pgvector:pg16 to postgres:16; backend
Dockerfile drops the dedicated torch RUN layer; requirements.txt
drops torch/torchvision/open-clip-torch/onnxruntime.
Alembic 0019_drop_ai_remnants:
- drops photos.needs_review + ix_photos_needs_review
- DROP EXTENSION IF EXISTS vector (must run before the image swap;
the new postgres:16 doesn't ship pgvector)
New scripts/full_refresh.py: one-shot DB ↔ filesystem reconciliation.
Runs cleanup_data_integrity, scans every active SourceRoot inline
(no celery dependency so the worker can be stopped), hard-prunes
photo + folder rows for files that are gone, removes orphan
/data/thumbs/{user}/{photo}/ directories. New helper
prune_orphan_thumbnails in cleanup.py.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
"""
|
|
Celery configuration and app initialization
|
|
"""
|
|
import logging
|
|
|
|
from celery import Celery
|
|
from app.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
celery_app = Celery(
|
|
'mulita',
|
|
broker=settings.celery_broker_url,
|
|
backend=settings.celery_result_backend,
|
|
include=[
|
|
'app.tasks.scan',
|
|
'app.tasks.thumbs',
|
|
'app.tasks.video',
|
|
'app.services.metadata',
|
|
]
|
|
)
|
|
|
|
celery_app.conf.update(
|
|
task_serializer='json',
|
|
accept_content=['json'],
|
|
result_serializer='json',
|
|
timezone='UTC',
|
|
enable_utc=True,
|
|
task_acks_late=True,
|
|
task_reject_on_worker_lost=True,
|
|
task_soft_time_limit=300,
|
|
task_time_limit=600,
|
|
task_routes={
|
|
'generate_thumbnails': {'queue': 'high'},
|
|
'regenerate_all_thumbnails': {'queue': 'high'},
|
|
'backfill_phashes': {'queue': 'high'},
|
|
'regroup_duplicates': {'queue': 'high'},
|
|
'incremental_regroup_duplicates': {'queue': 'high'},
|
|
'scan_folder': {'queue': 'low'},
|
|
'scan_all_source_roots': {'queue': 'low'},
|
|
'backfill_gps': {'queue': 'low'},
|
|
# CPU-heavy but tolerant of the low-priority queue (doesn't block
|
|
# any user-facing flow).
|
|
'pretranscode_video': {'queue': 'low'},
|
|
# `watch_folders` is retired (file events come from NC webhooks)
|
|
# but the task definition still exists as a no-op shim for any
|
|
# in-flight apply_async. Route it to the default queue so the
|
|
# remaining worker actually drains it.
|
|
'watch_folders': {'queue': 'default'},
|
|
'discard_missing_photos_beat': {'queue': 'low'},
|
|
},
|
|
task_default_queue='default',
|
|
task_default_exchange='default',
|
|
task_default_exchange_type='direct',
|
|
task_default_routing_key='default',
|
|
broker_connection_retry_on_startup=True,
|
|
# Periodic catch-up so external file deletions in Nextcloud get
|
|
# reflected even when the real-time watcher missed the event
|
|
# (worker restart window, mount transient, etc).
|
|
beat_schedule={
|
|
'discard-missing-photos-every-30min': {
|
|
'task': 'discard_missing_photos_beat',
|
|
'schedule': 30 * 60,
|
|
},
|
|
},
|
|
)
|