From b1812529a44b63007d60600180fdc20ae02e11ea Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 09:41:47 +0800 Subject: [PATCH 01/20] add healthcheck api endpoint --- backend/src/module/api/__init__.py | 2 ++ backend/src/module/api/health.py | 20 ++++++++++++++++++++ backend/src/module/network/request_url.py | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 backend/src/module/api/health.py diff --git a/backend/src/module/api/__init__.py b/backend/src/module/api/__init__.py index 38999e4d2..d0caa2457 100644 --- a/backend/src/module/api/__init__.py +++ b/backend/src/module/api/__init__.py @@ -7,6 +7,7 @@ from .program import router as program_router from .rss import router as rss_router from .search import router as search_router +from .health import router as health_router __all__ = "v1" @@ -19,3 +20,4 @@ v1.include_router(config_router) v1.include_router(rss_router) v1.include_router(search_router) +v1.include_router(health_router) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py new file mode 100644 index 000000000..4c521e74c --- /dev/null +++ b/backend/src/module/api/health.py @@ -0,0 +1,20 @@ +import logging +from backend.src.module.api import program +from fastapi import APIRouter +from fastapi import HTTPException + +router = APIRouter(prefix="/health", tags=["health"]) +logger = logging.getLogger(__name__) + +@router.get("/") +def health_check(): + is_healthy = program.check_downloader_status() + return {"status": "healthy" if is_healthy else "unhealthy"} + +@router.patch("/") +def update_health_status(status: str): + try: + logger.error(f"[Health] Health status changed to ",status) + return {"status": status} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 0b85e77e0..28699ea7b 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -14,6 +14,24 @@ class RequestURL: def __init__(self): self.header = {"user-agent": "Mozilla/5.0", "Accept": "application/xml"} self._socks5_proxy = False + + # Patch the health api endpoint if Network is unhealthy + def change_health_status_to_unhealthy(self): + url = "http://localhost:7892/health" + payload = { + "status": "unhealthy" + } + + try: + response = requests.patch(url, json=payload) + response.raise_for_status() + logger.debug( + f"[Health] Health status updated successfully." + ) + except requests.exceptions.RequestException as e: + logger.debug( + f"[Health] Failed to update health status:", str(e) + ) def get_url(self, url, retry=3): try_time = 0 @@ -35,6 +53,7 @@ def get_url(self, url, retry=3): logger.debug(e) break logger.error(f"[Network] Unable to connect to {url}, Please check your network settings") + self.change_health_status_to_unhealthy() return None def post_url(self, url: str, data: dict, retry=3): @@ -59,6 +78,7 @@ def post_url(self, url: str, data: dict, retry=3): break logger.error(f"[Network] Failed connecting to {url}") logger.warning("[Network] Please check DNS/Connection settings") + self.change_health_status_to_unhealthy() return None def check_url(self, url: str): From 05065dd0897d3bdb133ef21eaff3d78510d32f0d Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 10:00:10 +0800 Subject: [PATCH 02/20] fix module program import --- backend/src/module/api/health.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 4c521e74c..547674fa3 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -1,5 +1,5 @@ import logging -from backend.src.module.api import program +from module.api import program from fastapi import APIRouter from fastapi import HTTPException From c3d8229117e4659970c6553a9ed5d3b177335d2d Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 10:48:52 +0800 Subject: [PATCH 03/20] add healthcheck to dockerfile --- Dockerfile | 4 ++++ backend/src/module/api/health.py | 25 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index af83d1970..7f534ff1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ RUN set -ex && \ su-exec \ shadow \ tini \ + curl \ openssl \ tzdata && \ python3 -m pip install --no-cache-dir --upgrade pip && \ @@ -39,6 +40,9 @@ RUN set -ex && \ COPY --chmod=755 backend/src/. . COPY --chmod=755 entrypoint.sh /entrypoint.sh +# Add healthcheck endpoint +HEALTHCHECK --interval=5s --timeout=10s --retries=3 CMD curl --silent --fail http://localhost:7892/api/v1/health || exit 1 + ENTRYPOINT ["tini", "-g", "--", "/entrypoint.sh"] EXPOSE 7892 diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 547674fa3..130d833af 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -2,19 +2,36 @@ from module.api import program from fastapi import APIRouter from fastapi import HTTPException +from fastapi.responses import JSONResponse + +from module.models import APIResponse router = APIRouter(prefix="/health", tags=["health"]) logger = logging.getLogger(__name__) -@router.get("/") -def health_check(): +current_status = "healthy" + +@router.get("/", response_model=APIResponse) +async def health_check(): is_healthy = program.check_downloader_status() - return {"status": "healthy" if is_healthy else "unhealthy"} + status = "unhealthy" if not is_healthy else current_status + if status == "unhealthy": + return JSONResponse( + status_code=500, + content={"status": status}, + ) + else: + return JSONResponse( + status_code=200, + content={"status": status}, + ) @router.patch("/") -def update_health_status(status: str): +async def update_health_status(status: str): + global current_status try: logger.error(f"[Health] Health status changed to ",status) + current_status = status return {"status": status} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file From 15fcacd869ac2bcb7ad8465441359f8fa6182509 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 11:12:09 +0800 Subject: [PATCH 04/20] fix health check endpoints in checker and request_url --- backend/src/module/api/health.py | 3 +-- backend/src/module/checker/checker.py | 21 +++++++++++++++++++++ backend/src/module/network/request_url.py | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 130d833af..bf814fb7b 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -13,8 +13,7 @@ @router.get("/", response_model=APIResponse) async def health_check(): - is_healthy = program.check_downloader_status() - status = "unhealthy" if not is_healthy else current_status + status = current_status if status == "unhealthy": return JSONResponse( status_code=500, diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 4ff6b3a0f..5a1f8ac6b 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -50,6 +50,25 @@ def check_database() -> bool: @staticmethod def check_downloader() -> bool: + + # Patch the health api endpoint if Downloader connection was failed + def change_health_status_to_unhealthy(): + url = "http://localhost:7892/api/v1/health" + payload = { + "status": "unhealthy" + } + + try: + response = requests.patch(url, json=payload) + response.raise_for_status() + logger.debug( + f"[Health] Health status updated successfully." + ) + except requests.exceptions.RequestException as e: + logger.debug( + f"[Health] Failed to update health status:", str(e) + ) + try: url = ( f"http://{settings.downloader.host}" @@ -71,9 +90,11 @@ def check_downloader() -> bool: return False except requests.exceptions.ConnectionError: logger.error("[Checker] Downloader connect failed.") + change_health_status_to_unhealthy() return False except Exception as e: logger.error(f"[Checker] Downloader connect failed: {e}") + change_health_status_to_unhealthy() return False @staticmethod diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 28699ea7b..7695f06d7 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -15,9 +15,9 @@ def __init__(self): self.header = {"user-agent": "Mozilla/5.0", "Accept": "application/xml"} self._socks5_proxy = False - # Patch the health api endpoint if Network is unhealthy + # Patch the health api endpoint if Network connection was failed def change_health_status_to_unhealthy(self): - url = "http://localhost:7892/health" + url = "http://localhost:7892/api/v1/health" payload = { "status": "unhealthy" } From 9c927b26e7b1b20634b8cc4f6b664a667c41c1cc Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 11:26:48 +0800 Subject: [PATCH 05/20] fix patch healthcheck logic --- backend/src/module/api/health.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index bf814fb7b..2064566d1 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -29,8 +29,15 @@ async def health_check(): async def update_health_status(status: str): global current_status try: - logger.error(f"[Health] Health status changed to ",status) + logger.error(f"[Health] Health status changed from {current_status} to {status}") current_status = status - return {"status": status} + return JSONResponse( + status_code=200, + content={"msg_en": "Health status updated successfully.", "msg_zh": "健康状态更新成功。"}, + ) except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file + logger.error(f"[Health] Health status updated failed: {str(e)}") + return JSONResponse( + status_code=406, + content={"msg_en": "Health status updated failed.", "msg_zh": "健康状态更新失败。"}, + ) \ No newline at end of file From f9eb16a9b4d4b6b48f5ef464b9dcbb86ddbdb823 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 11:42:19 +0800 Subject: [PATCH 06/20] change the router path --- backend/src/module/api/health.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 2064566d1..f1669736a 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -11,7 +11,7 @@ current_status = "healthy" -@router.get("/", response_model=APIResponse) +@router.get("", response_model=APIResponse) async def health_check(): status = current_status if status == "unhealthy": @@ -25,7 +25,7 @@ async def health_check(): content={"status": status}, ) -@router.patch("/") +@router.patch("") async def update_health_status(status: str): global current_status try: From 8038d39af224af25ca666739edddca503da62d32 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 12:07:05 +0800 Subject: [PATCH 07/20] fix log output --- backend/src/module/api/health.py | 8 +++----- backend/src/module/checker/checker.py | 2 +- backend/src/module/network/request_url.py | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index f1669736a..db2e50ef1 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -1,7 +1,5 @@ import logging -from module.api import program from fastapi import APIRouter -from fastapi import HTTPException from fastapi.responses import JSONResponse from module.models import APIResponse @@ -25,18 +23,18 @@ async def health_check(): content={"status": status}, ) -@router.patch("") +@router.patch("", response_model=APIResponse) async def update_health_status(status: str): global current_status try: - logger.error(f"[Health] Health status changed from {current_status} to {status}") + logger.info(f"[Health] Health status changed from {current_status} to {status}") current_status = status return JSONResponse( status_code=200, content={"msg_en": "Health status updated successfully.", "msg_zh": "健康状态更新成功。"}, ) except Exception as e: - logger.error(f"[Health] Health status updated failed: {str(e)}") + logger.warning(f"[Health] Health status updated failed: {str(e)}") return JSONResponse( status_code=406, content={"msg_en": "Health status updated failed.", "msg_zh": "健康状态更新失败。"}, diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 5a1f8ac6b..00ee10fa0 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -66,7 +66,7 @@ def change_health_status_to_unhealthy(): ) except requests.exceptions.RequestException as e: logger.debug( - f"[Health] Failed to update health status:", str(e) + f"[Health] Failed to update health status: {str(e)}" ) try: diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 7695f06d7..e535550da 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -30,7 +30,7 @@ def change_health_status_to_unhealthy(self): ) except requests.exceptions.RequestException as e: logger.debug( - f"[Health] Failed to update health status:", str(e) + f"[Health] Failed to update health status: {str(e)}" ) def get_url(self, url, retry=3): From 4bd155ea4f3670e6ec584560496798596ea073d0 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 13:26:33 +0800 Subject: [PATCH 08/20] reuse core.status for programhealth check --- backend/src/module/api/health.py | 18 ++++++++++-------- backend/src/module/checker/checker.py | 23 +---------------------- backend/src/module/network/request_url.py | 4 ++-- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index db2e50ef1..7dd018012 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -1,34 +1,36 @@ import logging from fastapi import APIRouter from fastapi.responses import JSONResponse +from core.status import ProgramStatus from module.models import APIResponse router = APIRouter(prefix="/health", tags=["health"]) logger = logging.getLogger(__name__) -current_status = "healthy" +current_health_status = "healthy" @router.get("", response_model=APIResponse) async def health_check(): - status = current_status - if status == "unhealthy": + health_status = current_health_status + program_is_stopped = ProgramStatus.is_stopped + if health_status == "unhealthy" or program_is_stopped: return JSONResponse( status_code=500, - content={"status": status}, + content={"status": health_status}, ) else: return JSONResponse( status_code=200, - content={"status": status}, + content={"status": health_status}, ) @router.patch("", response_model=APIResponse) async def update_health_status(status: str): - global current_status + global current_health_status try: - logger.info(f"[Health] Health status changed from {current_status} to {status}") - current_status = status + logger.info(f"[Health] Health status changed from {current_health_status} to {status}") + current_health_status = status return JSONResponse( status_code=200, content={"msg_en": "Health status updated successfully.", "msg_zh": "健康状态更新成功。"}, diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 00ee10fa0..3d94504b9 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -49,26 +49,7 @@ def check_database() -> bool: return True @staticmethod - def check_downloader() -> bool: - - # Patch the health api endpoint if Downloader connection was failed - def change_health_status_to_unhealthy(): - url = "http://localhost:7892/api/v1/health" - payload = { - "status": "unhealthy" - } - - try: - response = requests.patch(url, json=payload) - response.raise_for_status() - logger.debug( - f"[Health] Health status updated successfully." - ) - except requests.exceptions.RequestException as e: - logger.debug( - f"[Health] Failed to update health status: {str(e)}" - ) - + def check_downloader() -> bool: try: url = ( f"http://{settings.downloader.host}" @@ -90,11 +71,9 @@ def change_health_status_to_unhealthy(): return False except requests.exceptions.ConnectionError: logger.error("[Checker] Downloader connect failed.") - change_health_status_to_unhealthy() return False except Exception as e: logger.error(f"[Checker] Downloader connect failed: {e}") - change_health_status_to_unhealthy() return False @staticmethod diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index e535550da..6d6eeb27a 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -17,13 +17,13 @@ def __init__(self): # Patch the health api endpoint if Network connection was failed def change_health_status_to_unhealthy(self): - url = "http://localhost:7892/api/v1/health" + health_check_url = "http://localhost:7892/api/v1/health" payload = { "status": "unhealthy" } try: - response = requests.patch(url, json=payload) + response = requests.patch(health_check_url, json=payload) response.raise_for_status() logger.debug( f"[Health] Health status updated successfully." From 21ef02268f8251cb53c39f7b26d4bfed19613780 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 13:29:52 +0800 Subject: [PATCH 09/20] fix core module import for health.py --- backend/src/module/api/health.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 7dd018012..133c51fe1 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -1,8 +1,8 @@ import logging from fastapi import APIRouter from fastapi.responses import JSONResponse -from core.status import ProgramStatus +from module.core.status import ProgramStatus from module.models import APIResponse router = APIRouter(prefix="/health", tags=["health"]) From fc3379ec40b3d492dcf27e987b3da5145423cdc2 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 13:40:04 +0800 Subject: [PATCH 10/20] fix typo --- backend/src/module/checker/checker.py | 4 ++-- backend/src/module/network/request_url.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 3d94504b9..3a58585bb 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -49,7 +49,7 @@ def check_database() -> bool: return True @staticmethod - def check_downloader() -> bool: + def check_downloader() -> bool: try: url = ( f"http://{settings.downloader.host}" @@ -83,4 +83,4 @@ def check_img_cache() -> bool: return True else: img_path.mkdir() - return False + return False \ No newline at end of file diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 6d6eeb27a..1957990a6 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -30,7 +30,7 @@ def change_health_status_to_unhealthy(self): ) except requests.exceptions.RequestException as e: logger.debug( - f"[Health] Failed to update health status: {str(e)}" + f"[Health] Failed to update health status: {e}" ) def get_url(self, url, retry=3): From 211b7ab69375dee9e6917f69a05864c216e755bd Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 14:17:04 +0800 Subject: [PATCH 11/20] fix healthcheck logic --- backend/src/module/api/health.py | 15 ++++++++------- backend/src/module/checker/checker.py | 2 +- backend/src/module/network/request_url.py | 12 +++++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 133c51fe1..8d2801759 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -12,17 +12,18 @@ @router.get("", response_model=APIResponse) async def health_check(): - health_status = current_health_status - program_is_stopped = ProgramStatus.is_stopped - if health_status == "unhealthy" or program_is_stopped: + program_is_running = ProgramStatus.is_running + global current_health_status + if current_health_status == "healthy" and program_is_running: return JSONResponse( - status_code=500, - content={"status": health_status}, + status_code=200, + content={"status": current_health_status}, ) else: return JSONResponse( - status_code=200, - content={"status": health_status}, + status_code=500, + current_health_status = "unhealthy" + content={"status": current_health_status}, ) @router.patch("", response_model=APIResponse) diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 3a58585bb..4ff6b3a0f 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -83,4 +83,4 @@ def check_img_cache() -> bool: return True else: img_path.mkdir() - return False \ No newline at end of file + return False diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 1957990a6..95651f9b4 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -16,17 +16,17 @@ def __init__(self): self._socks5_proxy = False # Patch the health api endpoint if Network connection was failed - def change_health_status_to_unhealthy(self): + def change_health_status(self,health_status): health_check_url = "http://localhost:7892/api/v1/health" payload = { - "status": "unhealthy" + "status": health_status } try: response = requests.patch(health_check_url, json=payload) response.raise_for_status() logger.debug( - f"[Health] Health status updated successfully." + f"[Health] Health status changed to {health_status}." ) except requests.exceptions.RequestException as e: logger.debug( @@ -40,6 +40,7 @@ def get_url(self, url, retry=3): req = self.session.get(url=url, headers=self.header, timeout=5) logger.debug(f"[Network] Successfully connected to {url}. Status: {req.status_code}") req.raise_for_status() + self.change_health_status("healthy") return req except requests.RequestException: logger.debug( @@ -53,7 +54,7 @@ def get_url(self, url, retry=3): logger.debug(e) break logger.error(f"[Network] Unable to connect to {url}, Please check your network settings") - self.change_health_status_to_unhealthy() + self.change_health_status("unhealthy") return None def post_url(self, url: str, data: dict, retry=3): @@ -64,6 +65,7 @@ def post_url(self, url: str, data: dict, retry=3): url=url, headers=self.header, data=data, timeout=5 ) req.raise_for_status() + self.change_health_status("healthy") return req except requests.RequestException: logger.warning( @@ -78,7 +80,7 @@ def post_url(self, url: str, data: dict, retry=3): break logger.error(f"[Network] Failed connecting to {url}") logger.warning("[Network] Please check DNS/Connection settings") - self.change_health_status_to_unhealthy() + self.change_health_status("unhealthy") return None def check_url(self, url: str): From d0b26eccc014f2a716126242fd293b079d6b4b01 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 14:27:02 +0800 Subject: [PATCH 12/20] fix global variable --- backend/src/module/api/health.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 8d2801759..ba36763a9 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -13,13 +13,13 @@ @router.get("", response_model=APIResponse) async def health_check(): program_is_running = ProgramStatus.is_running - global current_health_status if current_health_status == "healthy" and program_is_running: return JSONResponse( status_code=200, content={"status": current_health_status}, ) else: + global current_health_status return JSONResponse( status_code=500, current_health_status = "unhealthy" @@ -28,8 +28,8 @@ async def health_check(): @router.patch("", response_model=APIResponse) async def update_health_status(status: str): - global current_health_status try: + global current_health_status logger.info(f"[Health] Health status changed from {current_health_status} to {status}") current_health_status = status return JSONResponse( From bb7fba38e5f693dca695d631b07d439030a17db5 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 14:48:00 +0800 Subject: [PATCH 13/20] add debug logs --- backend/src/module/api/health.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index ba36763a9..1263022e6 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -12,24 +12,26 @@ @router.get("", response_model=APIResponse) async def health_check(): + global current_health_status program_is_running = ProgramStatus.is_running + logger.debug(f"[Health] Health status is {current_health_status} , ProgramStatus is {program_is_running}") if current_health_status == "healthy" and program_is_running: return JSONResponse( status_code=200, - content={"status": current_health_status}, + content={"status": "healthy"}, ) else: - global current_health_status return JSONResponse( status_code=500, current_health_status = "unhealthy" - content={"status": current_health_status}, + logger.debug(f"[Health] Health status is {current_health_status}.") + content={"status": "unhealthy"}, ) @router.patch("", response_model=APIResponse) async def update_health_status(status: str): + global current_health_status try: - global current_health_status logger.info(f"[Health] Health status changed from {current_health_status} to {status}") current_health_status = status return JSONResponse( From c7cc6d0d1734ce51c1b29337ca75d1aaf1361029 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 14:50:41 +0800 Subject: [PATCH 14/20] fix wrong JSONResponse --- backend/src/module/api/health.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 1263022e6..80014307e 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -21,10 +21,9 @@ async def health_check(): content={"status": "healthy"}, ) else: + current_health_status = "unhealthy" return JSONResponse( status_code=500, - current_health_status = "unhealthy" - logger.debug(f"[Health] Health status is {current_health_status}.") content={"status": "unhealthy"}, ) From 66f97f1623a04c1c39eb87f4839a35386dfcc0dc Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 15:06:10 +0800 Subject: [PATCH 15/20] fix healthcheck logics --- backend/src/module/api/health.py | 5 +---- backend/src/module/core/program.py | 21 +++++++++++++++++++++ backend/src/module/network/request_url.py | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 80014307e..8bd1cecb8 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -2,7 +2,6 @@ from fastapi import APIRouter from fastapi.responses import JSONResponse -from module.core.status import ProgramStatus from module.models import APIResponse router = APIRouter(prefix="/health", tags=["health"]) @@ -13,9 +12,7 @@ @router.get("", response_model=APIResponse) async def health_check(): global current_health_status - program_is_running = ProgramStatus.is_running - logger.debug(f"[Health] Health status is {current_health_status} , ProgramStatus is {program_is_running}") - if current_health_status == "healthy" and program_is_running: + if current_health_status == "healthy": return JSONResponse( status_code=200, content={"status": "healthy"}, diff --git a/backend/src/module/core/program.py b/backend/src/module/core/program.py index ee73c5f58..3cf85b1a0 100644 --- a/backend/src/module/core/program.py +++ b/backend/src/module/core/program.py @@ -1,4 +1,5 @@ import logging +import requests from module.conf import VERSION, settings from module.models import ResponseModel @@ -51,6 +52,24 @@ def startup(self): cache_image() self.start() + # Patch the health api endpoint + def change_health_status(self,health_status): + health_check_url = "http://localhost:7892/api/v1/health" + payload = { + "status": health_status + } + + try: + response = requests.patch(health_check_url, json=payload) + response.raise_for_status() + logger.debug( + f"[Health] Health status changed to {health_status}." + ) + except requests.exceptions.RequestException as e: + logger.debug( + f"[Health] Failed to update health status: {e}" + ) + def start(self): self.stop_event.clear() settings.load() @@ -59,6 +78,7 @@ def start(self): self.rename_start() if self.enable_rss: self.rss_start() + self.change_health_status("healthy") logger.info("Program running.") return ResponseModel( status=True, @@ -68,6 +88,7 @@ def start(self): ) else: self.stop_event.set() + self.change_health_status("unhealthy") logger.warning("Program failed to start.") return ResponseModel( status=False, diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index 95651f9b4..be738a718 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -15,7 +15,7 @@ def __init__(self): self.header = {"user-agent": "Mozilla/5.0", "Accept": "application/xml"} self._socks5_proxy = False - # Patch the health api endpoint if Network connection was failed + # Patch the health api endpoint if Network connection was changed def change_health_status(self,health_status): health_check_url = "http://localhost:7892/api/v1/health" payload = { From 770fb095d74cf9f3e5c623569099254a34fede54 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 15:22:33 +0800 Subject: [PATCH 16/20] fix check logic --- backend/src/module/api/health.py | 3 +++ backend/src/module/core/program.py | 21 --------------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 8bd1cecb8..fc1a3fbe6 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -3,6 +3,7 @@ from fastapi.responses import JSONResponse from module.models import APIResponse +from module.checker import Checker router = APIRouter(prefix="/health", tags=["health"]) logger = logging.getLogger(__name__) @@ -12,6 +13,8 @@ @router.get("", response_model=APIResponse) async def health_check(): global current_health_status + if not Checker.check_downloader(): + current_health_status = "unhealthy" if current_health_status == "healthy": return JSONResponse( status_code=200, diff --git a/backend/src/module/core/program.py b/backend/src/module/core/program.py index 3cf85b1a0..ee73c5f58 100644 --- a/backend/src/module/core/program.py +++ b/backend/src/module/core/program.py @@ -1,5 +1,4 @@ import logging -import requests from module.conf import VERSION, settings from module.models import ResponseModel @@ -52,24 +51,6 @@ def startup(self): cache_image() self.start() - # Patch the health api endpoint - def change_health_status(self,health_status): - health_check_url = "http://localhost:7892/api/v1/health" - payload = { - "status": health_status - } - - try: - response = requests.patch(health_check_url, json=payload) - response.raise_for_status() - logger.debug( - f"[Health] Health status changed to {health_status}." - ) - except requests.exceptions.RequestException as e: - logger.debug( - f"[Health] Failed to update health status: {e}" - ) - def start(self): self.stop_event.clear() settings.load() @@ -78,7 +59,6 @@ def start(self): self.rename_start() if self.enable_rss: self.rss_start() - self.change_health_status("healthy") logger.info("Program running.") return ResponseModel( status=True, @@ -88,7 +68,6 @@ def start(self): ) else: self.stop_event.set() - self.change_health_status("unhealthy") logger.warning("Program failed to start.") return ResponseModel( status=False, From fb6031dd0bed86a4a1efe59877a90d4d7a512732 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 15:32:11 +0800 Subject: [PATCH 17/20] fix health_check_url --- backend/src/module/network/request_url.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index be738a718..b072d8519 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -17,13 +17,10 @@ def __init__(self): # Patch the health api endpoint if Network connection was changed def change_health_status(self,health_status): - health_check_url = "http://localhost:7892/api/v1/health" - payload = { - "status": health_status - } + health_check_url = f"http://192.168.20.167:7892/api/v1/health?status={health_status}" try: - response = requests.patch(health_check_url, json=payload) + response = requests.patch(health_check_url) response.raise_for_status() logger.debug( f"[Health] Health status changed to {health_status}." From 4b7c988816f431b6f15edd07f75d1621d3fae2cd Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 15:41:51 +0800 Subject: [PATCH 18/20] change patch log level to debug --- backend/src/module/api/health.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index fc1a3fbe6..6f72d4301 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -31,7 +31,7 @@ async def health_check(): async def update_health_status(status: str): global current_health_status try: - logger.info(f"[Health] Health status changed from {current_health_status} to {status}") + logger.debug(f"[Health] Health status changed from {current_health_status} to {status}") current_health_status = status return JSONResponse( status_code=200, From 4962510f8fdde1f4064d7a70bb9397a30cc5d80c Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sat, 13 Jul 2024 16:27:33 +0800 Subject: [PATCH 19/20] change the request_url base_url --- backend/src/module/network/request_url.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/module/network/request_url.py b/backend/src/module/network/request_url.py index b072d8519..12bfb6ce2 100644 --- a/backend/src/module/network/request_url.py +++ b/backend/src/module/network/request_url.py @@ -17,7 +17,7 @@ def __init__(self): # Patch the health api endpoint if Network connection was changed def change_health_status(self,health_status): - health_check_url = f"http://192.168.20.167:7892/api/v1/health?status={health_status}" + health_check_url = f"http://localhost:7892/api/v1/health?status={health_status}" try: response = requests.patch(health_check_url) From 7b1faee730acebbd25931871249f99cb1ad304f9 Mon Sep 17 00:00:00 2001 From: Xavier Xiong Date: Sun, 14 Jul 2024 17:49:12 +0800 Subject: [PATCH 20/20] [safety] add validation to health api status parameter --- backend/src/module/api/health.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/module/api/health.py b/backend/src/module/api/health.py index 6f72d4301..bdb62300c 100644 --- a/backend/src/module/api/health.py +++ b/backend/src/module/api/health.py @@ -1,6 +1,7 @@ import logging from fastapi import APIRouter from fastapi.responses import JSONResponse +from typing import Literal from module.models import APIResponse from module.checker import Checker @@ -28,7 +29,7 @@ async def health_check(): ) @router.patch("", response_model=APIResponse) -async def update_health_status(status: str): +async def update_health_status(status: Literal["healthy", "unhealthy"]): global current_health_status try: logger.debug(f"[Health] Health status changed from {current_health_status} to {status}")