# app/tasks/background_tasks.py """Summary description .... This module provides classes and functions for: - .... - .... - .... """ import logging from datetime import datetime from app.core.database import SessionLocal from models.database.marketplace import MarketplaceImportJob from utils.csv_processor import CSVProcessor logger = logging.getLogger(__name__) async def process_marketplace_import( job_id: int, url: str, marketplace: str, shop_name: str, batch_size: int = 1000 ): """Background task to process marketplace CSV import.""" db = SessionLocal() csv_processor = CSVProcessor() job = None # Initialize job variable try: # Update job status job = ( db.query(MarketplaceImportJob) .filter(MarketplaceImportJob.id == job_id) .first() ) if not job: logger.error(f"Import job {job_id} not found") return job.status = "processing" job.started_at = datetime.utcnow() db.commit() logger.info(f"Processing import: Job {job_id}, Marketplace: {marketplace}") # Process CSV result = await csv_processor.process_marketplace_csv_from_url( url, marketplace, shop_name, batch_size, db ) # Update job with results job.status = "completed" job.completed_at = datetime.utcnow() job.imported_count = result["imported"] job.updated_count = result["updated"] job.error_count = result.get("errors", 0) job.total_processed = result["total_processed"] if result.get("errors", 0) > 0: job.status = "completed_with_errors" job.error_message = f"{result['errors']} rows had errors" db.commit() logger.info(f"Import job {job_id} completed successfully") except Exception as e: logger.error(f"Import job {job_id} failed: {e}") if job is not None: # Only update if job was found try: job.status = "failed" job.error_message = str(e) job.completed_at = datetime.utcnow() db.commit() except Exception as commit_error: logger.error(f"Failed to update job status: {commit_error}") db.rollback() # Don't re-raise the exception - background tasks should handle errors internally # and update the job status accordingly. Only log the error. pass finally: # Close the database session only if it's not a mock # In tests, we use the same session so we shouldn't close it if hasattr(db, "close") and callable(getattr(db, "close")): try: db.close() except Exception as close_error: logger.error(f"Error closing database session: {close_error}")