Skip to content

feat: include Horizon reachability in readiness probe (issue #172) - #194

Merged
Manuel1234477 merged 2 commits into
StellarGateLabs:mainfrom
darcszn:feat/issue-172-horizon-readiness-check
Jul 23, 2026
Merged

feat: include Horizon reachability in readiness probe (issue #172)#194
Manuel1234477 merged 2 commits into
StellarGateLabs:mainfrom
darcszn:feat/issue-172-horizon-readiness-check

Conversation

@darcszn

@darcszn darcszn commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The /ready endpoint previously only checked the database. A deployment with Horizon unreachable still reported ready, causing the load balancer to route traffic to an instance that cannot detect on-chain payments.

This change makes /ready check both the database AND Horizon before returning 200, and adds a dedicated /deps endpoint for detailed per-dependency health breakdowns.

What changed:

src/api/mod.rs — ready() handler

  • Database check retained as the first gate.
  • Horizon check added as the second gate: GET horizon_url with a hard 3-second timeout via tokio::time::timeout. Any non-5xx response is treated as reachable; a timeout or connection error returns 503 with a human-readable "reason" field.
  • Check is skipped entirely when STELLAR_GATEWAY_PUBLIC=UNCONFIGURED (no gateway configured, no on-chain work to do).
  • 503 body now carries a "reason" field so operators see exactly which dependency is down without reading logs.

src/api/mod.rs — check_horizon_ready() (new helper)

  • Extracted into a dedicated async fn so both ready() and deps_health() call the same logic without duplication.
  • 3-second timeout is intentionally hard-coded: short enough to keep probe latency well inside any liveness/readiness check interval, long enough to absorb transient Horizon slowness.

src/api/mod.rs — GET /deps (new endpoint)

  • Returns a JSON breakdown of each dependency individually: { "database": "ok", "horizon": "ok"|"unavailable"|"unconfigured" } plus background_tasks { healthy, failures } from the TaskHealth gauge.
  • Returns 503 when any dependency is unavailable or failure count > 0.
  • Designed for dashboards and alert rules that need to distinguish a DB failure from a Horizon failure.

src/api/mod.rs — GET /metrics

  • Passes both webhook_metrics and task_health to metrics::render().

src/metrics.rs / src/lib.rs / src/main.rs

test and fixture updates

  • gateway_public changed to "UNCONFIGURED" in api_tests and rate_limit_tests make_config() so the Horizon check is skipped for unit tests that target an empty horizon_url.
  • AppState construction in all five integration test files and src/expiry.rs updated to supply webhook_metrics and task_health.

closes #137

darcszn and others added 2 commits July 22, 2026 15:25
…ateLabs#172)

The /ready endpoint previously only checked the database. A deployment
with Horizon unreachable still reported ready, causing the load balancer
to route traffic to an instance that cannot detect on-chain payments.

This change makes /ready check both the database AND Horizon before
returning 200, and adds a dedicated /deps endpoint for detailed
per-dependency health breakdowns.

What changed:

src/api/mod.rs — ready() handler
- Database check retained as the first gate.
- Horizon check added as the second gate: GET horizon_url with a hard
  3-second timeout via tokio::time::timeout. Any non-5xx response is
  treated as reachable; a timeout or connection error returns 503 with
  a human-readable "reason" field.
- Check is skipped entirely when STELLAR_GATEWAY_PUBLIC=UNCONFIGURED
  (no gateway configured, no on-chain work to do).
- 503 body now carries a "reason" field so operators see exactly which
  dependency is down without reading logs.

src/api/mod.rs — check_horizon_ready() (new helper)
- Extracted into a dedicated async fn so both ready() and deps_health()
  call the same logic without duplication.
- 3-second timeout is intentionally hard-coded: short enough to keep
  probe latency well inside any liveness/readiness check interval, long
  enough to absorb transient Horizon slowness.

src/api/mod.rs — GET /deps (new endpoint)
- Returns a JSON breakdown of each dependency individually:
    { "database": "ok", "horizon": "ok"|"unavailable"|"unconfigured" }
  plus background_tasks { healthy, failures } from the TaskHealth gauge.
- Returns 503 when any dependency is unavailable or failure count > 0.
- Designed for dashboards and alert rules that need to distinguish a
  DB failure from a Horizon failure.

src/api/mod.rs — GET /metrics
- Passes both webhook_metrics and task_health to metrics::render().

src/metrics.rs / src/lib.rs / src/main.rs
- Full metrics + task-health foundation included (carries forward
  issues StellarGateLabs#170 and StellarGateLabs#171 as prerequisites).

test and fixture updates
- gateway_public changed to "UNCONFIGURED" in api_tests and
  rate_limit_tests make_config() so the Horizon check is skipped for
  unit tests that target an empty horizon_url.
- AppState construction in all five integration test files and
  src/expiry.rs updated to supply webhook_metrics and task_health.
@Manuel1234477
Manuel1234477 merged commit 6d89d44 into StellarGateLabs:main Jul 23, 2026
1 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/ready does not check Horizon reachability

2 participants