# retoor <retoor@molodetz.nl>
from __future__ import annotations
import json
import logging
from typing import Any
from devplacepy.services.jobs.isslop import store
from devplacepy.services.jobs.isslop.events import (
KIND_DOM,
KIND_DONE,
KIND_ERROR,
KIND_FILE,
KIND_IMAGE,
KIND_REPORT,
WorkerEvent,
)
logger = logging.getLogger(__name__)
SCORE_FIELDS: tuple[str, ...] = (
"grade",
"slop_score",
"origin_score",
"human_percent",
"ai_percent",
"category",
"confidence",
"content_hash",
"source_kind",
"files_total",
"files_analyzed",
"detected_builder",
)
ERROR_MESSAGE_CAP = 2000
TELLS_CAP = 4000
DESCRIPTION_CAP = 2000
class EventPersister:
def __init__(self, analysis_uid: str) -> None:
self._analysis_uid = analysis_uid
self._seq = 0
@property
def seq(self) -> int:
return self._seq
@property
def analysis_uid(self) -> str:
return self._analysis_uid
def apply(self, event: WorkerEvent) -> dict[str, Any]:
self._seq += 1
payload_for_storage = dict(event.data)
if event.kind == KIND_REPORT:
markdown = str(payload_for_storage.pop("markdown", ""))
model_used = str(payload_for_storage.get("model_used", "unknown"))
store.save_report(self._analysis_uid, markdown, model_used)
store.insert_event(
self._analysis_uid,
self._seq,
event.kind,
event.message,
json.dumps(payload_for_storage, ensure_ascii=False),
)
if event.kind == KIND_FILE:
store.insert_file_result(
self._analysis_uid,
{
"path": str(event.data.get("path", "")),
"language": str(event.data.get("language", "unknown")),
"lines": int(event.data.get("sloc", 0)),
"origin_score": float(event.data.get("origin_score", 0.0)),
"quality_deficit_score": float(event.data.get("quality_deficit", 0.0)),
"category": str(event.data.get("category", "uncertain")),
"signals": json.dumps(event.data.get("signals", []), ensure_ascii=False)[: store.SIGNALS_CAP],
"source": str(event.data.get("source") or ""),
},
)
if event.kind == KIND_IMAGE:
store.insert_image_result(
self._analysis_uid,
{
"path": str(event.data.get("path", "")),
"ai_probability": float(event.data.get("ai_probability", 0.0)),
"grade": str(event.data.get("grade", "n/a")),
"verdict": str(event.data.get("verdict", "uncertain")),
"image_kind": str(event.data.get("image_kind", "image")),
"tells": json.dumps(event.data.get("tells", []), ensure_ascii=False)[:TELLS_CAP],
"description": str(event.data.get("description", ""))[:DESCRIPTION_CAP],
"thumb": str(event.data.get("thumb") or ""),
},
)
if event.kind == KIND_DOM:
store.insert_dom_result(
self._analysis_uid,
{
"url": str(event.data.get("url", "")),
"detected_builder": str(event.data.get("detected_builder") or ""),
"signal_count": int(event.data.get("signal_count", 0)),
"screenshot": str(event.data.get("screenshot") or ""),
"signals": json.dumps(event.data.get("signals", []), ensure_ascii=False)[: store.SIGNALS_CAP],
},
)
if event.kind == KIND_DONE:
updates: dict[str, Any] = {
key: event.data.get(key) for key in SCORE_FIELDS if key in event.data
}
updates["quality_deficit_score"] = event.data.get("quality_deficit")
updates["dom_slop_score"] = event.data.get("dom_slop_score")
updates["status"] = "completed"
updates["finished_at"] = store.utc_now()
store.update_analysis(self._analysis_uid, **updates)
if event.kind == KIND_ERROR:
store.update_analysis(
self._analysis_uid,
status="failed",
finished_at=store.utc_now(),
error_message_text=event.message[:ERROR_MESSAGE_CAP],
)
return {
"analysis": self._analysis_uid,
"seq": self._seq,
"kind": event.kind,
"message": event.message,
"data": payload_for_storage if event.kind != KIND_FILE else event.data,
"created_at": store.utc_now(),
}