cert-study-app / cert_study_app /services /airflow_service.py
github-actions
Sync from GitHub d2682fe6d3fcffe93aa302c286320962009f6436
9381502
Raw
History Blame Contribute Delete
4.04 kB
from __future__ import annotations
import os
from datetime import datetime
import requests
class AirflowTriggerError(RuntimeError):
pass
class AirflowService:
def __init__(
self,
base_url: str | None = None,
username: str | None = None,
password: str | None = None,
):
self.base_url = (base_url or os.getenv("AIRFLOW_API_BASE_URL") or "http://localhost:8080").rstrip("/")
self.username = username or os.getenv("AIRFLOW_API_USERNAME") or "admin"
self.password = password or os.getenv("AIRFLOW_API_PASSWORD") or "admin"
def trigger_pdf_ingestion(
self,
job_id: int,
pdf_path: str,
source_name: str,
use_llm: bool,
llm_model: str,
ollama_base_url: str,
) -> dict:
dag_id = "cert_study_pdf_ingestion"
url = f"{self.base_url}/api/v1/dags/{dag_id}/dagRuns"
run_id = f"cert_study_job_{job_id}_{datetime.utcnow().strftime('%Y%m%dT%H%M%S')}"
payload = {
"dag_run_id": run_id,
"conf": {
"job_id": job_id,
"pdf_path": pdf_path,
"source_name": source_name,
"use_llm": use_llm,
"llm_model": llm_model,
"ollama_base_url": ollama_base_url,
},
}
try:
response = requests.post(
url,
json=payload,
auth=(self.username, self.password),
timeout=10,
)
except requests.RequestException as exc:
raise AirflowTriggerError(f"Airflow API 연결 실패: {exc}") from exc
if response.status_code >= 400:
raise AirflowTriggerError(
f"Airflow DAG trigger 실패 ({response.status_code}): {response.text[:500]}"
)
return response.json()
def trigger_visual_analysis(
self,
source_name: str | None = None,
limit: int = 20,
model: str | None = None,
) -> dict:
dag_id = "cert_study_visual_analysis"
url = f"{self.base_url}/api/v1/dags/{dag_id}/dagRuns"
run_id = f"cert_study_visual_{datetime.utcnow().strftime('%Y%m%dT%H%M%S')}"
payload = {
"dag_run_id": run_id,
"conf": {
"source_name": source_name or "",
"limit": int(limit),
"model": model or os.getenv("OLLAMA_VISUAL_MODEL", "qwen3-vl:8b-instruct-q4_K_M"),
},
}
try:
response = requests.post(
url,
json=payload,
auth=(self.username, self.password),
timeout=10,
)
except requests.RequestException as exc:
raise AirflowTriggerError(f"Airflow API 연결 실패: {exc}") from exc
if response.status_code >= 400:
raise AirflowTriggerError(
f"Airflow 이미지 분석 DAG trigger 실패 ({response.status_code}): {response.text[:500]}"
)
return response.json()
def list_dag_runs(self, dag_id: str, limit: int = 5) -> list[dict]:
url = f"{self.base_url}/api/v1/dags/{dag_id}/dagRuns"
try:
response = requests.get(
url,
params={"limit": max(int(limit), 50)},
auth=(self.username, self.password),
timeout=8,
)
except requests.RequestException as exc:
raise AirflowTriggerError(f"Airflow API 연결 실패: {exc}") from exc
if response.status_code >= 400:
raise AirflowTriggerError(
f"Airflow DAG 상태 조회 실패 ({response.status_code}): {response.text[:500]}"
)
runs = response.json().get("dag_runs", [])
return sorted(
runs,
key=lambda run: run.get("logical_date") or run.get("execution_date") or run.get("start_date") or "",
reverse=True,
)[: int(limit)]