Skip to content

Commit a640c1b

Browse files
committed
feat: fix deploy
1 parent e0ac1ad commit a640c1b

4 files changed

Lines changed: 20 additions & 3 deletions

File tree

apps/geoip/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Private FastAPI service for MaxMind-backed IP geolocation lookups.
1010

1111
## Endpoints
1212

13+
- `GET /live`
1314
- `GET /health`
1415
- `POST /v1/lookup`
1516

@@ -60,6 +61,8 @@ Deploy this app as its own Railway service named `geoip`.
6061

6162
The service binds to `::` by default so Railway private networking can reach it in both new dual-stack environments and older IPv6-only ones.
6263

64+
Use `/live` as the Railway deployment healthcheck path. `/health` remains a readiness endpoint and can return `503` until the MaxMind databases have been downloaded and loaded.
65+
6366
The main API should use:
6467

6568
```env

apps/geoip/src/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from .config import Settings
1212
from .database import GeoIPDatabaseManager
13-
from .models import HealthResponse, LookupRequest, LookupResponse
13+
from .models import HealthResponse, LiveResponse, LookupRequest, LookupResponse
1414

1515

1616
logging.basicConfig(level=logging.INFO)
@@ -48,6 +48,10 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
4848

4949
app = FastAPI(title="Cossistant GeoIP Service", lifespan=lifespan)
5050

51+
@app.get("/live", response_model=LiveResponse)
52+
async def live() -> LiveResponse:
53+
return LiveResponse(status="ok")
54+
5155
@app.get("/health", response_model=HealthResponse)
5256
async def health(response: Response) -> HealthResponse:
5357
snapshot = app.state.geoip_manager.health_snapshot()

apps/geoip/src/models.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
from pydantic import BaseModel, Field
77

88

9+
class LiveResponse(BaseModel):
10+
status: Literal["ok"]
11+
12+
913
class HealthResponse(BaseModel):
1014
status: Literal["healthy", "degraded", "unhealthy"]
1115
ready: bool
@@ -35,4 +39,3 @@ class LookupResponse(BaseModel):
3539
asn_organization: str | None = None
3640
source: str
3741
resolved_at: datetime
38-

apps/geoip/tests/test_main.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,17 @@ def test_health_returns_503_when_not_ready() -> None:
6565
assert response.json()["ready"] is False
6666

6767

68+
def test_live_returns_200_even_when_not_ready() -> None:
69+
with TestClient(create_app(FakeManager(ready=False))) as client:
70+
response = client.get("/live")
71+
72+
assert response.status_code == 200
73+
assert response.json() == {"status": "ok"}
74+
75+
6876
def test_lookup_returns_payload() -> None:
6977
with TestClient(create_app(FakeManager(ready=True))) as client:
7078
response = client.post("/v1/lookup", json={"ip": "8.8.8.8"})
7179

7280
assert response.status_code == 200
7381
assert response.json()["city"] == "Mountain View"
74-

0 commit comments

Comments
 (0)