Skip to content

Commit 7f6081c

Browse files
committed
feat: implement background health check for Inference API with Celery queue management
1 parent 28d7c0e commit 7f6081c

2 files changed

Lines changed: 46 additions & 6 deletions

File tree

inference_api/presentation/api/main.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
@asynccontextmanager
2020
async def lifespan(app: FastAPI):
21-
# Any necessary init happens via Dependency Injector singletons if needed
2221

2322
main_api_url = settings.MAIN_API_URL
2423
webhook_secret = settings.WEBHOOK_SECRET
@@ -43,11 +42,12 @@ async def fire_online_webhook_with_retry():
4342
logger.error(f"Failed to send online webhook: {e}. Retrying in 5 seconds...")
4443
await asyncio.sleep(5)
4544

46-
# Run the robust webhook logic in the background so we don't block server startup
47-
asyncio.create_task(fire_online_webhook_with_retry())
45+
task = asyncio.create_task(fire_online_webhook_with_retry())
4846

4947
yield
5048

49+
task.cancel()
50+
5151
app = FastAPI(
5252
title="Eventsnap Inference API",
5353
description="Local testing server for HF Endpoint Handler",
@@ -64,6 +64,10 @@ async def fire_online_webhook_with_retry():
6464

6565
app.include_router(inference.router)
6666

67+
@app.get("/health", tags=["Health"])
68+
async def health_check():
69+
return {"status": "ok"}
70+
6771
if __name__ == "__main__":
6872
port = 5000
6973
logger.info("=" * 50)

main_api/presentation/api/main.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,51 @@
99
from sqlalchemy import text
1010
from infrastructure.queue.celery_app import celery_app
1111

12-
# Create the container at startup to wire everything
13-
container = get_container()
12+
import asyncio
13+
import httpx
14+
import logging
15+
from config import settings
1416

17+
container = get_container()
18+
logger = logging.getLogger(__name__)
1519

1620
@asynccontextmanager
1721
async def lifespan(app: FastAPI):
1822
# Any necessary init happens via Dependency Injector singletons if needed
23+
24+
async def poll_inference_api():
25+
consecutive_failures = 0
26+
current_state = "online"
27+
28+
while True:
29+
try:
30+
async with httpx.AsyncClient() as client:
31+
response = await client.get(f"{settings.INFERENCE_API_URL.rstrip('/')}/health", timeout=5.0)
32+
response.raise_for_status()
33+
34+
consecutive_failures = 0
35+
if current_state == "offline":
36+
logger.info("Poller: Inference API is back online! Resuming Celery queue...")
37+
await asyncio.to_thread(celery_app.control.add_consumer, 'celery', reply=True)
38+
current_state = "online"
39+
40+
except Exception as e:
41+
consecutive_failures += 1
42+
if consecutive_failures >= 3 and current_state == "online":
43+
logger.warning(f"Poller: Inference API health check failed {consecutive_failures} times! Pausing Celery queue...")
44+
await asyncio.to_thread(celery_app.control.cancel_consumer, 'celery', reply=True)
45+
current_state = "offline"
46+
47+
# Wait 10 seconds before next ping
48+
await asyncio.sleep(10)
49+
50+
# Start the background task
51+
task = asyncio.create_task(poll_inference_api())
52+
1953
yield
20-
54+
55+
# Clean up on shutdown
56+
task.cancel()
2157

2258
app = FastAPI(
2359
title="Eventsnap Main API (Orchestrator) - Clean",

0 commit comments

Comments
 (0)