Files
service-finder/backend/app/workers/service/service_robot_3_enricher.py
2026-03-13 10:22:41 +00:00

115 lines
5.3 KiB
Python
Executable File

import asyncio
import logging
import json
from sqlalchemy import select, text, update, func
from app.database import AsyncSessionLocal # JAVÍTVA
from app.models.service import ServiceProfile, ExpertiseTag, ServiceExpertise, ServiceStaging
# Logolás MB 2.0 szabvány
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s')
logger = logging.getLogger("Service-Robot-3-Enricher")
class ServiceEnricher:
"""
Service Robot 3: Professional Classifier (Atomi Zárolással)
"""
@staticmethod
async def match_expertise_to_service(db, service_profile_id: int, scraped_text: str):
""" Kulcsszó-alapú elemző motor az ExpertiseTag tábla alapján. """
if not scraped_text: return
tags_query = await db.execute(select(ExpertiseTag).where(ExpertiseTag.is_official == True))
all_tags = tags_query.scalars().all()
found_any = False
for tag in all_tags:
match_count = 0
for kw in (tag.search_keywords or []):
if kw.lower() in scraped_text.lower():
match_count += 1
if match_count > 0:
existing_check = await db.execute(
select(ServiceExpertise).where(
ServiceExpertise.service_id == service_profile_id,
ServiceExpertise.expertise_id == tag.id
)
)
if not existing_check.scalar():
new_link = ServiceExpertise(
service_id=service_profile_id,
expertise_id=tag.id,
confidence_level=min(match_count, 2)
)
db.add(new_link)
found_any = True
logger.info(f"{tag.key} szakma azonosítva a szerviznél.")
if found_any:
await db.commit()
@classmethod
async def run_worker(cls):
logger.info("🧠 Service Enricher ONLINE - Szakmai elemzés indítása (Atomi Zárolás)")
while True:
try:
async with AsyncSessionLocal() as db:
# 1. Zárolunk egy "enrich_ready" szervizt a Staging táblából
query = text("""
UPDATE marketplace.service_staging
SET status = 'enriching'
WHERE id = (
SELECT id FROM marketplace.service_staging
WHERE status = 'enrich_ready'
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING id, name, city, full_address, fingerprint, raw_data;
""")
result = await db.execute(query)
task = result.fetchone()
await db.commit()
if task:
s_id, name, city, address, fprint, raw_data = task
web_context = raw_data.get('web_context', '') if isinstance(raw_data, dict) else ''
async with AsyncSessionLocal() as process_db:
try:
# 2. Áttesszük a végleges ServiceProfile táblába (mert már van elég adatunk a webről)
profile_stmt = text("""
INSERT INTO marketplace.service_profiles
(fingerprint, status, trust_score, location, is_verified, bio)
VALUES (:fp, 'active', 40, ST_SetSRID(ST_MakePoint(19.04, 47.49), 4326), false, :bio)
ON CONFLICT (fingerprint) DO UPDATE SET bio = EXCLUDED.bio
RETURNING id;
""") # Megjegyzés: A GPS koordinátát (19.04, 47.49) majd a Validator (Robot-4) pontosítja!
p_result = await process_db.execute(profile_stmt, {"fp": fprint, "bio": name + " - " + city})
profile_id = p_result.scalar()
await process_db.commit()
# 3. Futtatjuk a kulcsszó-elemzést
await cls.match_expertise_to_service(process_db, profile_id, web_context)
# 4. Lezárjuk a Staging feladatot
await process_db.execute(text("UPDATE marketplace.service_staging SET status = 'processed' WHERE id = :id"), {"id": s_id})
await process_db.commit()
except Exception as e:
await process_db.rollback()
logger.error(f"Hiba a dúsítás során ({s_id}): {e}")
await process_db.execute(text("UPDATE marketplace.service_staging SET status = 'error' WHERE id = :id"), {"id": s_id})
await process_db.commit()
else:
await asyncio.sleep(15)
except Exception as e:
logger.error(f"💀 Kritikus hiba a főciklusban: {e}")
await asyncio.sleep(10)
if __name__ == "__main__":
asyncio.run(ServiceEnricher.run_worker())