Skip to content

Commit fa4efbd

Browse files
aacicshaneahmedpre-commit-ci[bot]
authored
🩺 Add Health Check and Sessions Endpoints (#925)
- Introduces a healthcheck endpoint and the sessions endpoint. - The purpose of the healthcheck endpoint is to tell if the TileServer is running. - The purpose of the sessions endpoint is to return a mapping of all active sessions and their loaded Whole Slide Images (WSIs). --------- Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7ac64f1 commit fa4efbd

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

tests/test_tileserver.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,44 @@ def test_prop_range(app: TileServer) -> None:
734734
assert response.status_code == 200
735735
# should be back to no scaling
736736
assert layer.renderer.score_fn(0.5) == 0.5
737+
738+
739+
def test_healthcheck(empty_app: TileServer) -> None:
740+
"""Test the /tileserver/healthcheck endpoint."""
741+
with empty_app.test_client() as client:
742+
response = client.get("/tileserver/healthcheck")
743+
assert response.status_code == 200
744+
assert response.content_type == "application/json"
745+
assert response.get_json() == {"status": "OK"}
746+
747+
748+
def test_sessions_no_slide_loaded(empty_app: TileServer) -> None:
749+
"""Test /tileserver/sessions when no slides are loaded."""
750+
with empty_app.test_client() as client:
751+
setup_app(client)
752+
response = client.get("/tileserver/sessions")
753+
assert response.status_code == 200
754+
assert response.is_json
755+
assert response.get_json() == {}
756+
757+
758+
def test_sessions_one_slide_loaded(
759+
empty_app: TileServer, remote_sample: Callable
760+
) -> None:
761+
"""Test /tileserver/sessions after loading one slide."""
762+
with empty_app.test_client() as client:
763+
setup_app(client)
764+
slide_path = safe_str(remote_sample("svs-1-small"))
765+
766+
response = client.put(
767+
"/tileserver/slide",
768+
data={"slide_path": slide_path},
769+
)
770+
assert response.status_code == 200
771+
772+
response = client.get("/tileserver/sessions")
773+
assert response.status_code == 200
774+
sessions = response.get_json()
775+
776+
assert isinstance(sessions, dict)
777+
assert len(sessions) == 1

tiatoolbox/visualization/tileserver.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ def __init__( # noqa: PLR0915
165165
self.route("/tileserver/tap_query/<x>/<y>")(self.tap_query)
166166
self.route("/tileserver/prop_range", methods=["PUT"])(self.prop_range)
167167
self.route("/tileserver/shutdown", methods=["POST"])(self.shutdown)
168+
self.route("/tileserver/sessions", methods=["GET"])(self.sessions)
169+
self.route("/tileserver/healthcheck", methods=["GET"])(self.healthcheck)
168170

169171
def _get_session_id(self: TileServer) -> str:
170172
"""Get the session_id from the request.
@@ -718,6 +720,36 @@ def prop_range(self: TileServer) -> str:
718720
self.renderers[session_id].score_fn = lambda x: (x - minv) / (maxv - minv)
719721
return "done"
720722

723+
def sessions(self: TileServer) -> Response:
724+
"""Retrieve a mapping of session keys to their corresponding slide file paths.
725+
726+
Returns:
727+
Response:
728+
A JSON response containing a mapping of session keys
729+
and their respective slide file paths.
730+
731+
"""
732+
session_paths = {}
733+
for key, layer in self.layers.items():
734+
slide = layer.get("slide")
735+
if slide is not None:
736+
session_paths[key] = str(slide.info.as_dict().get("file_path", ""))
737+
return jsonify(session_paths)
738+
739+
@staticmethod
740+
def healthcheck() -> Response:
741+
"""Simple health check endpoint to verify the server is running.
742+
743+
Useful for load balancers or uptime monitoring tools to check
744+
if the service is operational.
745+
746+
Returns:
747+
Response:
748+
A JSON response with status "OK" and HTTP status code 200.
749+
750+
"""
751+
return jsonify({"status": "OK"})
752+
721753
@staticmethod
722754
def shutdown() -> None:
723755
"""Shutdown the tileserver."""

tiatoolbox/visualization/tileserver_api.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,24 @@ paths:
395395
'200':
396396
description: Successful response
397397

398+
/tileserver/sessions:
399+
get:
400+
summary: Returns all session/path mappings
401+
responses:
402+
'200':
403+
description: A jsonified session/path mappings
404+
content:
405+
application/json:
406+
407+
/tileserver/healthcheck:
408+
get:
409+
summary: Returns Ok if server is online
410+
responses:
411+
'200':
412+
description: A json with status field
413+
content:
414+
application/json:
415+
398416
/tileserver/tap_query/{x}/{y}:
399417
get:
400418
summary: Query annotation at a point

0 commit comments

Comments
 (0)