Skip to content

fix: allow setResetting() from LOADING_INITIAL and RESETTING#99

Merged
tkuhn merged 1 commit into
mainfrom
fix/setresetting-from-loading-initial
May 18, 2026
Merged

fix: allow setResetting() from LOADING_INITIAL and RESETTING#99
tkuhn merged 1 commit into
mainfrom
fix/setresetting-from-loading-initial

Conversation

@tkuhn
Copy link
Copy Markdown
Contributor

@tkuhn tkuhn commented May 18, 2026

Summary

  • A live instance with FORCE_RESYNC=true and persisted state LOADING_INITIAL (typical after a previous crash mid-initial-load) is stuck in a restart loop. The FORCE_RESYNC block in MainVerticle.start() calls StatusController.setResetting(), which only accepted READY or LOADING_UPDATES as source states. The throw bubbles to the init thread's catch, which logs "Initial load failed, terminating..." and calls Runtime.exit(1).
  • A reset is semantically "discard prior load progress, restart from -1" — valid from any post-initialize state. Loosen the guard to reject only LAUNCHING (state machine not yet initialized).
  • Also makes RESETTING → RESETTING (retry of a crashed prior reset) idempotent, and fixes the same latent hole in JellyNanopubLoader.performResync() for free.

Test plan

  • StatusControllerTest updated: setResettingFromInvalidStatesThrows split into setResettingFromLaunchingThrows; added setResettingFromLoadingInitial (the live failure scenario) and setResettingFromResetting. All 16 tests pass.
  • On the affected live instance: restart with FORCE_RESYNC=true and persisted state LOADING_INITIAL; confirm the resync proceeds instead of looping on IllegalStateException.

🤖 Generated with Claude Code

The FORCE_RESYNC startup path in MainVerticle calls setResetting()
whenever the persisted state isn't LAUNCHING, but setResetting()
only accepted READY or LOADING_UPDATES. A service that crashed
mid-initial-load persists state as LOADING_INITIAL; restarting
with FORCE_RESYNC=true then loops on IllegalStateException →
"Initial load failed, terminating..." → exit(1).

A reset is "discard prior progress, restart from -1", which is
semantically valid from any post-initialize state. Broaden the
guard to only reject LAUNCHING (state machine uninitialized).
This also makes a crashed prior reset retryable (RESETTING →
RESETTING) and fixes the same latent hole in
JellyNanopubLoader.performResync() under contrived state mixes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tkuhn tkuhn merged commit f618996 into main May 18, 2026
8 checks passed
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.11.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant