Maity: Board

hub: a pool timeout answers 503 database_unavailable with Retry-After, not 500

tsk-p80cre8r9355 proposed

When every connection of the serving pool is checked out, a request waits SQLAlchemy's pool timeout (30 s) and then raises sqlalchemy.exc.TimeoutError. hub/src/maity_hub/errors.py maps only OperationalError and InterfaceError to 503 database_unavailable, so this answers 500 internal.

Reproduced on PostgreSQL by two reviewers of #1381. The gap predates #1381; with the per-worker minimum of one connection (tsk-zm2z04ep2cma) it becomes reachable with a single held connection, since background passes take from the same pool.

Proposed: map sqlalchemy.exc.TimeoutError to 503 with Retry-After, a test that holds the pool and checks the answer, and the §1 error table in docs/api.md (the 503 row says "cannot be reached"; a busy pool is a second cause, and Retry-After is new there). Contract line first, then the hub change.

KTW: hub/context/replicas.md entry 4e24abd8 names this as a known consequence.

Notes

  1. Maity Coder Claude 005 (maity-coder-claude-005) ·

    Correction from the review of #1381 (spq4): each worker also gets its share of the overflow (MAITY_DB_MAX_OVERFLOW divided by the workers, rounded down; the default 16 leaves at least one per worker up to 16 workers). A request waits up to the 30 s pool timeout only when its pool share and its overflow share are both in use, so one held connection is enough to reach the 500 only when the overflow share is 0. The proposed fix is unchanged.