Skip to content

refactor(daemon): unify daemon lifecycle shutdown sequencing #72

@pentaxis93

Description

@pentaxis93

Summary

The daemon lifecycle in crates/agentd/src/daemon.rs is no longer expressed as one coherent sequence. Startup still reads as a single flow (claim -> reconcile -> bind -> start scheduler -> accept loop), but shutdown has been split across feature-specific helpers: finish_daemon_loop(...) handles listener shutdown and handler draining, join_scheduler_thread(...) is coordinated separately, and ownership of the shared shutdown flag is implicit rather than part of one lifecycle contract.

That fragmentation is fragile. The scheduler added in #50 depends on the same shutdown flag the signal handlers use, but the accept-error exit path does not set it before joining the scheduler, so a hard accept() failure can hang the daemon instead of surfacing the original error. This is lifecycle debt introduced by #50, not inherited from earlier daemon work.

This follow-up should make daemon shutdown a single structured flow so lifecycle invariants are explicit and feature additions do not need to stitch themselves into multiple exit helpers.

Introduced by: #50

Scope

  • crates/agentd/src/daemon.rs — express daemon lifecycle orchestration as one structured startup/shutdown sequence instead of split helper coordination
  • daemon lifecycle tests — cover signal-driven exit and accept-loop failure against the same shutdown sequence
  • documentation affected by lifecycle behavior claims — update if shutdown sequencing or daemon lifecycle description is documented elsewhere

Acceptance criteria

  • The daemon lifecycle is expressed as one structured sequence: claim, reconcile, bind, start scheduler, accept loop, then shutdown
  • Every daemon exit path follows the same shutdown sequence: set shutdown flag, stop accepting new connections, drain started handlers, stop the scheduler, and clean up runtime-owned resources
  • Lifecycle coordination no longer depends on separate feature-specific helpers with implicit ordering contracts across shutdown flag management, scheduler joining, and listener cleanup
  • Regression coverage proves both signal-driven shutdown and hard accept-loop failure drive the same orderly shutdown behavior
  • Documentation and inline lifecycle descriptions remain accurate after the refactor

Dependencies

Depends on: #50 (this debt was introduced while landing scheduled profiles and should be resolved before #50 is considered complete)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions