banger/internal/daemon/ARCHITECTURE.md
Thales Maciel ea0db1e17e
Split internal/daemon vm.go and guest_sessions.go by concern
vm.go (1529 LOC) splits into vm_create, vm_lifecycle, vm_set, vm_stats,
vm_disk, vm_authsync; firecracker/DNS/helpers stay in vm.go.

guest_sessions.go (1266 LOC) splits into session_controller,
session_lifecycle, session_attach, session_stream; scripts and helpers
stay in guest_sessions.go.

Mechanical move only. No behavior change. Adds doc.go and
ARCHITECTURE.md capturing subsystem map and current lock ordering as
the baseline for the upcoming subsystem extraction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:47:08 -03:00

59 lines
2.4 KiB
Markdown

# `internal/daemon` architecture
This document captures the current (pre-refactor) layout of the daemon
package and the lock ordering its callers must respect. It is the baseline
against which the phased split described in
`~/.claude/plans/fluffy-seeking-teapot.md` is executed.
## Composition
`Daemon` is a single struct aggregating state for every subsystem:
- Layout, config, store, runner, logger, pid — infrastructure handles.
- `mu sync.Mutex` — coarse lock, currently guards guest session controller
map mutations and image registry mutations.
- `vmLocks sync.Map` — per-VM `*sync.Mutex`, one per VM ID.
- `createOps`, `createOpsMu` — in-flight `vm create` operations.
- `imageBuildOps`, `imageBuildOpsMu` — in-flight `image build` operations.
- `tapPool`, `tapPoolNext`, `tapPoolMu` — TAP interface pool.
- `sessionControllers` — active guest session controllers (guarded by `mu`).
- `listener`, `webListener`, `webServer`, `webURL`, `vmDNS` — networking.
- `vmCaps` — registered VM capability hooks.
- `imageBuild`, `requestHandler`, `guestWaitForSSH`, `guestDial`,
`waitForGuestSessionReady` — injectable seams used by tests.
## Lock ordering
Acquire in this order, release in reverse. Never acquire in the opposite
direction.
```
vmLocks[id] → mu → {createOpsMu, imageBuildOpsMu, tapPoolMu}
```
Notes:
- `vmLocks[id]` is the outer lock for any operation scoped to a single VM.
Acquired via `withVMLockByID` / `withVMLockByRef`.
- `mu` is currently load-bearing for both session controller lookups and
image registry changes. Holding it while calling into guest SSH is
discouraged; prefer copying needed state out under the lock and releasing
before blocking I/O.
- The three subsystem locks (`createOpsMu`, `imageBuildOpsMu`, `tapPoolMu`)
are leaves. Nothing else is acquired while one is held.
The upcoming Phase 2 refactor will retire `mu` entirely by giving each
concern it currently guards its own owning type and lock. At that point
the ordering collapses to `vmLocks[id] → subsystem-local lock`.
## External API
Only `internal/cli` imports this package. The surface is:
- `daemon.Open(ctx) (*Daemon, error)`
- `(*Daemon).Serve(ctx) error`
- `(*Daemon).Close() error`
- `daemon.Doctor(...)` — host diagnostics (no receiver).
All other `*Daemon` methods are reached only through the RPC `dispatch`
switch in `daemon.go` and are free to move/rename during refactoring.