Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import os
import sys
import time
Expand All @@ -10,7 +11,7 @@
server_details_router = APIRouter(prefix="", tags=["Server Details"])
_start_time = time.time()
_last_event_time = time.time()
_initialization_complete = False
_initialization_complete = asyncio.Event()


def _package_version(dist_name: str) -> str:
Expand Down Expand Up @@ -60,8 +61,7 @@ def mark_initialization_complete() -> None:
have finished initializing. Until this is called, the /ready endpoint will
return 503 Service Unavailable.
"""
global _initialization_complete
_initialization_complete = True
_initialization_complete.set()


@server_details_router.get("/alive")
Expand All @@ -83,7 +83,7 @@ async def ready(response: Response) -> dict[str, str]:
This endpoint should be used by Kubernetes readiness probes to determine
when the pod is ready to receive traffic. Returns 503 during initialization.
"""
if _initialization_complete:
if _initialization_complete.is_set():
return {"status": "ready"}
else:
response.status_code = 503
Expand Down
50 changes: 50 additions & 0 deletions tests/agent_server/test_server_details_router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Tests for the server details router, including the /ready endpoint."""

import asyncio

import pytest
from fastapi.testclient import TestClient

import openhands.agent_server.server_details_router as sdr
from openhands.agent_server.api import create_app
from openhands.agent_server.config import Config


@pytest.fixture(autouse=True)
def reset_initialization_state():
"""Reset the asyncio.Event between tests to avoid state leakage."""
sdr._initialization_complete = asyncio.Event()
yield
sdr._initialization_complete = asyncio.Event()


@pytest.fixture
def client():
app = create_app(Config(static_files_path=None))
return TestClient(app)


def test_ready_returns_503_before_init(client):
"""The /ready endpoint should return 503 while initialization is not complete."""
response = client.get("/ready")
assert response.status_code == 503
assert response.json()["status"] == "initializing"


def test_ready_returns_200_after_init(client):
"""The /ready endpoint should return 200 after mark_initialization_complete()."""
sdr.mark_initialization_complete()
response = client.get("/ready")
assert response.status_code == 200
assert response.json()["status"] == "ready"


def test_ready_resets_after_new_event(client):
"""After resetting the event, /ready should return 503 again."""
sdr.mark_initialization_complete()
assert client.get("/ready").status_code == 200

# Simulate a reset (e.g. for testing)
sdr._initialization_complete = asyncio.Event()
response = client.get("/ready")
assert response.status_code == 503
Loading