github.com/hernad/nomad@v1.6.112/nomad/drainer/drainer_util.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package drainer 5 6 import ( 7 "github.com/hernad/nomad/nomad/structs" 8 ) 9 10 const ( 11 // defaultMaxIdsPerTxn is the maximum number of IDs that can be included in a 12 // single Raft transaction. This is to ensure that the Raft message 13 // does not become too large. 14 defaultMaxIdsPerTxn = (1024 * 256) / 36 // 0.25 MB of ids. 15 ) 16 17 // partitionIds takes a set of IDs and returns a partitioned view of them such 18 // that no batch would result in an overly large raft transaction. 19 func partitionIds(maxIds int, ids []string) [][]string { 20 index := 0 21 total := len(ids) 22 var partitions [][]string 23 for remaining := total - index; remaining > 0; remaining = total - index { 24 if remaining < maxIds { 25 partitions = append(partitions, ids[index:]) 26 break 27 } else { 28 partitions = append(partitions, ids[index:index+maxIds]) 29 index += maxIds 30 } 31 } 32 33 return partitions 34 } 35 36 // transitionTuple is used to group desired transitions and evals 37 type transitionTuple struct { 38 Transitions map[string]*structs.DesiredTransition 39 Evals []*structs.Evaluation 40 } 41 42 // partitionAllocDrain returns a list of alloc transitions and evals to apply 43 // in a single raft transaction.This is necessary to ensure that the Raft 44 // transaction does not become too large. 45 func partitionAllocDrain(maxIds int, transitions map[string]*structs.DesiredTransition, 46 evals []*structs.Evaluation) []*transitionTuple { 47 48 // Determine a stable ordering of the transitioning allocs 49 allocs := make([]string, 0, len(transitions)) 50 for id := range transitions { 51 allocs = append(allocs, id) 52 } 53 54 var requests []*transitionTuple 55 submittedEvals, submittedTrans := 0, 0 56 for submittedEvals != len(evals) || submittedTrans != len(transitions) { 57 req := &transitionTuple{ 58 Transitions: make(map[string]*structs.DesiredTransition), 59 } 60 requests = append(requests, req) 61 available := maxIds 62 63 // Add the allocs first 64 if remaining := len(allocs) - submittedTrans; remaining > 0 { 65 if remaining <= available { 66 for _, id := range allocs[submittedTrans:] { 67 req.Transitions[id] = transitions[id] 68 } 69 available -= remaining 70 submittedTrans += remaining 71 } else { 72 for _, id := range allocs[submittedTrans : submittedTrans+available] { 73 req.Transitions[id] = transitions[id] 74 } 75 submittedTrans += available 76 77 // Exhausted space so skip adding evals 78 continue 79 } 80 81 } 82 83 // Add the evals 84 if remaining := len(evals) - submittedEvals; remaining > 0 { 85 if remaining <= available { 86 req.Evals = evals[submittedEvals:] 87 submittedEvals += remaining 88 } else { 89 req.Evals = evals[submittedEvals : submittedEvals+available] 90 submittedEvals += available 91 } 92 } 93 } 94 95 return requests 96 }