Files
bvandeusenandClaude Opus 5 8c50ff242c
CI / lint (push) Successful in 2s
CI / unit (push) Successful in 40s
CI / integration (push) Successful in 2m21s
CI / publish (push) Successful in 1m2s
fix(db): ride out a brief database outage mid-request; explain it if it persists
The operator's 500 was NOT the startup gap I attributed it to. They found it by
logging in and getting Steward's own error page -- which means create_app had
completed and the app was serving, so the gaierror came from a request handler
acquiring a connection, not from boot. Neither prior fix covers that: the
startup retry never runs, and pool_pre_ping only helps once the database is
back, since its replacement connect fails too while the container is gone.

Adds a before_request gate that acquires a pooled connection with a short
bounded retry (~1.75s over 4 tries) so a database restart is ridden out
invisibly, and renders a distinct 503 "database unavailable" page when the
budget is exhausted. The request budget is deliberately far shorter than the
startup one: nobody watches a container boot, but somebody is watching this
page load, and a page that hangs is worse than one that says what is wrong.

/health and static are exempt -- a liveness probe must stay answerable while
the database is down, or a dependency outage triggers a restart loop.

Credential and missing-database errors still propagate rather than being
reported as "unavailable", which would send the operator chasing the wrong
problem entirely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 08:23:01 -04:00

17 lines
888 B
HTML

{% extends "base.html" %}
{% block title %}Database unavailable — Steward{% endblock %}
{% block content %}
<div style="text-align:center; padding: 4rem 2rem; font-family: var(--font-serif);">
<h1 style="color: var(--yellow); font-size: 2.5rem; margin-bottom: 0.5rem;">503</h1>
<p style="color: var(--text); font-size: 1.2rem; margin-bottom: 0.25rem;">The records are out of reach.</p>
<p style="color: var(--text-dim); margin-bottom: 0.5rem; max-width: 34rem; margin-left:auto; margin-right:auto;">
Steward is running, but cannot reach its database. Nothing has been lost —
this page will work again as soon as the database is back.
</p>
<p style="color: var(--text-dim); font-size: 0.85rem; margin-bottom: 1.5rem;">
Steward already retried for a moment before showing this.
</p>
<a href="{{ request.path }}" class="btn">Try again</a>
</div>
{% endblock %}