daemon split (7/n): narrow capability interfaces, wire deps at construction
Stop passing *Daemon into capability hooks. Each capability
implementation is now a struct with explicit service-pointer fields
populated at wireServices time; the six dynamic-dispatch interfaces
(AddStartPreflight, PrepareHost, PostStart, Cleanup, ApplyConfigChange,
AddDoctorChecks) no longer have a *Daemon parameter. Capability
methods reach their dependencies through struct fields, not through
d.vm / d.ws / d.net.
- workDiskCapability carries {vm, ws, store, defaultImageName}
- dnsCapability carries {net}
- natCapability carries {vm, net, logger}
Daemon.defaultCapabilities() builds the production list from the
already-constructed services and is called from wireServices so
d.vmCaps is populated eagerly. Tests that preinstall d.vmCaps with
stubs still work — wireServices only overwrites an empty slice.
registeredCapabilities() is gone (every dispatch loop now reads
d.vmCaps directly). capabilities_test.go's testCapability fake drops
*Daemon from its method set to match the new interfaces.
This finishes the daemon service split: capability implementations
no longer reach through the composition root, there's no path back
to *Daemon from any service or capability, and test construction
goes through one explicit wireServices call instead of lazy getters.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
16702bd5e1
commit
9c73155e17
4 changed files with 143 additions and 90 deletions
|
|
@ -32,10 +32,10 @@ import (
|
|||
// services remain unexported within the package so nothing outside
|
||||
// the daemon can see them.
|
||||
//
|
||||
// Capability invocation still runs through Daemon because the hook
|
||||
// interfaces take *Daemon directly. VMService calls back via the
|
||||
// capHooks seam rather than holding a *Daemon pointer, to keep the
|
||||
// dependency graph acyclic.
|
||||
// Capability dispatch goes through the capHooks seam rather than a
|
||||
// *Daemon pointer, so VMService has no path back to the composition
|
||||
// root. Daemon.buildCapabilityHooks() populates the seam at wiring
|
||||
// time with the registered-capabilities loops from capabilities.go.
|
||||
type VMService struct {
|
||||
runner system.CommandRunner
|
||||
logger *slog.Logger
|
||||
|
|
@ -67,10 +67,11 @@ type VMService struct {
|
|||
guestWaitForSSH func(context.Context, string, string, time.Duration) error
|
||||
guestDial func(context.Context, string, string) (guestSSHClient, error)
|
||||
|
||||
// Capability hook dispatch. Capabilities themselves live on
|
||||
// *Daemon (their interface takes *Daemon as receiver); VMService
|
||||
// invokes them via these seams so it doesn't need a *Daemon
|
||||
// pointer.
|
||||
// Capability hook dispatch. VMService invokes capabilities via
|
||||
// these seams, populated by Daemon.buildCapabilityHooks() at
|
||||
// wiring time. Capability implementations themselves are
|
||||
// structs with explicit service-pointer fields (see capabilities.go);
|
||||
// VMService never reaches back to *Daemon.
|
||||
capHooks capabilityHooks
|
||||
|
||||
beginOperation func(name string, attrs ...any) *operationLog
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue