# /opt/docker/dev/service_finder/backend/app/workers/discovery_engine.py import asyncio import httpx import logging from sqlalchemy import text, select from app.db.session import AsyncSessionLocal from app.models.asset import AssetCatalog from app.models.vehicle_definitions import VehicleModelDefinition logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s') logger = logging.getLogger("Discovery-Engine-v2.0") class DiscoveryEngine: """ A Robot-ökoszisztéma 'etetője'. Kombinálja a külső API felfedezést és a manuális alapozó adatokat. """ @staticmethod async def seed_manual_bootstrap(): """ 1. FÁZIS: Manuális alapozás (Bootstrap). Azonnali, biztos pontok a katalógusban a teszteléshez. """ initial_data = [ {"make": "AUDI", "model": "A4", "generation": "B8 (2008-2015)", "vehicle_class": "car"}, {"make": "BMW", "model": "3 SERIES", "generation": "F30 (2012-2019)", "vehicle_class": "car"}, {"make": "VOLKSWAGEN", "model": "PASSAT", "generation": "B8 (2014-)", "vehicle_class": "car"}, {"make": "SUZUKI", "model": "VITARA", "generation": "LY (2015-)", "vehicle_class": "car"} ] async with AsyncSessionLocal() as db: logger.info("🛠️ Manuális bootstrap indul...") for item in initial_data: stmt = select(AssetCatalog).where( AssetCatalog.make == item["make"], AssetCatalog.model == item["model"] ) exists = (await db.execute(stmt)).scalar_one_or_none() if not exists: db.add(AssetCatalog(**item)) await db.commit() logger.info("✅ Manuális bootstrap kész.") @staticmethod async def seed_from_rdw(): """ 2. FÁZIS: Külső prioritásos felfedezés (RDW API). Feltölti a várólistát a Hunter robot számára. """ RDW_URL = ( "https://opendata.rdw.nl/resource/m9d7-ebf2.json?" "$select=merk,voertuigsoort,count(*)%20as%20total" "&$group=merk,voertuigsoort" "&$having=total%20>=%2010" ) logger.info("📥 RDW adatgyűjtés indul a várólistához...") async with httpx.AsyncClient(timeout=60) as client: try: resp = await client.get(RDW_URL) if resp.status_code != 200: logger.error(f"❌ RDW API hiba: {resp.status_code}") return raw_data = resp.json() async with AsyncSessionLocal() as db: for entry in raw_data: make = str(entry.get("merk", "")).upper().strip() v_kind = entry.get("voertuigsoort", "") if not make: continue # Prioritás és Kategória meghatározása if "Personenauto" in v_kind: status, v_class = 'pending', 'car' elif "Motorfiets" in v_kind: status, v_class = 'queued_motor', 'motorcycle' else: status, v_class = 'queued_heavy', 'truck' # UPSERT (Ütközéskezelés) query = text(""" INSERT INTO data.catalog_discovery (make, model, vehicle_class, source, status) VALUES (:make, 'ALL_VARIANTS', :v_class, 'discovery_engine_v2', :status) ON CONFLICT (make, model, vehicle_class) DO NOTHING; """) await db.execute(query, {"make": make, "v_class": v_class, "status": status}) await db.commit() logger.info(f"✅ Discovery lista frissítve ({len(raw_data)} márka).") except Exception as e: logger.error(f"❌ Hiba az RDW szinkron alatt: {e}") @classmethod async def run_full_initialization(cls): """ A teljes rendszerindító folyamat. """ logger.info("🚀 Discovery Engine: TELJES INICIALIZÁLÁS") await cls.seed_manual_bootstrap() await cls.seed_from_rdw() logger.info("🏁 Minden alapozó folyamat lefutott.") if __name__ == "__main__": asyncio.run(DiscoveryEngine.run_full_initialization())