Skip to content

feat(bootstrap): shared shutdown lifetime (ISquidStdLifetime)#56

Merged
tgiachi merged 3 commits into
developfrom
feature/lifetime
Jul 3, 2026
Merged

feat(bootstrap): shared shutdown lifetime (ISquidStdLifetime)#56
tgiachi merged 3 commits into
developfrom
feature/lifetime

Conversation

@tgiachi

@tgiachi tgiachi commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

Port of moongatev2's ServerLifetimeService: a shared shutdown signal owned by the bootstrap. Closes the known follow-up "exit stops the services but a RunAsync-hosted app keeps waiting forever".

  • ISquidStdLifetime (ShutdownToken + idempotent RequestShutdown()), instance owned and ctor-registered by the bootstrap, disposed with it (post-dispose RequestShutdown is a safe no-op).
  • RunAsync now waits on a token linked to the caller token AND the shutdown token - RequestShutdown() ends the run with the ordered stop (engine events + lifecycle logs included).
  • Graceful Ctrl+C (our addition over the reference): Console.CancelKeyPress requests the shutdown instead of killing the process; a second Ctrl+C during shutdown still force-quits (handler removed before the stop).
  • ConsoleCommands exit is lifetime-first (fallback to the old direct StopAsync when no lifetime is registered - bare-container hosts). With a RunAsync host, exit now terminates the process cleanly. Manual StartAsync hosts: observe ShutdownToken yourself (documented).
  • Docs: RunAsync section + ConsoleCommands README.

Test Plan

  • 3 lifetime tests (RequestShutdown completes RunAsync with EngineStoppedEvent observed; idempotency; caller-token regression) + lifetime-first exit test (token cancelled, no direct bootstrap stop)
  • Full suite 1064/1064; build 0 errors; docfx 0 warnings; sample unchanged
  • Manual smoke pending on a real TTY: exit and Ctrl+C on a RunAsync host - not automatable in CI

NOTE: do NOT promote to main yet - batch still open.

@tgiachi
tgiachi merged commit a5db8af into develop Jul 3, 2026
2 checks passed
{
private readonly List<(Type ConfigType, Action<object> Apply)> _configHooks = [];
private readonly List<Action<IConfigManagerService>> _configReadyCallbacks = [];
private readonly SquidStdLifetimeService _lifetime = new();
Comment on lines +217 to +218
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested
|| _lifetime.ShutdownToken.IsCancellationRequested) { }
@tgiachi
tgiachi deleted the feature/lifetime branch July 20, 2026 12:26
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.

2 participants