"""Job functions executed by the ARQ worker.""" from __future__ import annotations from datetime import datetime from sqlalchemy import select from app.database import AsyncSessionLocal, init_db from app.models.auction import DomainAuction from app.services.auction_scraper import auction_scraper from app.services.pounce_score import calculate_pounce_score_v2 from app.services.tld_scraper.aggregator import tld_aggregator async def scrape_auctions(ctx) -> dict: # arq passes ctx """Scrape auctions from all platforms and store results.""" await init_db() async with AsyncSessionLocal() as db: result = await auction_scraper.scrape_all_platforms(db) await db.commit() return {"status": "ok", "result": result, "timestamp": datetime.utcnow().isoformat()} async def scrape_tld_prices(ctx) -> dict: """Scrape TLD prices from all sources and store results.""" await init_db() async with AsyncSessionLocal() as db: result = await tld_aggregator.run_scrape(db) await db.commit() return { "status": "ok", "tlds_scraped": result.tlds_scraped, "prices_saved": result.prices_saved, "sources_succeeded": result.sources_succeeded, "sources_attempted": result.sources_attempted, "timestamp": datetime.utcnow().isoformat(), } async def backfill_auction_scores(ctx, *, limit: int = 5000) -> dict: """ Backfill DomainAuction.pounce_score for legacy rows. Safe to run multiple times; only fills NULL scores. """ await init_db() updated = 0 async with AsyncSessionLocal() as db: rows = ( await db.execute( select(DomainAuction) .where(DomainAuction.pounce_score == None) # noqa: E711 .limit(limit) ) ).scalars().all() for auction in rows: auction.pounce_score = calculate_pounce_score_v2( auction.domain, auction.tld, num_bids=auction.num_bids or 0, age_years=auction.age_years or 0, is_pounce=False, ) updated += 1 await db.commit() return {"status": "ok", "updated": updated, "timestamp": datetime.utcnow().isoformat()}