UpdateTasks keeps task records aligned with what is actually running. A worker inspects each running task’s Docker container and records failure or allocated ports; a manager periodically asks every worker for its tasks and reconciles its own records with those reports. This avoids fire-and-forget scheduling, where a dispatched task can fail without the manager learning its current state. section 7.3.3 section 9.4.2 section 7.5
On a worker, the private update routine follows a small state-refresh algorithm:
- List the locally stored tasks and consider only tasks marked Running. section 9.4.2 section 11.6
- Inspect each task’s ContainerID through the Docker daemon. section 9.4.2
- Mark the task Failed when its container is absent or has exited; otherwise retain the running record. section 9.4.2
- Store the container’s allocated host ports on the task so its runtime networking information is available. section 9.4.2
The manager treats workers as authoritative for task state. For every configured worker, it sends GET /tasks, checks connection and HTTP status, decodes the JSON task list, then updates a known task’s State, StartTime, FinishTime, and ContainerID. A reported task absent from the manager database is logged and stops that update pass. section 7.3.3
Listing 9.5 The worker’s new updateTasks method
func (w *Worker) updateTasks() {
for id, t := range w.Db {
if t.State == task.Running {
resp := w.InspectTask(*t)
if resp.Error != nil {
fmt.Printf("ERROR: %v\n", resp.Error)
}
if resp.Container == nil {
log.Printf("No container for running task %s\n", id)
w.Db[id].State = task.Failed
}
if resp.Container.State.Status == "exited" {
log.Printf("Container for task %s in non-running state %s",
id, resp.Container.State.Status)
w.Db[id].State = task.Failed
}
w.Db[id].HostPorts =
resp.Container.NetworkSettings.NetworkSettingsBase.Ports
}
}
}
This worker update routine makes the inspection-to-state-transition path explicit: inspect running containers, mark missing or exited ones failed, and persist host-port data. section 9.4.2
Run updates as a background loop
A public UpdateTasks wrapper can own the polling loop: log the check, call a private updateTasks routine, log completion, and sleep for 15 seconds. Moving this loop onto Manager or Worker removes the need for an anonymous goroutine at each call site. section 8.7 section 7.5
The polling interval is deliberately a simple observation aid rather than a production timing policy. The important separation is between a public long-running loop and a private single-pass routine, which also makes storage changes localized: later code lists tasks and persists updates through a Store interface instead of directly mutating a map. section 8.7 section 11.6
