MCPcopy
hub / github.com/multica-ai/multica / Daemon

Struct Daemon

server/internal/daemon/daemon.go:153–240  ·  view source on GitHub ↗

Daemon is the local agent runtime that polls for and executes tasks.

Source from the content-addressed store, hash-verified

151
152// Daemon is the local agent runtime that polls for and executes tasks.
153type Daemon struct {
154 cfg Config
155 client *Client
156 repoCache repoCacheBackend
157 skillCache *SkillBundleCache
158 logger *slog.Logger
159
160 mu sync.Mutex
161 workspaces map[string]*workspaceState
162 runtimeIndex map[string]Runtime // runtimeID -> Runtime for provider lookups
163 // profileLaunchSpecs maps a custom runtime profile_id -> the absolute
164 // executable path plus fixed launch args resolved for that profile
165 // (MUL-3284). Populated in registerRuntimesForWorkspace when a profile's
166 // command resolves; read by runTask to launch the custom command for a
167 // claimed task. Guarded by mu.
168 profileLaunchSpecs map[string]profileLaunchSpec
169 reloading sync.Mutex // prevents concurrent workspace syncs
170 runtimeSet *runtimeSetWatcher // multi-subscriber pub/sub for runtime-set changes
171
172 versionsMu sync.RWMutex // guards agentVersions
173 agentVersions map[string]string // provider -> detected CLI version (set during registration)
174
175 wsHBMu sync.RWMutex // guards wsHBLastAck
176 wsHBLastAck map[string]time.Time // runtime_id -> last successful WS heartbeat ack timestamp
177
178 // reconcile fans out a "re-check server state now" signal to subscribers
179 // (watchTaskCancellation, workspaceSyncLoop) so the WS connect/reconnect
180 // path can shrink the 5s / 30s reconciliation gap to sub-second. See
181 // reconcile.go and runTaskWakeupConnection.
182 reconcile *reconcileBroadcaster
183
184 // runtimeGoneMu guards runtimeGoneInflight, reregisterNextAttempt, and
185 // reregisterLastCompletedAt. The state lets heartbeat / poller / WS-ack
186 // handlers converge on a single recovery path when they each detect that a
187 // runtime row was deleted server-side without three of them stampeding
188 // registerRuntimesForWorkspace.
189 runtimeGoneMu sync.Mutex
190 runtimeGoneInflight map[string]struct{} // runtime_id -> currently recovering
191 reregisterNextAttempt map[string]time.Time // workspace_id -> earliest time the next re-register attempt may run
192 reregisterLastCompletedAt map[string]time.Time // workspace_id -> wall-clock at which the last SUCCESSFUL re-register call returned (failures intentionally not stamped — see recordRegisterCompletion)
193
194 cancelFunc context.CancelFunc // set by Run(); called by triggerRestart
195 rootCtx context.Context // set by Run(); used by long-running recoveries that must survive per-runtime ctx cancellation
196 restartBinary string // non-empty after a successful update; path to the new binary
197 updating atomic.Bool // prevents concurrent update attempts
198 activeTasks atomic.Int64 // number of tasks currently in handleTask; exposed via /health
199 ready atomic.Bool // false until preflight completes; gates /health status (starting -> running)
200
201 // claimMu guards pauseClaims and claimsInFlight. It is held only for the
202 // microseconds it takes to make a decision; ClaimTask itself runs without
203 // the lock so a slow per-runtime claim cannot stall auto-update or any
204 // other poller.
205 //
206 // The pair is the auto-update path's barrier against the issue's
207 // requirement that "升级过程中如果有 task 进来,会延后升级而不是中断 task":
208 // runRuntimePoller refuses to call ClaimTask while pauseClaims is set, and
209 // tryAutoUpdate refuses to flip pauseClaims while any poller is mid-claim
210 // or any task is in handleTask. Together that closes the fetch-then-claim

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected