kin: BATON-ARCH-012 Добавить WEBHOOK_ENABLED флаг для локальной разработки
This commit is contained in:
parent
69d01ac3a6
commit
0f8ecdfc49
5 changed files with 434 additions and 0 deletions
|
|
@ -20,3 +20,4 @@ WEBHOOK_SECRET: str = _require("WEBHOOK_SECRET")
|
|||
WEBHOOK_URL: str = _require("WEBHOOK_URL")
|
||||
WEBHOOK_ENABLED: bool = os.getenv("WEBHOOK_ENABLED", "true").lower() == "true"
|
||||
FRONTEND_ORIGIN: str = os.getenv("FRONTEND_ORIGIN", "http://localhost:3000")
|
||||
APP_URL: str | None = os.getenv("APP_URL") # Публичный URL приложения для keep-alive self-ping
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from fastapi import Depends, FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
|
@ -24,6 +26,21 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
# aggregator = telegram.SignalAggregator(interval=10) # v2.0 feature — отключено в v1 (ADR-004)
|
||||
|
||||
_KEEPALIVE_INTERVAL = 600 # 10 минут
|
||||
|
||||
|
||||
async def _keep_alive_loop(app_url: str) -> None:
|
||||
"""Периодически пингует /health чтобы предотвратить cold start на бесплатных хостингах."""
|
||||
health_url = f"{app_url.rstrip('/')}/health"
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
while True:
|
||||
await asyncio.sleep(_KEEPALIVE_INTERVAL)
|
||||
try:
|
||||
resp = await client.get(health_url)
|
||||
logger.info("Keep-alive ping %s → %d", health_url, resp.status_code)
|
||||
except Exception as exc:
|
||||
logger.warning("Keep-alive ping failed: %s", exc)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
|
|
@ -39,9 +56,24 @@ async def lifespan(app: FastAPI):
|
|||
# task = asyncio.create_task(aggregator.run())
|
||||
# logger.info("Aggregator started")
|
||||
|
||||
keepalive_task: asyncio.Task | None = None
|
||||
if config.APP_URL:
|
||||
keepalive_task = asyncio.create_task(_keep_alive_loop(config.APP_URL))
|
||||
logger.info("Keep-alive task started (target: %s/health)", config.APP_URL)
|
||||
else:
|
||||
logger.info("APP_URL not set — keep-alive disabled")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
if keepalive_task is not None:
|
||||
keepalive_task.cancel()
|
||||
try:
|
||||
await keepalive_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
logger.info("Keep-alive task stopped")
|
||||
|
||||
# aggregator.stop()
|
||||
# await aggregator.flush()
|
||||
# task.cancel()
|
||||
|
|
@ -62,6 +94,11 @@ app.add_middleware(
|
|||
)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health() -> dict[str, Any]:
|
||||
return {"status": "ok", "timestamp": int(time.time())}
|
||||
|
||||
|
||||
@app.post("/api/register", response_model=RegisterResponse)
|
||||
async def register(body: RegisterRequest) -> RegisterResponse:
|
||||
result = await db.register_user(uuid=body.uuid, name=body.name)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue