Skip to content

fix(service): idle awaiting config instead of exit-restart loop when unconfigured - #10

Merged
bigduu merged 1 commit into
mainfrom
fix/4-idle-when-unconfigured
Jul 15, 2026
Merged

fix(service): idle awaiting config instead of exit-restart loop when unconfigured#10
bigduu merged 1 commit into
mainfrom
fix/4-idle-when-unconfigured

Conversation

@bigduu

@bigduu bigduu commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the 1s restart hot-loop reported in #4 when magpie runs as a bamboo-plugin services artifact:

  • Config file missing (fresh install, before the operator writes plugin_service_config/magpie/config.json): magpie used to log an ERROR and exit FAILURE. bamboo's ServiceManager restart policy (max_attempts: 0 = unlimited) then respawned it every ~1s forever.
  • platforms: [] (config present, nothing enabled): magpie used to warn and exit SUCCESS — but the restart policy restarts clean exits too, producing the same 1s loop.
  • Invalid config (parse error / failed validation, e.g. telegram entry missing a token): previously also exited FAILURE and crash-looped.

All three are now treated as a normal "not yet configured" state: magpie stays alive and polls the config path every 30s until it parses, validates, and has at least one platform configured, then proceeds with normal startup.

Change summary

  • await_valid_config(path, poll_interval) — the idle loop. Each iteration does one synchronous check (classify_config) then tokio::time::sleep(poll_interval); it never busy-spins. This also preserves the old "accidental hot-reload" the issue calls out: editing the config file while idle is picked up on the next 30s poll, the same way an operator's edit used to land on the restart loop's next spawn.
  • classify_config(path) — pure sync classifier (Ready(MagpieConfig) vs Idle(IdleReason)) so the missing-file / parse-error / validation-error / empty-platforms cases are unit-testable without going through the async poll loop.
  • Logging: one line when idling begins (or when the failure reason changes), then at most once every 5 minutes while it persists — visible without spamming.
  • main() races await_valid_config against the existing shutdown_signal() (tokio::select!), so SIGTERM/Ctrl-C still interrupts a sleeping poll and exits immediately — graceful shutdown is unaffected while idling.
  • --check (the interactive GET /api/v1/execute/defaults smoke test) intentionally keeps the old fail-fast behavior: it's an operator-invoked diagnostic, not the supervised service loop, so it should error immediately on a bad config rather than idle.
  • Added tokio's test-util feature as a dev-dependency for tokio::time::{pause, advance} in the new tests.

Diff is scoped to src/main.rs (startup/config handling) + Cargo.toml (test-only dependency) — no changes to bridge.rs or the resync/ask-park code (kept separate from the concurrent #9 work in that area).

Test plan

  • cargo fmt --check
  • cargo clippy --all-targets — clean, no warnings
  • cargo build --tests
  • cargo test — 172 lib tests + 12 main.rs tests (incl. 6 new: classify_config_* missing/parse/validation/empty-platforms/ready, await_valid_config_does_not_busy_spin_and_picks_up_a_later_config, await_valid_config_resolves_immediately_when_already_valid)
  • Manual smoke test of the built binary:
    • missing config file → process stays alive, logs the idle warning, SIGTERM exits cleanly within ~1s
    • platforms: [] → same idle behavior, SIGTERM exits cleanly
  • cargo tree -i aws-lc-sys — no match (native-tls pin unaffected by the new dev-dependency)

Closes #4.

https://claude.ai/code/session_014iw5PBsSzDFHus1GfkAK4y

…unconfigured

A missing/unparseable/invalid magpie.json, or one with platforms: [], made
main() exit — bamboo's ServiceManager (max_attempts: 0) then respawned the
process every ~1s forever. A freshly installed, not-yet-configured plugin
is a normal state, not a crash.

await_valid_config() now polls the config path every 30s (sleeping between
checks, so it never busy-spins) until it parses, validates, and has at
least one platform, logging once per idle-state change plus a low-rate
5-minute reminder. It races against shutdown_signal() so SIGTERM/Ctrl-C
still exits immediately while idling. --check keeps the old fail-fast
behavior since it's an interactive diagnostic, not the supervised loop.

Closes #4.
@bigduu
bigduu merged commit 9b57d63 into main Jul 15, 2026
3 checks passed
@bigduu
bigduu deleted the fix/4-idle-when-unconfigured branch July 15, 2026 20:02
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.

service: idle-and-wait instead of exit when config is missing or platforms is empty (1s restart loop under bamboo ServiceManager)

1 participant