Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check status server #20

Merged
merged 2 commits into from
Apr 23, 2024
Merged
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
2 changes: 1 addition & 1 deletion florist/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def start(server_address: str, client: str, data_path: str, redis_host: str, red
return JSONResponse({"error": str(ex)}, status_code=500)


@app.get("/api/client/check_status")
@app.get("/api/client/check_status/{client_uuid}")
jewelltaylor marked this conversation as resolved.
Show resolved Hide resolved
def check_status(client_uuid: str, redis_host: str, redis_port: str) -> JSONResponse:
"""
Retrieve value at key client_uuid in redis if it exists.
Expand Down
44 changes: 44 additions & 0 deletions florist/api/routes/server/status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""FastAPI routes for checking server status."""
import json
import logging

import redis
from fastapi import APIRouter
from fastapi.responses import JSONResponse


router = APIRouter()

LOGGER = logging.getLogger("uvicorn.error")


@router.get(
path="/{server_uuid}",
response_description="Check status of the server",
)
def check_status(server_uuid: str, redis_host: str, redis_port: str) -> JSONResponse:
"""
Retrieve value at key server_uuid in redis if it exists.

:param server_uuid: (str) the uuid of the server to fetch from redis.
:param redis_host: (str) the host name for the Redis instance for metrics reporting.
:param redis_port: (str) the port for the Redis instance for metrics reporting.

:return: (JSONResponse) If successful, returns 200 with JSON containing the val at `server_uuid`.
If not successful, returns the appropriate error code with a JSON with the format below:
{"error": <error message>}
"""
try:
redis_connection = redis.Redis(host=redis_host, port=redis_port)

result = redis_connection.get(server_uuid)

if result is not None:
assert isinstance(result, bytes)
return JSONResponse(json.loads(result))

return JSONResponse({"error": f"Server {server_uuid} Not Found"}, status_code=404)

except Exception as ex:
LOGGER.exception(ex)
return JSONResponse({"error": str(ex)}, status_code=500)
2 changes: 2 additions & 0 deletions florist/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from motor.motor_asyncio import AsyncIOMotorClient

from florist.api.routes.server.job import router as job_router
from florist.api.routes.server.status import router as status_router
from florist.api.routes.server.training import router as training_router


Expand All @@ -29,3 +30,4 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[Any, Any]:
app = FastAPI(lifespan=lifespan)
app.include_router(training_router, tags=["training"], prefix="/api/server/training")
app.include_router(job_router, tags=["job"], prefix="/api/server/job")
app.include_router(status_router, tags=["status"], prefix="/api/server/check_status")
50 changes: 50 additions & 0 deletions florist/tests/unit/api/routes/server/test_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json
from unittest.mock import Mock, patch

from florist.api.routes.server.status import check_status


@patch("florist.api.routes.server.status.redis")
def test_check_status(mock_redis: Mock) -> None:
mock_redis_connection = Mock()
mock_redis_connection.get.return_value = b"{\"info\": \"test\"}"

test_uuid = "test_uuid"
test_redis_host = "localhost"
test_redis_port = "testport"

mock_redis.Redis.return_value = mock_redis_connection

response = check_status(test_uuid, test_redis_host, test_redis_port)

mock_redis.Redis.assert_called_with(host=test_redis_host, port=test_redis_port)
assert json.loads(response.body.decode()) == {"info": "test"}

@patch("florist.api.routes.server.status.redis")
def test_check_status_not_found(mock_redis: Mock) -> None:
mock_redis_connection = Mock()
mock_redis_connection.get.return_value = None

test_uuid = "test_uuid"
test_redis_host = "localhost"
test_redis_port = "testport"

mock_redis.Redis.return_value = mock_redis_connection

response = check_status(test_uuid, test_redis_host, test_redis_port)

mock_redis.Redis.assert_called_with(host=test_redis_host, port=test_redis_port)
assert response.status_code == 404
assert json.loads(response.body.decode()) == {"error": f"Server {test_uuid} Not Found"}

@patch("florist.api.routes.server.status.redis.Redis", side_effect=Exception("test exception"))
def test_check_status_fail_exception(mock_redis: Mock) -> None:

test_uuid = "test_uuid"
test_redis_host = "localhost"
test_redis_port = "testport"

response = check_status(test_uuid, test_redis_host, test_redis_port)

assert response.status_code == 500
assert json.loads(response.body.decode()) == {"error": "test exception"}