Skip to content

Commit 6f34f27

Browse files
committed
Implement health service and proper shutdown
The health service is accessable without authentication The server didn't handle SIGINT or SIGTERM correctly because it relied on rescuing KeyboardInterrupt which isn't reliable in containers.
1 parent ad8235c commit 6f34f27

4 files changed

Lines changed: 35 additions & 5 deletions

File tree

main.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import concurrent.futures
22
import os
3+
import signal
34
import sys
45
import time
56

@@ -21,6 +22,7 @@
2122
import tucana.generated.velorum.info_pb2_grpc as info_pb2_grpc
2223
import tucana.generated.velorum.info_pb2 as info_pb2
2324
from grpc_reflection.v1alpha import reflection
25+
from grpc_health.v1 import health, health_pb2, health_pb2_grpc
2426

2527
from src.endpoint.info.info_endpoint import InfoService
2628
from src.endpoint.generation.generate_endpoint import GenerateService
@@ -34,6 +36,11 @@
3436
generate_pb2_grpc.add_GenerateServiceServicer_to_server(GenerateService(), server)
3537
info_pb2_grpc.add_InfoServiceServicer_to_server(InfoService(), server)
3638

39+
health_servicer = health.HealthServicer()
40+
health_servicer.set('liveness', health_pb2.HealthCheckResponse.SERVING)
41+
health_servicer.set('readiness', health_pb2.HealthCheckResponse.SERVING)
42+
health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
43+
3744
port = "0.0.0.0:50051"
3845
server.add_insecure_port(port)
3946
print(f"Velorum GenerateService läuft auf {port}...")
@@ -47,9 +54,12 @@
4754

4855
server.start()
4956

50-
try:
51-
while True:
52-
time.sleep(86400)
53-
except KeyboardInterrupt:
57+
def shutdown(signum, frame):
5458
print("\nServer wird sauber heruntergefahren...")
55-
server.stop(0)
59+
health_servicer.enter_graceful_shutdown()
60+
server.stop(5).wait()
61+
62+
signal.signal(signal.SIGTERM, shutdown)
63+
signal.signal(signal.SIGINT, shutdown)
64+
65+
server.wait_for_termination()

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ requires-python = ">=3.10,<3.13"
77
dependencies = [
88
"apscheduler>=3.11.2",
99
"grpcio>=1.80.0",
10+
"grpcio-health-checking>=1.80.0",
1011
"grpcio-reflection>=1.80.0",
1112
"instructor>=1.15.1",
1213
"PyJWT>=2.4.0",

src/interceptor/auth_interceptor.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
class AuthInterceptor(grpc.ServerInterceptor):
99

1010
def intercept_service(self, continuation, handler_call_details):
11+
method = handler_call_details.method or ''
12+
if method.startswith('/grpc.health.v1.Health/'):
13+
return continuation(handler_call_details)
14+
1115
metadata = dict(handler_call_details.invocation_metadata or [])
1216
auth_token = metadata.get('authorization', '')
1317

uv.lock

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)