Skip to content

Bound the GitHub requests of EvergreenService so a stalled GitHub cannot hang the UI - #57

Open
lgnap wants to merge 1 commit into
antoinevalentinHA:masterfrom
lgnap:fix/issue-11-evergreen-http-timeout
Open

lgnap wants to merge 1 commit into
antoinevalentinHA:masterfrom
lgnap:fix/issue-11-evergreen-http-timeout

Conversation

@lgnap

@lgnap lgnap commented Sep 11, 2026

Copy link
Copy Markdown

What

EvergreenService sent its three GitHub requests (latest release, announce commit, announce content) without any timeout. On a network where GitHub is unreachable but not refused — dropped packets, captive portal, a proxy that accepts and stalls — the request stayed pending forever, and with it the future the controller was waiting on. The frontend then sat on its "fetching" toast for the whole session.

Every request now carries HTTP_TIMEOUT_MS (5 s). On timeout the future fails; EvergreenController already turns that into a 500, and actionLoadEvergreen already turns that into a logged error (announce) or an error toast (latest release). Failing fast is the whole fix.

Not done on purpose: falling back to the built-in announce on timeout. That text is the 2020 first-announce, only meant for the "no commits on ANNOUNCE.md yet" case; showing it whenever GitHub is unreachable would pop an obsolete modal on every offline start.

Seam

A package-private constructor makes the API host, raw host, port, TLS and timeout injectable. Production keeps the single public constructor; nothing else changes.

Tests

EvergreenServiceTimeoutTest (5 tests) starts a local Vert.x server that deliberately never answers on a chosen path and asserts that each future completes — failed, with a TimeoutException as the cause — within a bound, for:

  • latest()
  • announce() when the commit lookup stalls
  • announce() when only the content fetch stalls (the second hop must be bounded too)

plus the nominal latest() and two-hop announce() against the same server answering, as controls. Verified red without the .timeout(...) calls: the three stalling cases hang until the test bound (3 failures).

Locally: mvn -B -Dskip.installnodeyarn=true -Dskip.yarn=true test → 327 run, 0 failures, 0 errors, 39 skipped (FAT32 opt-in). git diff --exit-code clean. Frontend untouched.

Tracked in lgnap#11.

🤖 Generated with Claude Code

…b cannot hang the UI

The three GitHub requests (latest release, announce commit, announce
content) were sent without a timeout. On a network where GitHub is
unreachable but not refused — dropped packets, captive portal, a proxy
that accepts and stalls — the request stayed pending forever, and with
it the future the controller was waiting on: the frontend sat on its
"fetching" toast for the whole session.

Every request now carries HTTP_TIMEOUT_MS (5 s). On timeout the future
fails, which the controller already turns into a 500 and the frontend
into a logged error or an error toast. The built-in announce is
deliberately not used as a fallback: popping the 2020 announce on every
offline start would be a regression of its own.

A package-private constructor makes host, port, TLS and timeout
injectable. EvergreenServiceTimeoutTest aims the service at a local
server that never answers and asserts each future fails within a bound
with a TimeoutException, for each of the three requests (the second hop
of announce() included), plus the nominal two-hop path as a control.
Without the timeouts the three stalling cases hang until the test bound.

Closes #11

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant