// asyncPlanWait is used to apply and respond to a plan async func (s *Server) asyncPlanWait(waitCh chan struct{}, future raft.ApplyFuture, result *structs.PlanResult, pending *pendingPlan) { defer metrics.MeasureSince([]string{"nomad", "plan", "apply"}, time.Now()) defer close(waitCh) // Wait for the plan to apply if err := future.Error(); err != nil { s.logger.Printf("[ERR] nomad: failed to apply plan: %v", err) pending.respond(nil, err) return } // Respond to the plan result.AllocIndex = future.Index() pending.respond(result, nil) }
// asyncPlanWait is used to apply and respond to a plan async func (s *Server) asyncPlanWait(waitCh chan struct{}, future raft.ApplyFuture, result *structs.PlanResult, pending *pendingPlan) { defer metrics.MeasureSince([]string{"nomad", "plan", "apply"}, time.Now()) defer close(waitCh) // Wait for the plan to apply if err := future.Error(); err != nil { s.logger.Printf("[ERR] nomad: failed to apply plan: %v", err) pending.respond(nil, err) return } // Respond to the plan result.AllocIndex = future.Index() // If this is a partial plan application, we need to ensure the scheduler // at least has visibility into any placements it made to avoid double placement. // The RefreshIndex computed by evaluatePlan may be stale due to evaluation // against an optimistic copy of the state. if result.RefreshIndex != 0 { result.RefreshIndex = maxUint64(result.RefreshIndex, result.AllocIndex) } pending.respond(result, nil) }
// planWaitFuture is used to wait for the Raft future to complete func planWaitFuture(future raft.ApplyFuture) (uint64, error) { if err := future.Error(); err != nil { return 0, err } return future.Index(), nil }