from datetime import datetime, timezone from packages.adapters.sqlalchemy_impl import SQLAlchemyAssetRepository, SQLAlchemyIngestJobRepository from packages.domain import Asset, IngestJobStatus from worker_app.celery_app import celery_app from worker_app.db import SessionLocal @celery_app.task(name="worker.ingest_asset") def ingest_asset(job_id: str) -> dict: """ Ingest asset task. Steps: 1. Fetch IngestJob from repository 2. Extract metadata from storage_key (placeholder: mock metadata) 3. Create Asset entity 4. Update IngestJob status to COMPLETED 5. Return result """ db = SessionLocal() job_repo = SQLAlchemyIngestJobRepository(db) asset_repo = SQLAlchemyAssetRepository(db) job = job_repo.get(job_id) if job is None: return {"status": "failed", "error": "job not found"} try: # Update job status to PROCESSING job.status = IngestJobStatus.PROCESSING job.updated_at = datetime.now(timezone.utc) job_repo.update(job) # Mock metadata extraction (in real implementation: use ffprobe, Pillow, etc.) mime_type = "video/mp4" if job.storage_key.endswith(".mp4") else "image/jpeg" metadata = { "duration": 10.5, "width": 1920, "height": 1080, "size_bytes": 1024000, } # Extract filename from storage_key filename = job.storage_key.split("/")[-1] # Create Asset asset = Asset.create( workspace_id=job.workspace_id, project_id=job.project_id, library_id=job.library_id, name=filename, storage_key=job.storage_key, mime_type=mime_type, metadata=metadata, ) asset_repo.create(asset) # Update job status to COMPLETED job.status = IngestJobStatus.COMPLETED job.result_asset_id = asset.id job.updated_at = datetime.now(timezone.utc) job_repo.update(job) return { "status": "completed", "job_id": job.id, "asset_id": asset.id, } except Exception as e: # Update job status to FAILED job.status = IngestJobStatus.FAILED job.error_message = str(e) job.updated_at = datetime.now(timezone.utc) job_repo.update(job) return { "status": "failed", "job_id": job.id, "error": str(e), } finally: db.close()