package agentsync import ( "sync" "time" "gitea.hostxtra.co.uk/vantage/vantage-shared/grpc/pb" ) // maxPendingResults bounds the results kept for a later stream. A host that // cannot reach the control plane for a very long time drops its oldest // results rather than growing without limit. const maxPendingResults = 32 // pendingResult is a PatchResult that could not be sent, with what the reboot // decision needs to be taken again when it finally can be. type pendingResult struct { msg *pb.AgentMessage requested bool // the command's RebootIfRequired deadline time.Time // the command's deadline, zero for a manual run } // resultQueue holds undelivered PatchResults until the next command stream. type resultQueue struct { mu sync.Mutex items []pendingResult max int } // push appends p, dropping the oldest entry when the queue is full. It // reports whether an entry was dropped. func (q *resultQueue) push(p pendingResult) bool { q.mu.Lock() defer q.mu.Unlock() q.items = append(q.items, p) if len(q.items) > q.max { q.items = q.items[len(q.items)-q.max:] return true } return false } // flush sends the queued results oldest first, removing each once sent. It // stops at the first failure and keeps that entry and everything after it // for the next stream. The lock is held throughout so two streams never // deliver the same result. func (q *resultQueue) flush(send func(pendingResult) error) { q.mu.Lock() defer q.mu.Unlock() for len(q.items) > 0 { if err := send(q.items[0]); err != nil { return } q.items = q.items[1:] } }