func (n *Node) createNodeEvals(nodeID string, nodeIndex uint64) ([]string, uint64, error) {
	// Snapshot the state
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return nil, 0, fmt.Errorf("failed to snapshot state: %v", err)
	}

	// Find all the allocations for this node
	ws := memdb.NewWatchSet()
	allocs, err := snap.AllocsByNode(ws, nodeID)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to find allocs for '%s': %v", nodeID, err)
	}

	sysJobsIter, err := snap.JobsByScheduler(ws, "system")
	if err != nil {
		return nil, 0, fmt.Errorf("failed to find system jobs for '%s': %v", nodeID, err)
	}

	var sysJobs []*structs.Job
	for job := sysJobsIter.Next(); job != nil; job = sysJobsIter.Next() {
		sysJobs = append(sysJobs, job.(*structs.Job))
	}

	// Fast-path if nothing to do
	if len(allocs) == 0 && len(sysJobs) == 0 {
		return nil, 0, nil
	}

	// Create an eval for each JobID affected
	var evals []*structs.Evaluation
	var evalIDs []string
	jobIDs := make(map[string]struct{})

	for _, alloc := range allocs {
		// Deduplicate on JobID
		if _, ok := jobIDs[alloc.JobID]; ok {
			continue
		}
		jobIDs[alloc.JobID] = struct{}{}

		// Create a new eval
		eval := &structs.Evaluation{
			ID:              structs.GenerateUUID(),
			Priority:        alloc.Job.Priority,
			Type:            alloc.Job.Type,
			TriggeredBy:     structs.EvalTriggerNodeUpdate,
			JobID:           alloc.JobID,
			NodeID:          nodeID,
			NodeModifyIndex: nodeIndex,
			Status:          structs.EvalStatusPending,
		}
		evals = append(evals, eval)
		evalIDs = append(evalIDs, eval.ID)
	}

	// Create an evaluation for each system job.
	for _, job := range sysJobs {
		// Still dedup on JobID as the node may already have the system job.
		if _, ok := jobIDs[job.ID]; ok {
			continue
		}
		jobIDs[job.ID] = struct{}{}

		// Create a new eval
		eval := &structs.Evaluation{
			ID:              structs.GenerateUUID(),
			Priority:        job.Priority,
			Type:            job.Type,
			TriggeredBy:     structs.EvalTriggerNodeUpdate,
			JobID:           job.ID,
			NodeID:          nodeID,
			NodeModifyIndex: nodeIndex,
			Status:          structs.EvalStatusPending,
		}
		evals = append(evals, eval)
		evalIDs = append(evalIDs, eval.ID)
	}

	// Create the Raft transaction
	update := &structs.EvalUpdateRequest{
		Evals:        evals,
		WriteRequest: structs.WriteRequest{Region: n.srv.config.Region},
	}

	// Commit this evaluation via Raft
	// XXX: There is a risk of partial failure where the node update succeeds
	// but that the EvalUpdate does not.
	_, evalIndex, err := n.srv.raftApply(structs.EvalUpdateRequestType, update)
	if err != nil {
		return nil, 0, err
	}
	return evalIDs, evalIndex, nil
}
// createNodeEvals is used to create evaluations for each alloc on a node.
// Each Eval is scoped to a job, so we need to potentially trigger many evals.
createNodeEvals is used to create evaluations for each alloc on a node.
Each Eval is scoped to a job, so we need to potentially trigger many evals.
// createNodeEvals is used to create evaluations for each alloc on a node . // Each Eval is scoped to a job so we need to potentially trigger many evals .
func (n *Node) createNodeEvals(nodeID string, nodeIndex uint64) ([]string, uint64, error) {
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return nil, 0, fmt.Errorf("failed to snapshot state: %v", err)
	}
	ws := memdb.NewWatchSet()
	allocs, err := snap.AllocsByNode(ws, nodeID)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to find allocs for '%s': %v", nodeID, err)
	}
	sysJobsIter, err := snap.JobsByScheduler(ws, "system")
	if err != nil {
		return nil, 0, fmt.Errorf("failed to find system jobs for '%s': %v", nodeID, err)
	}
	var sysJobs []*structs.Job
	for job := sysJobsIter.Next(); job != nil; job = sysJobsIter.Next() {
		sysJobs = append(sysJobs, job.(*structs.Job))
	}
	if len(allocs) == 0 && len(sysJobs) == 0 {
		return nil, 0, nil
	}
	var evals []*structs.Evaluation
	var evalIDs []string
	jobIDs := make(map[string]struct{})
	for _, alloc := range allocs {
		if _, ok := jobIDs[alloc.JobID]; ok {
			continue
		}
		jobIDs[alloc.JobID] = struct{}{}
		eval := &structs.Evaluation{
			ID:              structs.GenerateUUID(),
			Priority:        alloc.Job.Priority,
			Type:            alloc.Job.Type,
			TriggeredBy:     structs.EvalTriggerNodeUpdate,
			JobID:           alloc.JobID,
			NodeID:          nodeID,
			NodeModifyIndex: nodeIndex,
			Status:          structs.EvalStatusPending,
		}
		evals = append(evals, eval)
		evalIDs = append(evalIDs, eval.ID)
	}
	for _, job := range sysJobs {
		if _, ok := jobIDs[job.ID]; ok {
			continue
		}
		jobIDs[job.ID] = struct{}{}
		eval := &structs.Evaluation{
			ID:              structs.GenerateUUID(),
			Priority:        job.Priority,
			Type:            job.Type,
			TriggeredBy:     structs.EvalTriggerNodeUpdate,
			JobID:           job.ID,
			NodeID:          nodeID,
			NodeModifyIndex: nodeIndex,
			Status:          structs.EvalStatusPending,
		}
		evals = append(evals, eval)
		evalIDs = append(evalIDs, eval.ID)
	}
	update := &structs.EvalUpdateRequest{
		Evals:        evals,
		WriteRequest: structs.WriteRequest{Region: n.srv.config.Region},
	}
	_, evalIndex, err := n.srv.raftApply(structs.EvalUpdateRequestType, update)
	if err != nil {
		return nil, 0, err
	}
	return evalIDs, evalIndex, nil
}
func ( n * Node ) createNodeEvals ( nodeID string , nodeIndex uint64 ) ( [ ] string , uint64 , error ) { snap , err := n . srv . fsm . State ( ) . Snapshot ( ) if err != nil { return nil , 0 , fmt . Errorf ( " " , err ) } ws := memdb . NewWatchSet ( ) allocs , err := snap . AllocsByNode ( ws , nodeID ) if err != nil { return nil , 0 , fmt . Errorf ( " " , nodeID , err ) } sysJobsIter , err := snap . JobsByScheduler ( ws , " " ) if err != nil { return nil , 0 , fmt . Errorf ( " " , nodeID , err ) } var sysJobs [ ] * structs . Job for job := sysJobsIter . Next ( ) ; job != nil ; job = sysJobsIter . Next ( ) { sysJobs = append ( sysJobs , job . ( * structs . Job ) ) } if len ( allocs ) == 0 && len ( sysJobs ) == 0 { return nil , 0 , nil } var evals [ ] * structs . Evaluation var evalIDs [ ] string jobIDs := make ( map [ string ] struct { } ) for _ , alloc := range allocs { if _ , ok := jobIDs [ alloc . JobID ] ; ok { continue } jobIDs [ alloc . JobID ] = struct { } { } eval := & structs . Evaluation { ID : structs . GenerateUUID ( ) , Priority : alloc . Job . Priority , Type : alloc . Job . Type , TriggeredBy : structs . EvalTriggerNodeUpdate , JobID : alloc . JobID , NodeID : nodeID , NodeModifyIndex : nodeIndex , Status : structs . EvalStatusPending , } evals = append ( evals , eval ) evalIDs = append ( evalIDs , eval . ID ) } for _ , job := range sysJobs { if _ , ok := jobIDs [ job . ID ] ; ok { continue } jobIDs [ job . ID ] = struct { } { } eval := & structs . Evaluation { ID : structs . GenerateUUID ( ) , Priority : job . Priority , Type : job . Type , TriggeredBy : structs . EvalTriggerNodeUpdate , JobID : job . ID , NodeID : nodeID , NodeModifyIndex : nodeIndex , Status : structs . EvalStatusPending , } evals = append ( evals , eval ) evalIDs = append ( evalIDs , eval . ID ) } update := & structs . EvalUpdateRequest { Evals : evals , WriteRequest : structs . WriteRequest { Region : n . srv . config . Region } , } _ , evalIndex , err := n . srv . raftApply ( structs . EvalUpdateRequestType , update ) if err != nil { return nil , 0 , err } return evalIDs , evalIndex , nil }
createNodeEvals is used to create evaluations for each alloc on a node.
createNodeEvals is used to create evaluations for each alloc on a node .
// Snapshot the state // Find all the allocations for this node // Fast-path if nothing to do // Create an eval for each JobID affected // Deduplicate on JobID // Create a new eval // Create an evaluation for each system job. // Still dedup on JobID as the node may already have the system job. // Create a new eval // Create the Raft transaction // Commit this evaluation via Raft // XXX: There is a risk of partial failure where the node update succeeds // but that the EvalUpdate does not.