From 0a810c14f7ddbb124a0179f6e26c90b2513f87d5 Mon Sep 17 00:00:00 2001 From: DmsAnhr Date: Mon, 22 Dec 2025 15:18:14 +0700 Subject: [PATCH] adding ws for listen update --- api/routers/ws/manager.py | 23 +++++++++++++++++++++++ api/routers/ws/upload_progress_ws.py | 25 +++++++++++++++++++++++++ core/config.py | 15 ++++++++++++++- services/upload_file/upload_ws.py | 27 +++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 api/routers/ws/manager.py create mode 100644 api/routers/ws/upload_progress_ws.py create mode 100644 services/upload_file/upload_ws.py diff --git a/api/routers/ws/manager.py b/api/routers/ws/manager.py new file mode 100644 index 0000000..5833059 --- /dev/null +++ b/api/routers/ws/manager.py @@ -0,0 +1,23 @@ +from typing import Dict, List +from fastapi import WebSocket + +class JobWSManager: + def __init__(self): + self.connections: Dict[str, List[WebSocket]] = {} + + async def connect(self, job_id: str, ws: WebSocket): + await ws.accept() + self.connections.setdefault(job_id, []).append(ws) + + def disconnect(self, job_id: str, ws: WebSocket): + if job_id in self.connections: + self.connections[job_id].remove(ws) + if not self.connections[job_id]: + del self.connections[job_id] + + async def send(self, job_id: str, data: dict): + for ws in self.connections.get(job_id, []): + await ws.send_json(data) + + +manager = JobWSManager() diff --git a/api/routers/ws/upload_progress_ws.py b/api/routers/ws/upload_progress_ws.py new file mode 100644 index 0000000..746472d --- /dev/null +++ b/api/routers/ws/upload_progress_ws.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter, WebSocket, WebSocketDisconnect +from services.upload_file.upload_ws import job_state +from api.routers.ws.manager import manager + +router = APIRouter() + +@router.websocket("/ws/test") +async def ws_test(ws: WebSocket): + await ws.accept() + await ws.send_text("OK") + + +@router.websocket("/ws/job/{job_id}") +async def ws_job(job_id: str, ws: WebSocket): + await manager.connect(job_id, ws) + + # kirim progress terakhir (jika reconnect) + if job_id in job_state: + await ws.send_json(job_state[job_id]) + + try: + while True: + await ws.receive_text() # keep alive + except WebSocketDisconnect: + manager.disconnect(job_id, ws) diff --git a/core/config.py b/core/config.py index 9880cce..fe2e1db 100644 --- a/core/config.py +++ b/core/config.py @@ -7,8 +7,21 @@ load_dotenv() API_VERSION = "2.1.3" POSTGIS_URL = os.getenv("POSTGIS_URL") -GEOSERVER_URL = os.getenv("GEOSERVER_PATH") POSTGIS_SYNC_URL = os.getenv("SYNC_URL") + +QGIS_URL = os.getenv("QGIS_API_URL") + +GEN_AI_URL = os.getenv("GEN_AI_URL") + +GEOSERVER_URL = os.getenv("GEOSERVER_PATH") +GEOSERVER_USER = os.getenv("GEOSERVER_UNAME") +GEOSERVER_PASS = os.getenv("GEOSERVER_PASS") +GEOSERVER_WORKSPACE = os.getenv("GEOSERVER_WORKSPACE") + +GEONETWORK_URL=os.getenv("GEONETWORK_URL") +GEONETWORK_USER=os.getenv("GEONETWORK_USER") +GEONETWORK_PASS=os.getenv("GEONETWORK_PASS") + UPLOAD_FOLDER = Path(os.getenv("UPLOAD_FOLDER", "./uploads")) MAX_FILE_MB = int(os.getenv("MAX_FILE_MB", 30)) diff --git a/services/upload_file/upload_ws.py b/services/upload_file/upload_ws.py new file mode 100644 index 0000000..4c3727e --- /dev/null +++ b/services/upload_file/upload_ws.py @@ -0,0 +1,27 @@ +# app/jobs/progress.py +from typing import Dict +from api.routers.ws.manager import manager + +# state job (in-memory dulu) +job_state: Dict[str, dict] = {} + + +async def report_progress( + job_id: str, + step: str, + progress: int, + message: str +): + """ + Fungsi tunggal untuk update & broadcast progress job + """ + + job_state[job_id] = { + "job_id": job_id, + "step": step, + "progress": progress, + "message": message, + } + + # push ke websocket + await manager.send(job_id, job_state[job_id])