You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@yunikorn.apache.org by cc...@apache.org on 2024/06/25 21:03:12 UTC

(yunikorn-core) branch master updated: [YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)

This is an automated email from the ASF dual-hosted git repository.

ccondit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/yunikorn-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 87b1d7cf [YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)
87b1d7cf is described below

commit 87b1d7cf4d083fca75ea389ca025327b18bffd9a
Author: Craig Condit <cc...@apache.org>
AuthorDate: Tue Jun 25 16:02:58 2024 -0500

    [YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)
    
    Closes: #902
---
 pkg/scheduler/context.go                  |  18 +-
 pkg/scheduler/objects/allocation.go       |  92 ++--
 pkg/scheduler/objects/allocation_test.go  |  82 +++-
 pkg/scheduler/objects/application.go      | 135 +++---
 pkg/scheduler/objects/application_test.go |  92 ++--
 pkg/scheduler/objects/preemption.go       |   4 +-
 pkg/scheduler/objects/preemption_test.go  | 104 +++--
 pkg/scheduler/objects/queue.go            |  51 ++-
 pkg/scheduler/partition.go                |  72 +--
 pkg/scheduler/partition_test.go           | 711 +++++++++++++++---------------
 10 files changed, 708 insertions(+), 653 deletions(-)

diff --git a/pkg/scheduler/context.go b/pkg/scheduler/context.go
index 9fe37996..39715b44 100644
--- a/pkg/scheduler/context.go
+++ b/pkg/scheduler/context.go
@@ -130,22 +130,22 @@ func (cc *ClusterContext) schedule() bool {
 		}
 		// try reservations first
 		schedulingStart := time.Now()
-		alloc := psc.tryReservedAllocate()
-		if alloc == nil {
+		result := psc.tryReservedAllocate()
+		if result == nil {
 			// placeholder replacement second
-			alloc = psc.tryPlaceholderAllocate()
+			result = psc.tryPlaceholderAllocate()
 			// nothing reserved that can be allocated try normal allocate
-			if alloc == nil {
-				alloc = psc.tryAllocate()
+			if result == nil {
+				result = psc.tryAllocate()
 			}
 		}
-		if alloc != nil {
+		if result != nil {
 			metrics.GetSchedulerMetrics().ObserveSchedulingLatency(schedulingStart)
-			if alloc.GetResultType() == objects.Replaced {
+			if result.ResultType == objects.Replaced {
 				// communicate the removal to the RM
-				cc.notifyRMAllocationReleased(psc.RmID, psc.Name, []*objects.Allocation{alloc.GetRelease()}, si.TerminationType_PLACEHOLDER_REPLACED, "replacing allocationKey: "+alloc.GetAllocationKey())
+				cc.notifyRMAllocationReleased(psc.RmID, psc.Name, []*objects.Allocation{result.Allocation.GetRelease()}, si.TerminationType_PLACEHOLDER_REPLACED, "replacing allocationKey: "+result.Ask.GetAllocationKey())
 			} else {
-				cc.notifyRMNewAllocation(psc.RmID, alloc)
+				cc.notifyRMNewAllocation(psc.RmID, result.Allocation)
 			}
 			activity = true
 		}
diff --git a/pkg/scheduler/objects/allocation.go b/pkg/scheduler/objects/allocation.go
index f6a3c27a..ddbfe6bf 100644
--- a/pkg/scheduler/objects/allocation.go
+++ b/pkg/scheduler/objects/allocation.go
@@ -43,8 +43,27 @@ const (
 	Replaced
 )
 
-func (ar AllocationResultType) String() string {
-	return [...]string{"None", "Allocated", "AllocatedReserved", "Reserved", "Unreserved", "Replaced"}[ar]
+func (art AllocationResultType) String() string {
+	return [...]string{"None", "Allocated", "AllocatedReserved", "Reserved", "Unreserved", "Replaced"}[art]
+}
+
+type AllocationResult struct {
+	ResultType     AllocationResultType
+	NodeID         string
+	ReservedNodeID string
+	Ask            *AllocationAsk
+	Allocation     *Allocation
+}
+
+func (ar *AllocationResult) String() string {
+	if ar == nil {
+		return "nil allocation result"
+	}
+	allocationKey := ""
+	if ar.Ask != nil {
+		allocationKey = ar.Ask.GetAllocationKey()
+	}
+	return fmt.Sprintf("resultType=%s, nodeID=%s, reservedNodeID=%s, allocationKey=%s", ar.ResultType.String(), ar.NodeID, ar.ReservedNodeID, allocationKey)
 }
 
 type Allocation struct {
@@ -65,8 +84,6 @@ type Allocation struct {
 	bindTime              time.Time // the time this allocation was bound to a node
 	placeholderCreateTime time.Time
 	released              bool
-	reservedNodeID        string
-	resultType            AllocationResultType
 	release               *Allocation
 	preempted             bool
 	instType              string
@@ -87,22 +104,37 @@ func NewAllocation(nodeID string, ask *AllocationAsk) *Allocation {
 		allocatedResource: ask.GetAllocatedResource().Clone(),
 		taskGroupName:     ask.GetTaskGroup(),
 		placeholder:       ask.IsPlaceholder(),
-		resultType:        Allocated,
 	}
 }
 
-func newReservedAllocation(nodeID string, ask *AllocationAsk) *Allocation {
-	alloc := NewAllocation(nodeID, ask)
-	alloc.SetBindTime(time.Time{})
-	alloc.SetResultType(Reserved)
-	return alloc
+// newAllocatedAllocationResult creates a new allocation result for a new allocation.
+func newAllocatedAllocationResult(nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+	return newAllocationResultInternal(Allocated, nodeID, ask, alloc)
+}
+
+// newReservedAllocationResult creates a new allocation result for reserving a node.
+func newReservedAllocationResult(nodeID string, ask *AllocationAsk) *AllocationResult {
+	return newAllocationResultInternal(Reserved, nodeID, ask, nil)
 }
 
-func newUnreservedAllocation(nodeID string, ask *AllocationAsk) *Allocation {
-	alloc := NewAllocation(nodeID, ask)
-	alloc.SetBindTime(time.Time{})
-	alloc.SetResultType(Unreserved)
-	return alloc
+// newUnreservedAllocationResult creates a new allocation result for unreserving a node.
+func newUnreservedAllocationResult(nodeID string, ask *AllocationAsk) *AllocationResult {
+	return newAllocationResultInternal(Unreserved, nodeID, ask, nil)
+}
+
+// newReplacedAllocationResult create a new allocation result for replaced allocations.
+func newReplacedAllocationResult(nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+	return newAllocationResultInternal(Replaced, nodeID, ask, alloc)
+}
+
+// newAllocationResultInternal creates a new allocation result. It should not be called directly.
+func newAllocationResultInternal(resultType AllocationResultType, nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+	return &AllocationResult{
+		ResultType: resultType,
+		NodeID:     nodeID,
+		Ask:        ask,
+		Allocation: alloc,
+	}
 }
 
 // Create a new Allocation from a node recovered allocation.
@@ -179,7 +211,7 @@ func (a *Allocation) String() string {
 	}
 	a.RLock()
 	defer a.RUnlock()
-	return fmt.Sprintf("applicationID=%s, allocationKey=%s, Node=%s, resultType=%s", a.applicationID, a.allocationKey, a.nodeID, a.resultType.String())
+	return fmt.Sprintf("applicationID=%s, allocationKey=%s, Node=%s", a.applicationID, a.allocationKey, a.nodeID)
 }
 
 // GetAsk returns the ask associated with this allocation
@@ -277,20 +309,6 @@ func (a *Allocation) GetPriority() int32 {
 	return a.priority
 }
 
-// GetReservedNodeID gets the node this allocation is reserved for
-func (a *Allocation) GetReservedNodeID() string {
-	a.RLock()
-	defer a.RUnlock()
-	return a.reservedNodeID
-}
-
-// SetReservedNodeID sets the node this allocation is reserved for
-func (a *Allocation) SetReservedNodeID(reservedNodeID string) {
-	a.Lock()
-	defer a.Unlock()
-	a.reservedNodeID = reservedNodeID
-}
-
 // IsReleased returns the release status of the allocation
 func (a *Allocation) IsReleased() bool {
 	a.RLock()
@@ -310,20 +328,6 @@ func (a *Allocation) GetTagsClone() map[string]string {
 	return CloneAllocationTags(a.tags)
 }
 
-// GetResultType gets the result type of this allocation
-func (a *Allocation) GetResultType() AllocationResultType {
-	a.RLock()
-	defer a.RUnlock()
-	return a.resultType
-}
-
-// SetResultType sets the result type of this allocation
-func (a *Allocation) SetResultType(resultType AllocationResultType) {
-	a.Lock()
-	defer a.Unlock()
-	a.resultType = resultType
-}
-
 // GetRelease returns the associated release for this allocation
 func (a *Allocation) GetRelease() *Allocation {
 	a.RLock()
diff --git a/pkg/scheduler/objects/allocation_test.go b/pkg/scheduler/objects/allocation_test.go
index b7b26bb0..77f3c2c5 100644
--- a/pkg/scheduler/objects/allocation_test.go
+++ b/pkg/scheduler/objects/allocation_test.go
@@ -54,7 +54,6 @@ func TestNewAlloc(t *testing.T) {
 		t.Fatal("NewAllocation create failed while it should not")
 	}
 	assert.Equal(t, alloc.GetAllocationKey(), "ask-1")
-	assert.Equal(t, alloc.GetResultType(), Allocated, "New alloc should default to result type Allocated")
 	assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
 	assert.Assert(t, !alloc.IsPlaceholder(), "ask should not have been a placeholder")
 	assert.Equal(t, time.Now().Round(time.Second), alloc.GetCreateTime().Round(time.Second))
@@ -62,7 +61,7 @@ func TestNewAlloc(t *testing.T) {
 	alloc.SetInstanceType(instType1)
 	assert.Equal(t, alloc.GetInstanceType(), instType1, "Instance type not set as expected")
 	allocStr := alloc.String()
-	expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Allocated"
+	expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1"
 	assert.Equal(t, allocStr, expected, "Strings should have been equal")
 	assert.Assert(t, !alloc.IsPlaceholderUsed(), fmt.Sprintf("Alloc should not be placeholder replacement by default: got %t, expected %t", alloc.IsPlaceholderUsed(), false))
 	// check that createTime is properly copied from the ask
@@ -74,34 +73,77 @@ func TestNewAlloc(t *testing.T) {
 	assert.Equal(t, alloc.GetCreateTime(), ask.GetCreateTime(), "createTime was not copied from the ask")
 }
 
-func TestNewReservedAlloc(t *testing.T) {
+func TestNewAllocatedAllocationResult(t *testing.T) {
 	res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
 	assert.NilError(t, err, "Resource creation failed")
 	ask := newAllocationAsk("ask-1", "app-1", res)
-	alloc := newReservedAllocation("node-1", ask)
-	if alloc == nil {
-		t.Fatal("NewReservedAllocation create failed while it should not")
+	alloc := NewAllocation("node-1", ask)
+	result := newAllocatedAllocationResult("node-1", ask, alloc)
+	if result == nil {
+		t.Fatal("NewAllocatedAllocationResult create failed while it should not")
 	}
-	assert.Equal(t, alloc.GetResultType(), Reserved, "NewReservedAlloc should have Reserved result type")
-	assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
-	allocStr := alloc.String()
-	expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Reserved"
-	assert.Equal(t, allocStr, expected, "Strings should have been equal")
+	assert.Equal(t, result.ResultType, Allocated, "NewAllocatedAllocationResult should have Allocated result type")
+	assert.Equal(t, ask, result.Ask, "wrong ask")
+	assert.Equal(t, alloc, result.Allocation, "wrong allocation")
+	assert.Equal(t, result.NodeID, "node-1", "wrong node id")
 }
 
-func TestNewUnreservedAlloc(t *testing.T) {
+func TestNewReservedAllocationResult(t *testing.T) {
 	res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
 	assert.NilError(t, err, "Resource creation failed")
 	ask := newAllocationAsk("ask-1", "app-1", res)
-	alloc := newUnreservedAllocation("node-1", ask)
-	if alloc == nil {
-		t.Fatal("NewReservedAllocation create failed while it should not")
+	result := newReservedAllocationResult("node-1", ask)
+	if result == nil {
+		t.Fatal("NewReservedAllocationResult create failed while it should not")
 	}
-	assert.Equal(t, alloc.GetResultType(), Unreserved, "NewReservedAlloc should have Reserved result type")
-	assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
-	allocStr := alloc.String()
-	expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Unreserved"
-	assert.Equal(t, allocStr, expected, "Strings should have been equal")
+	assert.Equal(t, result.ResultType, Reserved, "NewReservedAllocationResult should have Reserved result type")
+	assert.Equal(t, ask, result.Ask, "wrong ask")
+	assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestNewUnreservedAllocationResult(t *testing.T) {
+	res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+	assert.NilError(t, err, "Resource creation failed")
+	ask := newAllocationAsk("ask-1", "app-1", res)
+	result := newUnreservedAllocationResult("node-1", ask)
+	if result == nil {
+		t.Fatal("NewReservedAllocationResult create failed while it should not")
+	}
+	assert.Equal(t, result.ResultType, Unreserved, "NewReservedAllocationResult should have Reserved result type")
+	assert.Equal(t, ask, result.Ask, "wrong ask")
+	assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestNewReplacedAllocationResult(t *testing.T) {
+	res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+	assert.NilError(t, err, "Resource creation failed")
+	ask := newAllocationAsk("ask-1", "app-1", res)
+	alloc := NewAllocation("node-1", ask)
+	result := newReplacedAllocationResult("node-1", ask, alloc)
+	if result == nil {
+		t.Fatal("NewReplacedllocationResult create failed while it should not")
+	}
+	assert.Equal(t, result.ResultType, Replaced, "NewReplacedAllocationResult should have Allocated result type")
+	assert.Equal(t, ask, result.Ask, "wrong ask")
+	assert.Equal(t, alloc, result.Allocation, "wrong allocation")
+	assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestAllocationResultString(t *testing.T) {
+	res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+	assert.NilError(t, err, "Resource creation failed")
+	ask := newAllocationAsk("ask-1", "app-1", res)
+	result := &AllocationResult{
+		ResultType:     Allocated,
+		NodeID:         "node-1",
+		ReservedNodeID: "node-2",
+		Ask:            ask,
+	}
+	assert.Equal(t, result.String(), "resultType=Allocated, nodeID=node-1, reservedNodeID=node-2, allocationKey=ask-1", "wrong content")
+
+	// validate nil ask
+	result.Ask = nil
+	assert.Equal(t, result.String(), "resultType=Allocated, nodeID=node-1, reservedNodeID=node-2, allocationKey=", "wrong content")
 }
 
 func TestSIFromNilAlloc(t *testing.T) {
diff --git a/pkg/scheduler/objects/application.go b/pkg/scheduler/objects/application.go
index 797c5d5a..e3325f57 100644
--- a/pkg/scheduler/objects/application.go
+++ b/pkg/scheduler/objects/application.go
@@ -946,7 +946,7 @@ func (sa *Application) canReplace(request *AllocationAsk) bool {
 }
 
 // tryAllocate will perform a regular allocation of a pending request, includes placeholders.
-func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption bool, preemptionDelay time.Duration, preemptAttemptsRemaining *int, nodeIterator func() NodeIterator, fullNodeIterator func() NodeIterator, getNodeFn func(string) *Node) *Allocation {
+func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption bool, preemptionDelay time.Duration, preemptAttemptsRemaining *int, nodeIterator func() NodeIterator, fullNodeIterator func() NodeIterator, getNodeFn func(string) *Node) *AllocationResult {
 	sa.Lock()
 	defer sa.Unlock()
 	if sa.sortedRequests == nil {
@@ -981,9 +981,9 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
 				*preemptAttemptsRemaining--
 				fullIterator := fullNodeIterator()
 				if fullIterator != nil {
-					if alloc, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, false); ok {
+					if result, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, false); ok {
 						// preemption occurred, and possibly reservation
-						return alloc
+						return result
 					}
 				}
 			}
@@ -1013,31 +1013,31 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
 					return nil
 				}
 			}
-			alloc := sa.tryNode(node, request)
-			if alloc != nil {
+			result := sa.tryNode(node, request)
+			if result != nil {
 				// check if the node was reserved and we allocated after a release
 				if _, ok := sa.reservations[reservationKey(node, nil, request)]; ok {
 					log.Log(log.SchedApplication).Debug("allocation on required node after release",
 						zap.String("appID", sa.ApplicationID),
 						zap.String("nodeID", requiredNode),
 						zap.String("allocationKey", request.GetAllocationKey()))
-					alloc.SetResultType(AllocatedReserved)
-					return alloc
+					result.ResultType = AllocatedReserved
+					return result
 				}
 				log.Log(log.SchedApplication).Debug("allocation on required node is completed",
 					zap.String("nodeID", node.NodeID),
 					zap.String("allocationKey", request.GetAllocationKey()),
-					zap.Stringer("resultType", alloc.GetResultType()))
-				return alloc
+					zap.Stringer("resultType", result.ResultType))
+				return result
 			}
-			return newReservedAllocation(node.NodeID, request)
+			return newReservedAllocationResult(node.NodeID, request)
 		}
 
 		iterator := nodeIterator()
 		if iterator != nil {
-			if alloc := sa.tryNodes(request, iterator); alloc != nil {
+			if result := sa.tryNodes(request, iterator); result != nil {
 				// have a candidate return it
-				return alloc
+				return result
 			}
 
 			// no nodes qualify, attempt preemption
@@ -1045,9 +1045,9 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
 				*preemptAttemptsRemaining--
 				fullIterator := fullNodeIterator()
 				if fullIterator != nil {
-					if alloc, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, true); ok {
+					if result, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, true); ok {
 						// preemption occurred, and possibly reservation
-						return alloc
+						return result
 					}
 				}
 			}
@@ -1106,7 +1106,7 @@ func (sa *Application) cancelReservations(reservations []*reservation) bool {
 // tryPlaceholderAllocate tries to replace a placeholder that is allocated with a real allocation
 //
 //nolint:funlen
-func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator, getNodeFn func(string) *Node) *Allocation {
+func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator, getNodeFn func(string) *Node) *AllocationResult {
 	sa.Lock()
 	defer sa.Unlock()
 	// nothing to do if we have no placeholders allocated
@@ -1164,7 +1164,8 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
 				alloc.SetRelease(ph)
 				// placeholder point to the real one in the releases list
 				ph.SetRelease(alloc)
-				alloc.SetResultType(Replaced)
+
+				result := newReplacedAllocationResult(node.NodeID, request, alloc)
 				// mark placeholder as released
 				ph.SetReleased(true)
 				_, err := sa.allocateAsk(request)
@@ -1172,7 +1173,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
 					log.Log(log.SchedApplication).Warn("allocation of ask failed unexpectedly",
 						zap.Error(err))
 				}
-				return alloc
+				return result
 			}
 		}
 	}
@@ -1183,7 +1184,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
 	}
 	// we checked all placeholders and asks nothing worked as yet
 	// pick the first fit and try all nodes if that fails give up
-	var allocResult *Allocation
+	var allocResult *AllocationResult
 	if phFit != nil && reqFit != nil {
 		iterator.ForEachNode(func(node *Node) bool {
 			if !node.IsSchedulable() {
@@ -1206,7 +1207,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
 			alloc.SetRelease(phFit)
 			// placeholder point to the real one in the releases list
 			phFit.SetRelease(alloc)
-			alloc.SetResultType(Replaced)
+			result := newReplacedAllocationResult(node.NodeID, reqFit, alloc)
 			// mark placeholder as released
 			phFit.SetReleased(true)
 			// update just the node to make sure we keep its spot
@@ -1224,7 +1225,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
 					zap.Error(err))
 			}
 
-			allocResult = alloc
+			allocResult = result
 			return false
 		})
 	}
@@ -1239,7 +1240,7 @@ func (sa *Application) checkHeadRooms(ask *AllocationAsk, userHeadroom *resource
 }
 
 // Try a reserved allocation of an outstanding reservation
-func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIterator func() NodeIterator) *Allocation {
+func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIterator func() NodeIterator) *AllocationResult {
 	sa.Lock()
 	defer sa.Unlock()
 	// calculate the users' headroom, includes group check which requires the applicationID
@@ -1262,8 +1263,7 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
 				unreserveAsk = ask
 			}
 			// remove the reservation as this should not be reserved
-			alloc := newUnreservedAllocation(reserve.nodeID, unreserveAsk)
-			return alloc
+			return newUnreservedAllocationResult(reserve.nodeID, unreserveAsk)
 		}
 
 		if !sa.checkHeadRooms(ask, userHeadroom, headRoom) {
@@ -1278,16 +1278,16 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
 			}
 		}
 		// check allocation possibility
-		alloc := sa.tryNode(reserve.node, ask)
+		result := sa.tryNode(reserve.node, ask)
 
 		// allocation worked fix the resultType and return
-		if alloc != nil {
-			alloc.SetResultType(AllocatedReserved)
-			return alloc
+		if result != nil {
+			result.ResultType = AllocatedReserved
+			return result
 		}
 	}
 
-	// lets try this on all other nodes
+	// try this on all other nodes
 	for _, reserve := range sa.reservations {
 		// Other nodes cannot be tried if the ask has a required node
 		ask := reserve.ask
@@ -1299,17 +1299,17 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
 			if !sa.checkHeadRooms(ask, userHeadroom, headRoom) {
 				continue
 			}
-			alloc := sa.tryNodesNoReserve(ask, iterator, reserve.nodeID)
+			result := sa.tryNodesNoReserve(ask, iterator, reserve.nodeID)
 			// have a candidate return it, including the node that was reserved
-			if alloc != nil {
-				return alloc
+			if result != nil {
+				return result
 			}
 		}
 	}
 	return nil
 }
 
-func (sa *Application) tryPreemption(headRoom *resources.Resource, preemptionDelay time.Duration, ask *AllocationAsk, iterator NodeIterator, nodesTried bool) (*Allocation, bool) {
+func (sa *Application) tryPreemption(headRoom *resources.Resource, preemptionDelay time.Duration, ask *AllocationAsk, iterator NodeIterator, nodesTried bool) (*AllocationResult, bool) {
 	preemptor := NewPreemptor(sa, headRoom, preemptionDelay, ask, iterator, nodesTried)
 
 	// validate prerequisites for preemption of an ask and mark ask for preemption if successful
@@ -1358,9 +1358,9 @@ func (sa *Application) tryRequiredNodePreemption(reserve *reservation, ask *Allo
 }
 
 // Try all the nodes for a reserved request that have not been tried yet.
-// This should never resultType in a reservation as the ask is already reserved
-func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterator, reservedNode string) *Allocation {
-	var allocResult *Allocation
+// This should never result in a reservation as the ask is already reserved
+func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterator, reservedNode string) *AllocationResult {
+	var allocResult *AllocationResult
 	iterator.ForEachNode(func(node *Node) bool {
 		if !node.IsSchedulable() {
 			log.Log(log.SchedApplication).Debug("skipping node for reserved ask as state is unschedulable",
@@ -1372,12 +1372,12 @@ func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterat
 		if !node.FitInNode(ask.GetAllocatedResource()) || node.NodeID == reservedNode {
 			return true
 		}
-		alloc := sa.tryNode(node, ask)
+		result := sa.tryNode(node, ask)
 		// allocation worked: update resultType and return
-		if alloc != nil {
-			alloc.SetReservedNodeID(reservedNode)
-			alloc.SetResultType(AllocatedReserved)
-			allocResult = alloc
+		if result != nil {
+			result.ResultType = AllocatedReserved
+			result.ReservedNodeID = reservedNode
+			allocResult = result
 			return false
 		}
 
@@ -1389,14 +1389,14 @@ func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterat
 
 // Try all the nodes for a request. The resultType is an allocation or reservation of a node.
 // New allocations can only be reserved after a delay.
-func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allocation {
+func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *AllocationResult {
 	var nodeToReserve *Node
 	scoreReserved := math.Inf(1)
 	// check if the ask is reserved or not
 	allocKey := ask.GetAllocationKey()
 	reservedAsks := sa.GetAskReservations(allocKey)
 	allowReserve := !ask.IsAllocated() && len(reservedAsks) == 0
-	var allocResult *Allocation
+	var allocResult *AllocationResult
 	iterator.ForEachNode(func(node *Node) bool {
 		// skip the node if the node is not valid for the ask
 		if !node.IsSchedulable() {
@@ -1410,9 +1410,9 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
 			return true
 		}
 		tryNodeStart := time.Now()
-		alloc := sa.tryNode(node, ask)
+		result := sa.tryNode(node, ask)
 		// allocation worked so return
-		if alloc != nil {
+		if result != nil {
 			metrics.GetSchedulerMetrics().ObserveTryNodeLatency(tryNodeStart)
 			// check if the node was reserved for this ask: if it is set the resultType and return
 			// NOTE: this is a safeguard as reserved nodes should never be part of the iterator
@@ -1422,8 +1422,8 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
 					zap.String("appID", sa.ApplicationID),
 					zap.String("nodeID", node.NodeID),
 					zap.String("allocationKey", allocKey))
-				alloc.SetResultType(AllocatedReserved)
-				allocResult = alloc
+				result.ResultType = AllocatedReserved
+				allocResult = result
 				return false
 			}
 			// we could also have a different node reserved for this ask if it has pick one of
@@ -1434,13 +1434,13 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
 					zap.String("appID", sa.ApplicationID),
 					zap.String("nodeID", nodeID),
 					zap.String("allocationKey", allocKey))
-				alloc.SetResultType(AllocatedReserved)
-				alloc.SetReservedNodeID(nodeID)
-				allocResult = alloc
+				result.ResultType = AllocatedReserved
+				result.ReservedNodeID = nodeID
+				allocResult = result
 				return false
 			}
 			// nothing reserved just return this as a normal alloc
-			allocResult = alloc
+			allocResult = result
 			return false
 		}
 		// nothing allocated should we look at a reservation?
@@ -1479,15 +1479,14 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
 			return nil
 		}
 		// return reservation allocation and mark it as a reservation
-		alloc := newReservedAllocation(nodeToReserve.NodeID, ask)
-		return alloc
+		return newReservedAllocationResult(nodeToReserve.NodeID, ask)
 	}
 	// ask does not fit, skip to next ask
 	return nil
 }
 
 // Try allocating on one specific node
-func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *Allocation {
+func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *AllocationResult {
 	toAllocate := ask.GetAllocatedResource()
 	// create the key for the reservation
 	if !node.preAllocateCheck(toAllocate, reservationKey(nil, sa, ask)) {
@@ -1516,8 +1515,9 @@ func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *Allocation {
 				zap.Error(err))
 		}
 		// all is OK, last update for the app
-		sa.addAllocationInternal(alloc)
-		return alloc
+		result := newAllocatedAllocationResult(node.NodeID, ask, alloc)
+		sa.addAllocationInternal(result.ResultType, alloc)
+		return result
 	}
 	return nil
 }
@@ -1616,17 +1616,17 @@ func (sa *Application) getAllRequestsInternal() []*AllocationAsk {
 }
 
 // Add a new Allocation to the application
-func (sa *Application) AddAllocation(info *Allocation) {
+func (sa *Application) AddAllocation(alloc *Allocation) {
 	sa.Lock()
 	defer sa.Unlock()
-	sa.addAllocationInternal(info)
+	sa.addAllocationInternal(Allocated, alloc)
 }
 
 // Add the Allocation to the application
 // No locking must be called while holding the lock
-func (sa *Application) addAllocationInternal(info *Allocation) {
+func (sa *Application) addAllocationInternal(allocType AllocationResultType, alloc *Allocation) {
 	// placeholder allocations do not progress the state of the app and are tracked in a separate total
-	if info.IsPlaceholder() {
+	if alloc.IsPlaceholder() {
 		// when we have the first placeholder allocation start the placeholder timer.
 		// It will start to use the resources only after the first allocation, so we will count the time from this point.
 		// Also this is the first stable point on the placeholder handling, what is easy to explain and troubleshoot
@@ -1637,8 +1637,8 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
 			sa.initPlaceholderTimer()
 		}
 		// User resource usage needs to be updated even during resource allocation happen for ph's itself even though state change would happen only after all ph allocation completes.
-		sa.incUserResourceUsage(info.GetAllocatedResource())
-		sa.allocatedPlaceholder = resources.Add(sa.allocatedPlaceholder, info.GetAllocatedResource())
+		sa.incUserResourceUsage(alloc.GetAllocatedResource())
+		sa.allocatedPlaceholder = resources.Add(sa.allocatedPlaceholder, alloc.GetAllocatedResource())
 		sa.maxAllocatedResource = resources.ComponentWiseMax(sa.allocatedPlaceholder, sa.maxAllocatedResource)
 
 		// If there are no more placeholder to allocate we should move state
@@ -1654,7 +1654,7 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
 		// already when the last placeholder was allocated
 		// special case COMPLETING: gang with only one placeholder moves to COMPLETING and causes orphaned
 		// allocations
-		if info.GetResultType() != Replaced || !resources.IsZero(sa.allocatedResource) || sa.IsCompleting() {
+		if allocType != Replaced || !resources.IsZero(sa.allocatedResource) || sa.IsCompleting() {
 			// progress the state based on where we are, we should never fail in this case
 			// keep track of a failure in log.
 			if err := sa.HandleApplicationEvent(RunApplication); err != nil {
@@ -1663,12 +1663,12 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
 					zap.Error(err))
 			}
 		}
-		sa.incUserResourceUsage(info.GetAllocatedResource())
-		sa.allocatedResource = resources.Add(sa.allocatedResource, info.GetAllocatedResource())
+		sa.incUserResourceUsage(alloc.GetAllocatedResource())
+		sa.allocatedResource = resources.Add(sa.allocatedResource, alloc.GetAllocatedResource())
 		sa.maxAllocatedResource = resources.ComponentWiseMax(sa.allocatedResource, sa.maxAllocatedResource)
 	}
-	sa.appEvents.sendNewAllocationEvent(info)
-	sa.allocations[info.GetAllocationKey()] = info
+	sa.appEvents.sendNewAllocationEvent(alloc)
+	sa.allocations[alloc.GetAllocationKey()] = alloc
 }
 
 // Increase user resource usage
@@ -1735,11 +1735,10 @@ func (sa *Application) ReplaceAllocation(allocationKey string) *Allocation {
 	alloc.SetPlaceholderUsed(true)
 	alloc.SetPlaceholderCreateTime(ph.GetCreateTime())
 	alloc.SetBindTime(time.Now())
-	sa.addAllocationInternal(alloc)
+	sa.addAllocationInternal(Replaced, alloc)
 	// order is important: clean up the allocation after adding it to the app
 	// we need the original Replaced allocation resultType.
 	alloc.ClearRelease()
-	alloc.SetResultType(Allocated)
 	if sa.placeholderData != nil {
 		sa.placeholderData[ph.GetTaskGroup()].Replaced++
 	}
diff --git a/pkg/scheduler/objects/application_test.go b/pkg/scheduler/objects/application_test.go
index 7ab670a5..6a942c29 100644
--- a/pkg/scheduler/objects/application_test.go
+++ b/pkg/scheduler/objects/application_test.go
@@ -960,7 +960,6 @@ func TestGangAllocChange(t *testing.T) {
 
 	// add a real alloc this should NOT trigger state update
 	alloc = newAllocation(appID1, nodeID1, res)
-	alloc.SetResultType(Replaced)
 	app.AddAllocation(alloc)
 	assert.Equal(t, len(app.GetAllAllocations()), 3)
 	assert.Assert(t, app.IsRunning(), "app should still be in running state")
@@ -968,7 +967,6 @@ func TestGangAllocChange(t *testing.T) {
 
 	// add a second real alloc this should NOT trigger state update
 	alloc = newAllocation(appID1, nodeID1, res)
-	alloc.SetResultType(Replaced)
 	app.AddAllocation(alloc)
 	assert.Equal(t, len(app.GetAllAllocations()), 4)
 	assert.Assert(t, app.IsRunning(), "app should still be in running state")
@@ -1271,7 +1269,6 @@ func TestReplaceAllocation(t *testing.T) {
 
 	// set the real one to replace the placeholder
 	realAlloc := newAllocation(appID1, nodeID1, res)
-	realAlloc.SetResultType(Replaced)
 	ph.SetRelease(realAlloc)
 	alloc = app.ReplaceAllocation(ph.GetAllocationKey())
 	assert.Equal(t, alloc, ph, "returned allocation is not the placeholder")
@@ -1290,27 +1287,6 @@ func TestReplaceAllocation(t *testing.T) {
 	app.addPlaceholderDataWithLocking(ph.GetAsk())
 	assert.Equal(t, app.placeholderData[""].Count, int64(3))
 	assertUserGroupResource(t, getTestUserGroup(), resources.Multiply(res, 2))
-
-	// set multiple real allocations to replace the placeholder
-	realAlloc = newAllocation(appID1, nodeID1, res)
-	realAlloc.SetResultType(Replaced)
-	ph.SetRelease(realAlloc)
-	realAllocNoAdd := newAllocation(appID1, nodeID1, res)
-	realAllocNoAdd.SetResultType(Replaced)
-	ph.SetRelease(realAlloc)
-	alloc = app.ReplaceAllocation(ph.GetAllocationKey())
-	assert.Equal(t, alloc, ph, "returned allocation is not the placeholder")
-	assert.Assert(t, resources.IsZero(app.allocatedPlaceholder), "real allocation counted as placeholder")
-	assert.Equal(t, app.placeholderData[""].Replaced, int64(2))
-	// after the second replace we have 2 real allocations
-	if !resources.Equals(app.allocatedResource, resources.Multiply(res, 2)) {
-		t.Fatalf("real allocation not updated as expected: got %s, expected %s", app.allocatedResource, resources.Multiply(res, 2))
-	}
-	assert.Equal(t, realAlloc.GetPlaceholderCreateTime(), ph.GetCreateTime(), "real allocation's placeholder create time not updated as expected: got %s, expected %s", realAlloc.GetPlaceholderCreateTime(), ph.GetCreateTime())
-	if _, ok := app.allocations["not-added"]; ok {
-		t.Fatalf("real allocation added which shouldn't have been added")
-	}
-	assertUserGroupResource(t, getTestUserGroup(), resources.Multiply(res, 2))
 }
 
 func TestReplaceAllocationTracking(t *testing.T) {
@@ -1345,21 +1321,18 @@ func TestReplaceAllocationTracking(t *testing.T) {
 
 	// replace placeholders
 	realAlloc1 := newAllocation(appID1, nodeID1, res)
-	realAlloc1.SetResultType(Replaced)
 	ph1.SetRelease(realAlloc1)
 	alloc1 := app.ReplaceAllocation(ph1.GetAllocationKey())
 	app.RemoveAllocation(ph1.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
 	assert.Equal(t, ph1.GetAllocationKey(), alloc1.GetAllocationKey())
 	assert.Equal(t, true, app.HasPlaceholderAllocation())
 	realAlloc2 := newAllocation(appID1, nodeID1, res)
-	realAlloc2.SetResultType(Replaced)
 	ph2.SetRelease(realAlloc2)
 	alloc2 := app.ReplaceAllocation(ph2.GetAllocationKey())
 	app.RemoveAllocation(ph2.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
 	assert.Equal(t, ph2.GetAllocationKey(), alloc2.GetAllocationKey())
 	assert.Equal(t, true, app.HasPlaceholderAllocation())
 	realAlloc3 := newAllocation(appID1, nodeID1, res)
-	realAlloc3.SetResultType(Replaced)
 	ph3.SetRelease(realAlloc3)
 	alloc3 := app.ReplaceAllocation(ph3.GetAllocationKey())
 	app.RemoveAllocation(ph3.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
@@ -1781,8 +1754,8 @@ func TestTryAllocateNoRequests(t *testing.T) {
 
 	app := newApplication(appID1, "default", "root.unknown")
 	preemptionAttemptsRemaining := 0
-	alloc := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Check(t, alloc == nil, "unexpected alloc")
+	result := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Check(t, result == nil, "unexpected result")
 }
 
 func TestTryAllocateFit(t *testing.T) {
@@ -1806,9 +1779,11 @@ func TestTryAllocateFit(t *testing.T) {
 	assert.NilError(t, err)
 
 	preemptionAttemptsRemaining := 0
-	alloc := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Assert(t, alloc != nil, "alloc expected")
-	assert.Equal(t, "node1", alloc.GetNodeID(), "wrong node")
+	result := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+
+	assert.Assert(t, result != nil, "alloc expected")
+	assert.Assert(t, result.Allocation != nil, "alloc expected")
+	assert.Equal(t, "node1", result.NodeID, "wrong node")
 }
 
 func TestTryAllocatePreemptQueue(t *testing.T) {
@@ -1848,20 +1823,24 @@ func TestTryAllocatePreemptQueue(t *testing.T) {
 
 	preemptionAttemptsRemaining := 10
 
-	alloc1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result1 != nil, "result1 expected")
+	alloc1 := result1.Allocation
 	assert.Assert(t, alloc1 != nil, "alloc1 expected")
-	alloc2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result2 != nil, "result2 expected")
+	alloc2 := result2.Allocation
 	assert.Assert(t, alloc2 != nil, "alloc2 expected")
 
 	// on first attempt, not enough time has passed
-	alloc3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Assert(t, alloc3 == nil, "alloc3 not expected")
+	result3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result3 == nil, "result3 not expected")
 	assert.Assert(t, !alloc2.IsPreempted(), "alloc2 should not have been preempted")
 
 	// pass the time and try again
 	ask3.createTime = ask3.createTime.Add(-30 * time.Second)
-	alloc3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Assert(t, alloc3 != nil && alloc3.resultType == Reserved, "alloc3 should be a reservation")
+	result3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result3 != nil && result3.Allocation == nil && result3.ResultType == Reserved, "alloc3 should be a reservation")
 	assert.Assert(t, alloc2.IsPreempted(), "alloc2 should have been preempted")
 }
 
@@ -1916,31 +1895,44 @@ func TestTryAllocatePreemptNode(t *testing.T) {
 	preemptionAttemptsRemaining := 10
 
 	// consume capacity with 'unlimited' app
-	alloc00 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 40}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result00 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 40}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result00 != nil, "result00 expected")
+	alloc00 := result00.Allocation
 	assert.Assert(t, alloc00 != nil, "alloc00 expected")
-	alloc01 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 39}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result01 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 39}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result01 != nil, "result01 expected")
+	alloc01 := result01.Allocation
 	assert.Assert(t, alloc01 != nil, "alloc01 expected")
 
 	// consume remainder of space but not quota
-	alloc1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 28}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 28}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result1 != nil, "result1 expected")
+	alloc1 := result1.Allocation
 	assert.Assert(t, alloc1 != nil, "alloc1 expected")
-	alloc2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 23}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	result2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 23}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result2 != nil, "result2 expected")
+	alloc2 := result2.Allocation
 	assert.Assert(t, alloc2 != nil, "alloc2 expected")
 
 	// on first attempt, should see a reservation since we're after the reservation timeout
 	ask3.createTime = ask3.createTime.Add(-10 * time.Second)
-	alloc3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Assert(t, alloc3 != nil, "alloc3 expected")
-	assert.Equal(t, "node1", alloc3.GetNodeID(), "wrong node assignment")
-	assert.Equal(t, Reserved, alloc3.GetResultType(), "expected reservation")
+	result3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result3 != nil, "result3 expected")
+	alloc3 := result3.Allocation
+	assert.Assert(t, alloc3 == nil, "alloc3 not expected")
+	assert.Equal(t, "node1", result3.NodeID, "wrong node assignment")
+	assert.Equal(t, Reserved, result3.ResultType, "expected reservation")
 	assert.Assert(t, !alloc2.IsPreempted(), "alloc2 should not have been preempted")
 	err = node1.Reserve(app2, ask3)
 	assert.NilError(t, err)
 
 	// pass the time and try again
 	ask3.createTime = ask3.createTime.Add(-30 * time.Second)
-	alloc3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
-	assert.Assert(t, alloc3 != nil, "alloc3 expected")
+	result3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+	assert.Assert(t, result3 != nil, "result3 expected")
+	assert.Equal(t, Reserved, result3.ResultType, "expected reservation")
+	alloc3 = result3.Allocation
+	assert.Assert(t, alloc3 == nil, "alloc3 not expected")
 	assert.Assert(t, alloc1.IsPreempted(), "alloc1 should have been preempted")
 }
 
@@ -2610,8 +2602,8 @@ func TestTryAllocateWithReservedHeadRoomChecking(t *testing.T) {
 	assert.NilError(t, err, "reservation should not have failed")
 
 	iter := getNodeIteratorFn(node1, node2)
-	alloc := app.tryReservedAllocate(headRoom, iter)
-	assert.Assert(t, alloc == nil, "Alloc is expected to be nil due to insufficient headroom")
+	result := app.tryReservedAllocate(headRoom, iter)
+	assert.Assert(t, result == nil, "result is expected to be nil due to insufficient headroom")
 }
 
 func TestUpdateRunnableStatus(t *testing.T) {
diff --git a/pkg/scheduler/objects/preemption.go b/pkg/scheduler/objects/preemption.go
index f006a0ed..d91dbe32 100644
--- a/pkg/scheduler/objects/preemption.go
+++ b/pkg/scheduler/objects/preemption.go
@@ -551,7 +551,7 @@ func (p *Preemptor) tryNodes() (string, []*Allocation, bool) {
 	return "", nil, false
 }
 
-func (p *Preemptor) TryPreemption() (*Allocation, bool) {
+func (p *Preemptor) TryPreemption() (*AllocationResult, bool) {
 	// validate that sufficient capacity can be freed
 	if !p.checkPreemptionQueueGuarantees() {
 		return nil, false
@@ -649,7 +649,7 @@ func (p *Preemptor) TryPreemption() (*Allocation, bool) {
 		zap.String("allocationKey", p.ask.GetAllocationKey()),
 		zap.String("nodeID", nodeID),
 		zap.Int("victimCount", len(victims)))
-	return newReservedAllocation(nodeID, p.ask), true
+	return newReservedAllocationResult(nodeID, p.ask), true
 }
 
 type predicateCheckResult struct {
diff --git a/pkg/scheduler/objects/preemption_test.go b/pkg/scheduler/objects/preemption_test.go
index bba1a9c2..d98de242 100644
--- a/pkg/scheduler/objects/preemption_test.go
+++ b/pkg/scheduler/objects/preemption_test.go
@@ -221,10 +221,11 @@ func TestTryPreemption(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
 	assert.Check(t, alloc1.IsPreempted(), "alloc1 not preempted")
 	assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
 }
@@ -283,10 +284,11 @@ func TestTryPreemptionOnNode(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID2, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID2, result.NodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
 }
@@ -344,10 +346,11 @@ func TestTryPreemptionOnQueue(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID2, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID2, result.NodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
 }
@@ -398,10 +401,9 @@ func TestTryPreemption_VictimsAvailable_InsufficientResource(t *testing.T) {
 	headRoom := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10, "pods": 3})
 	preemptor := NewPreemptor(app2, headRoom, 30*time.Second, ask3, iterator(), false)
 
-	alloc, ok := preemptor.TryPreemption()
-	var expectedAlloc *Allocation
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result == nil, "unexpected result")
 	assert.Equal(t, ok, false, "no victims found")
-	assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
 }
@@ -462,10 +464,9 @@ func TestTryPreemption_VictimsOnDifferentNodes_InsufficientResource(t *testing.T
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
-	var expectedAlloc *Allocation
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result == nil, "unexpected result")
 	assert.Equal(t, ok, false, "no victims found")
-	assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
 }
@@ -525,10 +526,9 @@ func TestTryPreemption_VictimsAvailableOnDifferentNodes(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
-	var expectedAlloc *Allocation
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result == nil, "unexpected result")
 	assert.Equal(t, ok, false, "no victims found")
-	assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
 }
@@ -606,10 +606,11 @@ func TestTryPreemption_OnQueue_VictimsOnDifferentNodes(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID2, alloc.nodeID, "wrong alloc")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID2, result.NodeID, "wrong alloc")
 	assert.Equal(t, nodeID1, alloc1.nodeID, "wrong node")
 	assert.Equal(t, nodeID2, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID2, alloc4.nodeID, "wrong node")
@@ -691,10 +692,11 @@ func TestTryPreemption_OnQueue_VictimsAvailable_LowerPriority(t *testing.T) {
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc1.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID2, alloc4.nodeID, "wrong node")
@@ -763,10 +765,11 @@ func TestTryPreemption_AskResTypesDifferent_GuaranteedSetOnPreemptorSide(t *test
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
@@ -831,10 +834,11 @@ func TestTryPreemption_OnNode_AskResTypesDifferent_GuaranteedSetOnPreemptorSide(
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
 	assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
@@ -929,11 +933,12 @@ func TestTryPreemption_AskResTypesDifferent_GuaranteedSetOnVictimAndPreemptorSid
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1029,11 +1034,12 @@ func TestTryPreemption_OnNode_AskResTypesDifferent_GuaranteedSetOnVictimAndPreem
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
 	assert.NilError(t, plugin.GetPredicateError())
+	assert.Assert(t, result != nil, "no result")
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1130,11 +1136,12 @@ func TestTryPreemption_AskResTypesSame_GuaranteedSetOnPreemptorSide(t *testing.T
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1230,11 +1237,12 @@ func TestTryPreemption_OnNode_AskResTypesSame_GuaranteedSetOnPreemptorSide(t *te
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1332,11 +1340,12 @@ func TestTryPreemption_AskResTypesSame_GuaranteedSetOnVictimAndPreemptorSides(t
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1433,11 +1442,12 @@ func TestTryPreemption_OnNode_AskResTypesSame_GuaranteedSetOnVictimAndPreemptorS
 	plugins.RegisterSchedulerPlugin(plugin)
 	defer plugins.UnregisterSchedulerPlugins()
 
-	alloc, ok := preemptor.TryPreemption()
+	result, ok := preemptor.TryPreemption()
+	assert.Assert(t, result != nil, "no result")
 	assert.NilError(t, plugin.GetPredicateError())
 	assert.Assert(t, ok, "no victims found")
-	assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
-	assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+	assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+	assert.Equal(t, nodeID1, result.NodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
 	assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
 	assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
diff --git a/pkg/scheduler/objects/queue.go b/pkg/scheduler/objects/queue.go
index ff4957e7..9960d01a 100644
--- a/pkg/scheduler/objects/queue.go
+++ b/pkg/scheduler/objects/queue.go
@@ -1324,7 +1324,7 @@ func (sq *Queue) canRunApp(appID string) bool {
 // resources are skipped.
 // Applications are sorted based on the application sortPolicy. Applications without pending resources are skipped.
 // Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() NodeIterator, getnode func(string) *Node, allowPreemption bool) *Allocation {
+func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() NodeIterator, getnode func(string) *Node, allowPreemption bool) *AllocationResult {
 	if sq.IsLeafQueue() {
 		// get the headroom
 		headRoom := sq.getHeadRoom()
@@ -1339,26 +1339,27 @@ func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() N
 			if app.IsAccepted() && (!runnableInQueue || !runnableByUserLimit) {
 				continue
 			}
-			alloc := app.tryAllocate(headRoom, allowPreemption, preemptionDelay, &preemptAttemptsRemaining, iterator, fullIterator, getnode)
-			if alloc != nil {
+			result := app.tryAllocate(headRoom, allowPreemption, preemptionDelay, &preemptAttemptsRemaining, iterator, fullIterator, getnode)
+			if result != nil {
 				log.Log(log.SchedQueue).Info("allocation found on queue",
 					zap.String("queueName", sq.QueuePath),
 					zap.String("appID", app.ApplicationID),
-					zap.Stringer("allocation", alloc))
+					zap.Stringer("resultType", result.ResultType),
+					zap.Stringer("allocation", result.Allocation))
 				// if the app is still in Accepted state we're allocating placeholders.
 				// we want to count these apps as running
 				if app.IsAccepted() {
 					sq.setAllocatingAccepted(app.ApplicationID)
 				}
-				return alloc
+				return result
 			}
 		}
 	} else {
 		// process the child queues (filters out queues without pending requests)
 		for _, child := range sq.sortQueues() {
-			alloc := child.TryAllocate(iterator, fullIterator, getnode, allowPreemption)
-			if alloc != nil {
-				return alloc
+			result := child.TryAllocate(iterator, fullIterator, getnode, allowPreemption)
+			if result != nil {
+				return result
 			}
 		}
 	}
@@ -1371,25 +1372,26 @@ func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() N
 // the configured queue sortPolicy. Queues without pending resources are skipped.
 // Applications are sorted based on the application sortPolicy. Applications without pending resources are skipped.
 // Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryPlaceholderAllocate(iterator func() NodeIterator, getnode func(string) *Node) *Allocation {
+func (sq *Queue) TryPlaceholderAllocate(iterator func() NodeIterator, getnode func(string) *Node) *AllocationResult {
 	if sq.IsLeafQueue() {
 		// process the apps (filters out app without pending requests)
 		for _, app := range sq.sortApplications(true) {
-			alloc := app.tryPlaceholderAllocate(iterator, getnode)
-			if alloc != nil {
+			result := app.tryPlaceholderAllocate(iterator, getnode)
+			if result != nil {
 				log.Log(log.SchedQueue).Info("allocation found on queue",
 					zap.String("queueName", sq.QueuePath),
 					zap.String("appID", app.ApplicationID),
-					zap.Stringer("allocation", alloc))
-				return alloc
+					zap.Stringer("resultType", result.ResultType),
+					zap.Stringer("allocation", result.Allocation))
+				return result
 			}
 		}
 	} else {
 		// process the child queues (filters out queues without pending requests)
 		for _, child := range sq.sortQueues() {
-			alloc := child.TryPlaceholderAllocate(iterator, getnode)
-			if alloc != nil {
-				return alloc
+			result := child.TryPlaceholderAllocate(iterator, getnode)
+			if result != nil {
+				return result
 			}
 		}
 	}
@@ -1420,7 +1422,7 @@ func (sq *Queue) GetQueueOutstandingRequests(total *[]*AllocationAsk) {
 // the configured queue sortPolicy. Queues without pending resources are skipped.
 // Applications are currently NOT sorted and are iterated over in a random order.
 // Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *Allocation {
+func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *AllocationResult {
 	if sq.IsLeafQueue() {
 		// skip if it has no reservations
 		reservedCopy := sq.GetReservedApps()
@@ -1444,28 +1446,29 @@ func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *Allocation {
 				if app.IsAccepted() && (!sq.canRunApp(appID) || !ugm.GetUserManager().CanRunApp(sq.QueuePath, appID, app.user)) {
 					continue
 				}
-				alloc := app.tryReservedAllocate(headRoom, iterator)
-				if alloc != nil {
+				result := app.tryReservedAllocate(headRoom, iterator)
+				if result != nil {
 					log.Log(log.SchedQueue).Info("reservation found for allocation found on queue",
 						zap.String("queueName", sq.QueuePath),
 						zap.String("appID", appID),
-						zap.Stringer("allocation", alloc),
+						zap.Stringer("resultType", result.ResultType),
+						zap.Stringer("allocation", result.Allocation),
 						zap.String("appStatus", app.CurrentState()))
 					// if the app is still in Accepted state we're allocating placeholders.
 					// we want to count these apps as running
 					if app.IsAccepted() {
 						sq.setAllocatingAccepted(app.ApplicationID)
 					}
-					return alloc
+					return result
 				}
 			}
 		}
 	} else {
 		// process the child queues (filters out queues that have no pending requests)
 		for _, child := range sq.sortQueues() {
-			alloc := child.TryReservedAllocate(iterator)
-			if alloc != nil {
-				return alloc
+			result := child.TryReservedAllocate(iterator)
+			if result != nil {
+				return result
 			}
 		}
 	}
diff --git a/pkg/scheduler/partition.go b/pkg/scheduler/partition.go
index 8ede0725..01e0f39a 100644
--- a/pkg/scheduler/partition.go
+++ b/pkg/scheduler/partition.go
@@ -829,22 +829,22 @@ func (pc *PartitionContext) calculateOutstandingRequests() []*objects.Allocation
 
 // Try regular allocation for the partition
 // Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryAllocate() *objects.AllocationResult {
 	if !resources.StrictlyGreaterThanZero(pc.root.GetPendingResource()) {
 		// nothing to do just return
 		return nil
 	}
 	// try allocating from the root down
-	alloc := pc.root.TryAllocate(pc.GetNodeIterator, pc.GetFullNodeIterator, pc.GetNode, pc.isPreemptionEnabled())
-	if alloc != nil {
-		return pc.allocate(alloc)
+	result := pc.root.TryAllocate(pc.GetNodeIterator, pc.GetFullNodeIterator, pc.GetNode, pc.isPreemptionEnabled())
+	if result != nil {
+		return pc.allocate(result)
 	}
 	return nil
 }
 
 // Try process reservations for the partition
 // Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryReservedAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryReservedAllocate() *objects.AllocationResult {
 	if pc.getReservationCount() == 0 {
 		return nil
 	}
@@ -853,16 +853,16 @@ func (pc *PartitionContext) tryReservedAllocate() *objects.Allocation {
 		return nil
 	}
 	// try allocating from the root down
-	alloc := pc.root.TryReservedAllocate(pc.GetNodeIterator)
-	if alloc != nil {
-		return pc.allocate(alloc)
+	result := pc.root.TryReservedAllocate(pc.GetNodeIterator)
+	if result != nil {
+		return pc.allocate(result)
 	}
 	return nil
 }
 
 // Try process placeholder for the partition
 // Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryPlaceholderAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryPlaceholderAllocate() *objects.AllocationResult {
 	if pc.getPhAllocationCount() == 0 {
 		return nil
 	}
@@ -871,23 +871,23 @@ func (pc *PartitionContext) tryPlaceholderAllocate() *objects.Allocation {
 		return nil
 	}
 	// try allocating from the root down
-	alloc := pc.root.TryPlaceholderAllocate(pc.GetNodeIterator, pc.GetNode)
-	if alloc != nil {
+	result := pc.root.TryPlaceholderAllocate(pc.GetNodeIterator, pc.GetNode)
+	if result != nil {
 		log.Log(log.SchedPartition).Info("scheduler replace placeholder processed",
-			zap.String("appID", alloc.GetApplicationID()),
-			zap.String("allocationKey", alloc.GetAllocationKey()),
-			zap.String("placeholder released allocationKey", alloc.GetRelease().GetAllocationKey()))
+			zap.String("appID", result.Ask.GetApplicationID()),
+			zap.String("allocationKey", result.Ask.GetAllocationKey()),
+			zap.String("placeholder released allocationKey", result.Allocation.GetRelease().GetAllocationKey()))
 		// pass the release back to the RM via the cluster context
-		return alloc
+		return result
 	}
 	return nil
 }
 
 // Process the allocation and make the left over changes in the partition.
 // NOTE: this is a lock free call. It must NOT be called holding the PartitionContext lock.
-func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocation {
+func (pc *PartitionContext) allocate(result *objects.AllocationResult) *objects.AllocationResult {
 	// find the app make sure it still exists
-	appID := alloc.GetApplicationID()
+	appID := result.Ask.GetApplicationID()
 	app := pc.getApplication(appID)
 	if app == nil {
 		log.Log(log.SchedPartition).Info("Application was removed while allocating",
@@ -898,12 +898,13 @@ func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocat
 	// if the node was passed in use that ID instead of the one from the allocation
 	// the node ID is set when a reservation is allocated on a non-reserved node
 	var nodeID string
-	if alloc.GetReservedNodeID() == "" {
-		nodeID = alloc.GetNodeID()
+	alloc := result.Allocation
+	if alloc == nil || result.ReservedNodeID == "" {
+		nodeID = result.NodeID
 	} else {
-		nodeID = alloc.GetReservedNodeID()
+		nodeID = result.ReservedNodeID
 		log.Log(log.SchedPartition).Debug("Reservation allocated on different node",
-			zap.String("current node", alloc.GetNodeID()),
+			zap.String("current node", result.NodeID),
 			zap.String("reserved node", nodeID),
 			zap.String("appID", appID))
 	}
@@ -914,36 +915,37 @@ func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocat
 			zap.String("appID", appID))
 		return nil
 	}
-	alloc.SetInstanceType(node.GetInstanceType())
 	// reservation
-	if alloc.GetResultType() == objects.Reserved {
-		pc.reserve(app, node, alloc.GetAsk())
+	if result.ResultType == objects.Reserved {
+		pc.reserve(app, node, result.Ask)
 		return nil
 	}
 	// unreserve
-	if alloc.GetResultType() == objects.Unreserved || alloc.GetResultType() == objects.AllocatedReserved {
-		pc.unReserve(app, node, alloc.GetAsk())
-		if alloc.GetResultType() == objects.Unreserved {
+	if result.ResultType == objects.Unreserved || result.ResultType == objects.AllocatedReserved {
+		pc.unReserve(app, node, result.Ask)
+		if result.ResultType == objects.Unreserved {
 			return nil
 		}
 		// remove the link to the reserved node
-		alloc.SetReservedNodeID("")
+		result.ReservedNodeID = ""
 	}
 
+	alloc.SetInstanceType(node.GetInstanceType())
+
 	// track the number of allocations
 	pc.updateAllocationCount(1)
-	if alloc.IsPlaceholder() {
+	if result.Ask.IsPlaceholder() {
 		pc.incPhAllocationCount()
 	}
 
 	log.Log(log.SchedPartition).Info("scheduler allocation processed",
-		zap.String("appID", alloc.GetApplicationID()),
-		zap.String("allocationKey", alloc.GetAllocationKey()),
-		zap.Stringer("allocatedResource", alloc.GetAllocatedResource()),
-		zap.Bool("placeholder", alloc.IsPlaceholder()),
+		zap.String("appID", result.Ask.GetApplicationID()),
+		zap.String("allocationKey", result.Ask.GetAllocationKey()),
+		zap.Stringer("allocatedResource", result.Ask.GetAllocatedResource()),
+		zap.Bool("placeholder", result.Ask.IsPlaceholder()),
 		zap.String("targetNode", alloc.GetNodeID()))
-	// pass the allocation back to the RM via the cluster context
-	return alloc
+	// pass the allocation result back to the RM via the cluster context
+	return result
 }
 
 // Process the reservation in the scheduler
diff --git a/pkg/scheduler/partition_test.go b/pkg/scheduler/partition_test.go
index 003a0387..7a014c4a 100644
--- a/pkg/scheduler/partition_test.go
+++ b/pkg/scheduler/partition_test.go
@@ -374,7 +374,6 @@ func TestRemoveNodeWithPlaceholders(t *testing.T) {
 	alloc.SetRelease(ph)
 	// double link as if the replacement is ongoing
 	ph.SetRelease(alloc)
-	alloc.SetResultType(objects.Replaced)
 
 	allocs = app.GetAllAllocations()
 	assert.Equal(t, len(allocs), 1, "expected one allocation for the app (placeholder)")
@@ -488,8 +487,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
 		err = gangApp.AddAllocationAsk(ask)
 		assert.NilError(t, err, "failed to add placeholder ask %s to app1", lastPh)
 		// try to allocate a placeholder via normal allocate
-		ph := partition.tryAllocate()
-		assert.Assert(t, ph != nil, "expected placeholder to be allocated")
+		result := partition.tryAllocate()
+		assert.Assert(t, result != nil && result.Allocation != nil, "expected placeholder to be allocated")
 	}
 	assert.Equal(t, 7, partition.GetTotalAllocationCount(), "placeholder allocation should be counted as normal allocations on the partition")
 	assert.Equal(t, 6, partition.getPhAllocationCount(), "placeholder allocations should be counted as placeholders on the partition")
@@ -511,8 +510,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-2 to app1-1")
 
 	// since node-2 available resource is less than needed, reserve the node
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result := partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation attempt should not have returned an allocation")
 	}
 	// check if updated (must be after allocate call)
@@ -520,8 +519,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
 	assert.Equal(t, 1, len(app2.GetAskReservations(allocKey2)), "ask should have been reserved")
 
 	// try through reserved scheduling cycle this should trigger preemption
-	alloc = partition.tryReservedAllocate()
-	if alloc != nil {
+	result = partition.tryReservedAllocate()
+	if result != nil {
 		t.Fatal("reserved allocation attempt should not have returned an allocation")
 	}
 
@@ -612,8 +611,8 @@ func TestPlaceholderDataWithNodeRemoval(t *testing.T) {
 		err = gangApp.AddAllocationAsk(ask)
 		assert.NilError(t, err, "failed to add placeholder ask ph-1 to app1")
 		// try to allocate a placeholder via normal allocate
-		ph := partition.tryAllocate()
-		if ph == nil {
+		result := partition.tryAllocate()
+		if result == nil || result.Allocation == nil {
 			t.Fatal("expected placeholder to be allocated")
 		}
 	}
@@ -696,11 +695,11 @@ func TestPlaceholderDataWithRemoval(t *testing.T) {
 		err = gangApp.AddAllocationAsk(ask)
 		assert.NilError(t, err, "failed to add placeholder ask ph-1 to app1")
 		// try to allocate a placeholder via normal allocate
-		ph := partition.tryAllocate()
-		if ph == nil {
+		result := partition.tryAllocate()
+		if result == nil || result.Allocation == nil {
 			t.Fatal("expected placeholder to be allocated")
 		}
-		lastPhAllocationKey = ph.GetAllocationKey()
+		lastPhAllocationKey = result.Allocation.GetAllocationKey()
 	}
 
 	// add an ask for a last placeholder and allocate
@@ -774,7 +773,6 @@ func TestRemoveNodeWithReplacement(t *testing.T) {
 	// add real allocation that is replacing the placeholder on the 2nd node
 	alloc := objects.NewAllocation(nodeID2, ask)
 	alloc.SetRelease(ph)
-	alloc.SetResultType(objects.Replaced)
 	node2.AddAllocation(alloc)
 	allocated = node2.GetAllAllocations()
 	assert.Equal(t, 1, len(allocated), "allocation not added correctly to node2")
@@ -801,7 +799,6 @@ func TestRemoveNodeWithReplacement(t *testing.T) {
 	allocs = app.GetAllAllocations()
 	assert.Equal(t, 1, len(allocs), "expected one allocation for the app (real)")
 	assert.Equal(t, alloc.GetAllocationKey(), allocs[0].GetAllocationKey(), "allocationKey for the app is not the same as the real allocation")
-	assert.Equal(t, objects.Allocated, allocs[0].GetResultType(), "allocation result type should be allocated")
 	assert.Check(t, !allocs[0].HasRelease(), "real allocation should not have release liked anymore")
 	assertLimits(t, getTestUserGroup(), appRes)
 }
@@ -846,7 +843,6 @@ func TestRemoveNodeWithReal(t *testing.T) {
 	// add real allocation that is replacing the placeholder on the 2nd node
 	alloc := objects.NewAllocation(nodeID2, ask)
 	alloc.SetRelease(ph)
-	alloc.SetResultType(objects.Replaced)
 	node2.AddAllocation(alloc)
 	allocated = node2.GetAllAllocations()
 	assert.Equal(t, 1, len(allocated), "allocation not added correctly to node2")
@@ -1535,8 +1531,8 @@ func TestTryAllocate(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// create a set of queues and apps: app-1 2 asks; app-2 1 ask (same size)
@@ -1573,36 +1569,36 @@ func TestTryAllocate(t *testing.T) {
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), nil, expectedQueuesMaxLimits)
 
 	// first allocation should be app-1 and alloc-2
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 1), expectedQueuesMaxLimits)
 
 	// second allocation should be app-2 and alloc-1: higher up in the queue hierarchy
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID2, "expected application app-2 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID2, "expected application app-2 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 2), expectedQueuesMaxLimits)
 
 	// third allocation should be app-1 and alloc-1
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 	assert.Assert(t, resources.IsZero(partition.root.GetPendingResource()), "pending resources should be set to zero")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 3), expectedQueuesMaxLimits)
 }
@@ -1614,8 +1610,8 @@ func TestRequiredNodeReservation(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	app := newApplication(appID1, "default", "root.parent.sub-leaf")
@@ -1632,23 +1628,23 @@ func TestRequiredNodeReservation(t *testing.T) {
 	assertLimits(t, getTestUserGroup(), nil)
 
 	// first allocation should be app-1 and alloc-1
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 	assertLimits(t, getTestUserGroup(), res)
 
 	ask2 := newAllocationAsk(allocKey2, appID1, res)
 	ask2.SetRequiredNode(nodeID1)
 	err = app.AddAllocationAsk(ask2)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
-	alloc = partition.tryAllocate()
-	if alloc != nil {
-		t.Fatal("allocation attempt should have returned an allocation")
+	result = partition.tryAllocate()
+	if result != nil {
+		t.Fatal("allocation attempt should not have returned an allocation")
 	}
 	// check if updated (must be after allocate call)
 	assert.Equal(t, 1, len(app.GetReservations()), "app should have one reserved ask")
@@ -1664,8 +1660,8 @@ func TestRequiredNodeReservation(t *testing.T) {
 	ask3.SetRequiredNode(nodeID1)
 	err = app.AddAllocationAsk(ask3)
 	assert.NilError(t, err, "failed to add ask alloc-3 to app-1")
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation attempt should not have returned an allocation")
 	}
 
@@ -1680,8 +1676,8 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// override the reservation delay, and cleanup when done
@@ -1712,15 +1708,15 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
 	assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
 
 	// the first one should be allocated
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("1st allocation did not return the correct allocation")
 	}
-	assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+	assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
 
 	// the second one should be reserved as the 2nd node is not scheduling
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("2nd allocation did not return the correct allocation")
 	}
 	// check if updated (must be after allocate call)
@@ -1741,11 +1737,11 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
 	err = app1.AddAllocationAsk(ask2)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("1st allocation did not return the correct allocation")
 	}
-	assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+	assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
 
 	// earlier app (app1) reservation count should be zero
 	assert.Equal(t, 0, len(app.GetReservations()), "ask should have been reserved")
@@ -1758,8 +1754,8 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// override the reservation delay, and cleanup when done
@@ -1792,15 +1788,15 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
 	assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
 
 	// the first one should be allocated
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("1st allocation did not return the correct allocation")
 	}
-	assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+	assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
 
 	// the second one should be reserved as the 2nd node is not scheduling
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("2nd allocation should not return allocation")
 	}
 	// check if updated (must be after allocate call)
@@ -1821,8 +1817,8 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
 	err = app1.AddAllocationAsk(ask2)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("3rd allocation should not return allocation")
 	}
 	// still reservation count is 1
@@ -1836,8 +1832,8 @@ func TestRequiredNodeNotExist(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// add app to the partition
@@ -1860,8 +1856,8 @@ func TestRequiredNodeNotExist(t *testing.T) {
 			t.Fatal("panic on nil required node")
 		}
 	}()
-	alloc := partition.tryAllocate()
-	if alloc != nil {
+	result := partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation should not have worked on unknown node")
 	}
 	assertLimits(t, getTestUserGroup(), nil)
@@ -1873,8 +1869,8 @@ func TestRequiredNodeAllocation(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result.Allocation.String())
 	}
 
 	app := newApplication(appID1, "default", "root.parent.sub-leaf")
@@ -1891,14 +1887,14 @@ func TestRequiredNodeAllocation(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
 	// first allocation should be app-1 and alloc-1
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 	assertLimits(t, getTestUserGroup(), res)
 
 	// required node set on ask
@@ -1908,14 +1904,14 @@ func TestRequiredNodeAllocation(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 
 	// since node-1 available resource is larger than required ask gets allocated
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
 	// ensure there is no reservations
 	assert.Equal(t, 0, len(app.GetReservations()), "ask should not have been reserved")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
 	assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
 }
 
@@ -1955,8 +1951,8 @@ func TestPreemption(t *testing.T) {
 	time.Sleep(time.Second)
 
 	// third allocation should not succeed, as we are currently above capacity
-	alloc := partition.tryAllocate()
-	if alloc != nil {
+	result := partition.tryAllocate()
+	if result != nil {
 		t.Fatal("unexpected allocation")
 	}
 
@@ -1966,8 +1962,8 @@ func TestPreemption(t *testing.T) {
 
 	// allocation should still not do anything as we have not yet released the preempted allocation
 	// but the ask should have a reservation
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("unexpected allocation")
 	}
 
@@ -1989,13 +1985,13 @@ func TestPreemption(t *testing.T) {
 	assert.Assert(t, resources.IsZero(preemptingRes), "incorrect preempting resources")
 
 	// allocation should now allocate
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("missing allocation")
 	}
 	assert.Equal(t, 0, len(app2.GetReservations()), "ask should not be reserved")
-	assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type should be allocated from reservation")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey3, "expected ask alloc-3 to be allocated")
+	assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type should be allocated from reservation")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey3, "expected ask alloc-3 to be allocated")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}), getExpectedQueuesLimitsForPreemption())
 
 	appSummary := app1.GetApplicationSummary("default")
@@ -2011,9 +2007,9 @@ func TestPreemptionForRequiredNodeNormalAlloc(t *testing.T) {
 	// setup the partition so we can try the real allocation
 	partition, app := setupPreemptionForRequiredNode(t)
 	// now try the allocation again: the normal path
-	alloc := partition.tryAllocate()
-	if alloc != nil {
-		t.Fatal("allocations should not have returned an allocation")
+	result := partition.tryAllocate()
+	if result != nil {
+		t.Fatal("allocations should not have returned a result")
 	}
 	// check if updated (must be after allocate call)
 	assert.Equal(t, 1, len(app.GetReservations()), "ask should have been reserved")
@@ -2025,15 +2021,15 @@ func TestPreemptionForRequiredNodeReservedAlloc(t *testing.T) {
 	// setup the partition so we can try the real allocation
 	partition, app := setupPreemptionForRequiredNode(t)
 	// now try the allocation again: the reserved path
-	alloc := partition.tryReservedAllocate()
-	if alloc == nil {
+	result := partition.tryReservedAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation attempt should have returned an allocation")
 	}
 	// check if updated (must be after allocate call)
 	assert.Equal(t, 0, len(app.GetReservations()), "ask should have no longer be reserved")
-	assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected AllocatedReserved")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected AllocatedReserved")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemption())
 }
 
@@ -2057,7 +2053,9 @@ func TestPreemptionForRequiredNodeMultipleAttemptsAvoided(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
 	// first allocation should be app-1 and alloc-1
-	alloc := partition.tryAllocate()
+	result := partition.tryAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "alloc expected")
+	alloc := result.Allocation
 
 	// required node set on ask
 	ask2 := newAllocationAsk(allocKey2, appID1, res)
@@ -2122,8 +2120,8 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	app1, _ := newApplicationWithHandler(appID1, "default", "root.parent.leaf1")
@@ -2140,15 +2138,15 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
 	// first allocation should be app-1 and alloc-1
-	alloc1 := partition.tryAllocate()
-	if alloc1 == nil {
+	result1 := partition.tryAllocate()
+	if result1 == nil || result1.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc1.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc1.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc1.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc1.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
-	assert.Equal(t, alloc1.GetNodeID(), nodeID1, "expected alloc-1 on node-1")
+	assert.Equal(t, result1.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result1.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result1.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result1.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result1.NodeID, nodeID1, "expected alloc-1 on node-1")
 
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 5000}), getExpectedQueuesLimitsForPreemption())
 
@@ -2158,15 +2156,15 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 
 	// second allocation should be app-1 and alloc-2
-	alloc2 := partition.tryAllocate()
-	if alloc2 == nil {
+	result2 := partition.tryAllocate()
+	if result2 == nil || result2.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc2.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc2.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc2.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc2.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
-	assert.Equal(t, alloc2.GetNodeID(), nodeID2, "expected alloc-2 on node-2")
+	assert.Equal(t, result2.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result2.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result2.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result2.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result2.NodeID, nodeID2, "expected alloc-2 on node-2")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}), getExpectedQueuesLimitsForPreemption())
 
 	app2, _ := newApplicationWithHandler(appID2, "default", "root.parent.leaf2")
@@ -2175,7 +2173,7 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
 	err = partition.AddApplication(app2)
 	assert.NilError(t, err, "failed to add app-1 to partition")
 
-	return partition, app1, app2, alloc1, alloc2
+	return partition, app1, app2, result1.Allocation, result2.Allocation
 }
 
 // setup the partition in a state that we need for multiple tests
@@ -2184,8 +2182,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	app, testHandler := newApplicationWithHandler(appID1, "default", "root.parent.sub-leaf")
@@ -2202,16 +2200,16 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
 	// first allocation should be app-1 and alloc-1
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemptionWithRequiredNode())
-	allocationKey := alloc.GetAllocationKey()
+	allocationKey := result.Allocation.GetAllocationKey()
 
 	// required node set on ask
 	ask2 := newAllocationAsk(allocKey2, appID1, res)
@@ -2220,8 +2218,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 
 	// since node-1 available resource is less than needed, reserve the node for alloc-2
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation attempt should not have returned an allocation")
 	}
 	// check if updated (must be after allocate call)
@@ -2230,8 +2228,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
 	assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemptionWithRequiredNode())
 
 	// try through reserved scheduling cycle this should trigger preemption
-	alloc = partition.tryReservedAllocate()
-	if alloc != nil {
+	result = partition.tryReservedAllocate()
+	if result != nil {
 		t.Fatal("reserved allocation attempt should not have returned an allocation")
 	}
 
@@ -2263,8 +2261,8 @@ func TestTryAllocateLarge(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// override the reservation delay, and cleanup when done
@@ -2282,9 +2280,9 @@ func TestTryAllocateLarge(t *testing.T) {
 	err = app.AddAllocationAsk(newAllocationAsk("alloc-1", appID1, res))
 	assert.NilError(t, err, "failed to add large ask to app")
 	assert.Assert(t, resources.Equals(res, app.GetPendingResource()), "pending resource not set as expected")
-	alloc := partition.tryAllocate()
-	if alloc != nil {
-		t.Fatalf("allocation did return allocation which does not fit: %s", alloc)
+	result := partition.tryAllocate()
+	if result != nil {
+		t.Fatalf("allocation returned unexpected result: %s", result)
 	}
 	assert.Equal(t, 0, len(app.GetReservations()), "ask should not have been reserved")
 	assertLimits(t, getTestUserGroup(), nil)
@@ -2296,8 +2294,8 @@ func TestAllocReserveNewNode(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned result: %s", result)
 	}
 
 	// override the reservation delay, and cleanup when done
@@ -2328,16 +2326,16 @@ func TestAllocReserveNewNode(t *testing.T) {
 	assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
 
 	// the first one should be allocated
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("1st allocation did not return the correct allocation")
 	}
-	assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+	assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}))
 
 	// the second one should be reserved as the 2nd node is not scheduling
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("2nd allocation did not return the correct allocation")
 	}
 	// check if updated (must be after allocate call)
@@ -2346,10 +2344,11 @@ func TestAllocReserveNewNode(t *testing.T) {
 
 	// turn on 2nd node
 	node2.SetSchedulable(true)
-	alloc = partition.tryReservedAllocate()
-	assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "allocation result type should have been allocatedReserved")
-	assert.Equal(t, "", alloc.GetReservedNodeID(), "reserved node should be reset after processing")
-	assert.Equal(t, node2.NodeID, alloc.GetNodeID(), "allocation should be fulfilled on new node")
+	result = partition.tryReservedAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "no result")
+	assert.Equal(t, objects.AllocatedReserved, result.ResultType, "allocation result type should have been allocatedReserved")
+	assert.Equal(t, "", result.ReservedNodeID, "reserved node should be reset after processing")
+	assert.Equal(t, node2.NodeID, result.NodeID, "allocation should be fulfilled on new node")
 	// check if all updated
 	node1 := partition.GetNode(nodeID1)
 	assert.Equal(t, 0, len(node1.GetReservationKeys()), "old node should have no more reservations")
@@ -2363,8 +2362,8 @@ func TestTryAllocateReserve(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryReservedAllocate(); alloc != nil {
-		t.Fatalf("empty cluster reserved allocate returned allocation: %s", alloc)
+	if result := partition.tryReservedAllocate(); result != nil {
+		t.Fatalf("empty cluster reserved allocate returned allocation: %s", result)
 	}
 
 	// create a set of queues and apps: app-1 2 asks; app-2 1 ask (same size)
@@ -2394,15 +2393,15 @@ func TestTryAllocateReserve(t *testing.T) {
 	}
 
 	// first allocation should be app-1 and alloc-2
-	alloc := partition.tryReservedAllocate()
-	if alloc == nil {
+	result := partition.tryReservedAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected allocated from reserved")
-	assert.Equal(t, alloc.GetReservedNodeID(), "", "node should not be set for allocated from reserved")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected allocated from reserved")
+	assert.Equal(t, result.ReservedNodeID, "", "node should not be set for allocated from reserved")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 1000}))
 
 	// reservations should have been removed: it is in progress
@@ -2411,19 +2410,19 @@ func TestTryAllocateReserve(t *testing.T) {
 	}
 
 	// no reservations left this should return nil
-	alloc = partition.tryReservedAllocate()
-	if alloc != nil {
-		t.Fatalf("reserved allocation should not return any allocation: %s, '%s'", alloc, alloc.GetReservedNodeID())
+	result = partition.tryReservedAllocate()
+	if result != nil {
+		t.Fatalf("reserved allocation should not return any allocation: %s", result)
 	}
 	// try non reserved this should allocate
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), "alloc-1", "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-1", "expected ask alloc-1 to be allocated")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 2000}))
 
 	if !resources.IsZero(partition.root.GetPendingResource()) {
@@ -2465,23 +2464,23 @@ func TestTryAllocateWithReserved(t *testing.T) {
 	if !app.IsReservedOnNode(node2.NodeID) || len(app.GetAskReservations("alloc-1")) == 0 {
 		t.Fatal("reservation failure for ask and node2")
 	}
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return correct an allocation")
 	}
-	assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "expected reserved allocation to be returned")
-	assert.Equal(t, "", alloc.GetReservedNodeID(), "reserved node should be reset after processing")
+	assert.Equal(t, objects.AllocatedReserved, result.ResultType, "expected reserved allocation to be returned")
+	assert.Equal(t, "", result.ReservedNodeID, "reserved node should be reset after processing")
 	assert.Equal(t, 0, len(node2.GetReservationKeys()), "reservation should have been removed from node")
 	assert.Equal(t, false, app.IsReservedOnNode(node2.NodeID), "reservation cleanup for ask on app failed")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 5000}))
 
 	// node2 is unreserved now so the next one should allocate on the 2nd node (fair sharing)
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return correct allocation")
 	}
-	assert.Equal(t, objects.Allocated, alloc.GetResultType(), "expected allocated allocation to be returned")
-	assert.Equal(t, node2.NodeID, alloc.GetNodeID(), "expected allocation on node2 to be returned")
+	assert.Equal(t, objects.Allocated, result.ResultType, "expected allocated allocation to be returned")
+	assert.Equal(t, node2.NodeID, result.NodeID, "expected allocation on node2 to be returned")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}))
 }
 
@@ -2492,8 +2491,8 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// override the reservation delay, and cleanup when done
@@ -2517,9 +2516,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 
 	// allocate the ask
 	for i := 1; i <= 4; i++ {
-		alloc := partition.tryAllocate()
-		if alloc == nil || alloc.GetResultType() != objects.Allocated {
-			t.Fatalf("expected allocated allocation to be returned (step %d) %s", i, alloc)
+		result := partition.tryAllocate()
+		if result == nil || result.Allocation == nil || result.ResultType != objects.Allocated {
+			t.Fatalf("expected allocated allocation to be returned (step %d)", i)
 		}
 	}
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 16000}))
@@ -2535,9 +2534,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 	assert.Assert(t, resources.Equals(pending, app.GetPendingResource()), "pending resource not set as expected")
 	// allocate so we get reservations
 	for i := 1; i <= 2; i++ {
-		alloc := partition.tryAllocate()
-		if alloc != nil {
-			t.Fatalf("expected reservations to be created not allocation to be returned (step %d) %s", i, alloc)
+		result := partition.tryAllocate()
+		if result != nil {
+			t.Fatalf("expected reservations to be created not allocation to be returned (step %d) %s", i, result)
 		}
 		assert.Equal(t, len(app.GetReservations()), i, "application reservations incorrect")
 	}
@@ -2550,9 +2549,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 	assert.NilError(t, err, "failed to add node node-3 to the partition")
 	// Try to allocate one of the reservation. We go directly to the root queue not using the partition otherwise
 	// we confirm before we get back in the test code and cannot remove the ask
-	alloc := partition.root.TryReservedAllocate(partition.GetNodeIterator)
-	if alloc == nil || alloc.GetResultType() != objects.AllocatedReserved {
-		t.Fatalf("expected allocatedReserved allocation to be returned %v", alloc)
+	result := partition.root.TryReservedAllocate(partition.GetNodeIterator)
+	if result == nil || result.Allocation == nil || result.ResultType != objects.AllocatedReserved {
+		t.Fatalf("expected allocatedReserved allocation to be returned")
 	}
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
 
@@ -2560,7 +2559,7 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 	// shim in processAllocationReleaseByAllocationKey()
 	// make sure we are counting correctly and leave the other reservation intact
 	removeAskID := "alloc-5"
-	if alloc.GetAllocationKey() == "alloc-6" {
+	if result.Allocation.GetAllocationKey() == "alloc-6" {
 		removeAskID = "alloc-6"
 	}
 	released := app.RemoveAllocationAsk(removeAskID)
@@ -2569,8 +2568,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
 
 	// now confirm the allocation: this should not remove the reservation
-	rmAlloc := partition.allocate(alloc)
-	assert.Equal(t, "", rmAlloc.GetReservedNodeID(), "reserved node should be reset after processing")
+	rmAlloc := partition.allocate(result)
+	assert.Assert(t, rmAlloc != nil && rmAlloc.Allocation != nil, "no result")
+	assert.Equal(t, "", rmAlloc.ReservedNodeID, "reserved node should be reset after processing")
 	assert.Equal(t, len(app.GetReservations()), 1, "application reservations should be kept at 1")
 	assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
 }
@@ -2941,11 +2941,11 @@ func TestPlaceholderSmallerThanReal(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 	// try to allocate a placeholder via normal allocate
-	ph := partition.tryAllocate()
-	if ph == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected placeholder ph-1 to be allocated")
 	}
-	assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+	assert.Equal(t, phID, result.Allocation.GetAllocationKey(), "expected allocation of ph-1 to be returned")
 	assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should be allocated on queue")
 	assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should be allocated on node")
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered on the partition")
@@ -2959,14 +2959,14 @@ func TestPlaceholderSmallerThanReal(t *testing.T) {
 	if partition.tryPlaceholderAllocate() != nil {
 		t.Fatal("allocation should not have matched placeholder")
 	}
-	assert.Assert(t, ph.IsReleased(), "placeholder should be released")
+	assert.Assert(t, result.Allocation.IsReleased(), "placeholder should be released")
 	assertLimits(t, getTestUserGroup(), phRes)
 
 	// release placeholder: do what the context would do after the shim processing
 	release := &si.AllocationRelease{
 		PartitionName:   partition.Name,
 		ApplicationID:   appID1,
-		AllocationKey:   ph.GetAllocationKey(),
+		AllocationKey:   result.Allocation.GetAllocationKey(),
 		TerminationType: si.TerminationType_TIMEOUT,
 	}
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "ph should be registered")
@@ -3006,12 +3006,12 @@ func TestPlaceholderSmallerMulti(t *testing.T) {
 		err = app.AddAllocationAsk(ask)
 		assert.NilError(t, err, "failed to add placeholder ask %s to app", id)
 		// try to allocate a placeholder via normal allocate
-		ph := partition.tryAllocate()
-		if ph == nil {
+		result := partition.tryAllocate()
+		if result == nil || result.Allocation == nil {
 			t.Fatalf("expected placeholder %s to be allocated", id)
 		}
-		assert.Equal(t, id, ph.GetAllocationKey(), "expected allocation of %s to be returned", id)
-		phs[id] = ph
+		assert.Equal(t, id, result.Allocation.GetAllocationKey(), "expected allocation of %s to be returned", id)
+		phs[id] = result.Allocation
 	}
 	assert.Assert(t, resources.Equals(tgRes, app.GetQueue().GetAllocatedResource()), "all placeholders should be allocated on queue")
 	assert.Assert(t, resources.Equals(tgRes, node.GetAllocatedResource()), "all placeholders should be allocated on node")
@@ -3055,8 +3055,8 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
 	setupUGM()
 	partition, err := newBasePartition()
 	assert.NilError(t, err, "partition create failed")
-	if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
-		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+	if result := partition.tryPlaceholderAllocate(); result != nil {
+		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
 	}
 
 	tgRes := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5, "second": 5})
@@ -3075,11 +3075,11 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 	// try to allocate a placeholder via normal allocate
-	ph := partition.tryAllocate()
-	if ph == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected placeholder ph-1 to be allocated")
 	}
-	assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+	assert.Equal(t, phID, result.Allocation.GetAllocationKey(), "expected allocation of ph-1 to be returned")
 	assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should be allocated on queue")
 	assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should be allocated on node")
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered on the partition")
@@ -3090,12 +3090,12 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
 	ask = newAllocationAskTG(allocKey, appID1, taskGroup, smallRes, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-1 to app with correct TG")
-	alloc := partition.tryPlaceholderAllocate()
-	if alloc == nil {
+	result2 := partition.tryPlaceholderAllocate()
+	if result2 == nil || result2.Allocation == nil {
 		t.Fatal("allocation should have matched placeholder")
 	}
-	assert.Equal(t, objects.Replaced, alloc.GetResultType(), "expected replacement result type to be returned")
-	assert.Check(t, alloc.HasRelease(), "placeholder should have been linked")
+	assert.Equal(t, objects.Replaced, result2.ResultType, "expected replacement result type to be returned")
+	assert.Check(t, result2.Allocation.HasRelease(), "placeholder should have been linked")
 	// no updates yet on queue and node
 	assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should still be allocated on queue")
 	assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should still be allocated on node")
@@ -3105,7 +3105,7 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
 	release := &si.AllocationRelease{
 		PartitionName:   partition.Name,
 		ApplicationID:   appID1,
-		AllocationKey:   ph.GetAllocationKey(),
+		AllocationKey:   result.Allocation.GetAllocationKey(),
 		TerminationType: si.TerminationType_PLACEHOLDER_REPLACED,
 	}
 	released, confirmed := partition.removeAllocation(release)
@@ -3140,12 +3140,12 @@ func TestPlaceholderMatch(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 	// try to allocate a placeholder via normal allocate
-	ph := partition.tryAllocate()
-	if ph == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected placeholder ph-1 to be allocated")
 	}
-	phAllocationKey := ph.GetAllocationKey()
-	assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+	phAllocationKey := result.Allocation.GetAllocationKey()
+	assert.Equal(t, phID, phAllocationKey, "expected allocation of ph-1 to be returned")
 	assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should be created on allocate")
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered as allocation")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
@@ -3155,13 +3155,13 @@ func TestPlaceholderMatch(t *testing.T) {
 	ask = newAllocationAskTG(allocKey, appID1, "unknown", phRes, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app")
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected ask to be allocated (unmatched task group)")
 	}
 	assert.Equal(t, 2, partition.GetTotalAllocationCount(), "allocations should be registered: ph + normal")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
-	assert.Equal(t, allocKey, alloc.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
+	assert.Equal(t, allocKey, result.Allocation.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
 	assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
 	assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
 	assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements")
@@ -3171,8 +3171,8 @@ func TestPlaceholderMatch(t *testing.T) {
 	ask = newAllocationAskTG(allocKey2, appID1, taskGroup, phRes, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app")
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("expected ask not to be allocated (matched task group)")
 	}
 	assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
@@ -3181,13 +3181,13 @@ func TestPlaceholderMatch(t *testing.T) {
 	assertLimits(t, getTestUserGroup(), resources.Multiply(phRes, 2))
 
 	// replace the placeholder should work
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc == nil {
+	result = partition.tryPlaceholderAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation should have matched placeholder")
 	}
 	assert.Equal(t, 2, partition.GetTotalAllocationCount(), "allocations should be registered: ph + normal")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
-	assert.Equal(t, allocKey2, alloc.GetAllocationKey(), "expected allocation of alloc-2 to be returned")
+	assert.Equal(t, allocKey2, result.Allocation.GetAllocationKey(), "expected allocation of alloc-2 to be returned")
 	assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
 	assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements yet")
 
@@ -3213,8 +3213,8 @@ func TestPlaceholderMatch(t *testing.T) {
 	ask = newAllocationAskTG("no_ph_used", appID1, taskGroup, phRes, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask no_ph_used to app")
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected ask to be allocated no placeholders left")
 	}
 	assertLimits(t, getTestUserGroup(), resources.Multiply(phRes, 3))
@@ -3241,12 +3241,13 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 	// try to allocate a placeholder via normal allocate
-	ph := partition.tryAllocate()
-	if ph == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected placeholder ph-1 to be allocated")
 	}
-	phAllocationKey := ph.GetAllocationKey()
-	assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+	ph := result.Allocation
+	phAllocationKey := result.Allocation.GetAllocationKey()
+	assert.Equal(t, phID, phAllocationKey, "expected allocation of ph-1 to be returned")
 	assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should be created on allocate")
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered as allocation")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
@@ -3264,8 +3265,8 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
 	ph.MarkPreempted()
 
 	// replace the placeholder should NOT work
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc != nil {
+	result = partition.tryPlaceholderAllocate()
+	if result != nil {
 		t.Fatal("allocation should not have matched placeholder")
 	}
 
@@ -3286,11 +3287,11 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
 	assert.Equal(t, 0, partition.getPhAllocationCount(), "no placeholder allocation should be registered")
 
 	// normal allocate should work as we have no placeholders left
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected ask to be allocated (no placeholder left)")
 	}
-	assert.Equal(t, allocKey, alloc.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
+	assert.Equal(t, allocKey, result.Allocation.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
 	assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
 	assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
 	assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements")
@@ -3304,8 +3305,8 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	setupUGM()
 	partition, err := newBasePartition()
 	assert.NilError(t, err, "partition create failed")
-	if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
-		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+	if result := partition.tryPlaceholderAllocate(); result != nil {
+		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
 	}
 
 	var tgRes, res *resources.Resource
@@ -3326,19 +3327,19 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 	// try to allocate placeholder should just return
-	alloc := partition.tryPlaceholderAllocate()
-	if alloc != nil {
-		t.Fatalf("placeholder ask should not be allocated: %s", alloc)
+	result := partition.tryPlaceholderAllocate()
+	if result != nil {
+		t.Fatalf("placeholder ask should not be allocated: %s", result)
 	}
 	assertLimits(t, getTestUserGroup(), nil)
 	// try to allocate a placeholder via normal allocate
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected first placeholder to be allocated")
 	}
-	assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation not found on node")
-	assert.Assert(t, alloc.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "placeholder alloc should return an allocated result")
+	assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation not found on node")
+	assert.Assert(t, result.Allocation.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
+	assert.Equal(t, result.ResultType, objects.Allocated, "placeholder alloc should return an allocated result")
 	if !resources.Equals(app.GetPlaceholderResource(), res) {
 		t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
 	}
@@ -3350,16 +3351,16 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add placeholder ask ph-2 to app")
 	// try to allocate placeholder should just return
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc != nil {
-		t.Fatalf("placeholder ask should not be allocated: %s", alloc)
+	result = partition.tryPlaceholderAllocate()
+	if result != nil {
+		t.Fatalf("placeholder ask should not be allocated: %s", result)
 	}
 	assertLimits(t, getTestUserGroup(), res)
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected 2nd placeholder to be allocated")
 	}
-	assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation 2 not found on node")
+	assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation 2 not found on node")
 	if !resources.Equals(app.GetPlaceholderResource(), resources.Multiply(res, 2)) {
 		t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
 	}
@@ -3371,9 +3372,9 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	ask = newAllocationAskTG(allocKey, appID1, "tg-unk", res, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-1 to app")
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc != nil {
-		t.Fatalf("allocation should not have matched placeholder: %s", alloc)
+	result = partition.tryPlaceholderAllocate()
+	if result != nil {
+		t.Fatalf("allocation should not have matched placeholder: %s", result)
 	}
 	assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
 
@@ -3381,16 +3382,16 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	ask = newAllocationAskTG(allocKey2, appID1, taskGroup, res, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-2 to app with correct TG")
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc == nil {
+	result = partition.tryPlaceholderAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation should have matched placeholder")
 	}
 	assert.Equal(t, 2, partition.GetTotalAllocationCount(), "placeholder replacement should not be counted as alloc")
 	assert.Equal(t, 2, partition.getPhAllocationCount(), "placeholder allocation should be registered")
-	assert.Equal(t, alloc.GetResultType(), objects.Replaced, "result type is not the expected allocated replaced")
-	assert.Check(t, alloc.HasRelease(), "released allocation should be present")
+	assert.Equal(t, result.ResultType, objects.Replaced, "result type is not the expected allocated replaced")
+	assert.Check(t, result.Allocation.HasRelease(), "released allocation should be present")
 	assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
-	phAllocationKey := alloc.GetRelease().GetAllocationKey()
+	phAllocationKey := result.Allocation.GetRelease().GetAllocationKey()
 	// placeholder is not released until confirmed by the shim
 	if !resources.Equals(app.GetPlaceholderResource(), resources.Multiply(res, 2)) {
 		t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
@@ -3410,7 +3411,7 @@ func TestTryPlaceholderAllocate(t *testing.T) {
 	if confirmed == nil {
 		t.Fatal("confirmed allocation should not be nil")
 	}
-	assert.Equal(t, confirmed.GetAllocationKey(), alloc.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
+	assert.Equal(t, confirmed.GetAllocationKey(), result.Allocation.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
 	if !resources.Equals(app.GetPlaceholderResource(), res) {
 		t.Fatalf("placeholder allocations not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
 	}
@@ -3425,8 +3426,8 @@ func TestFailReplacePlaceholder(t *testing.T) {
 	setupUGM()
 	partition, err := newBasePartition()
 	assert.NilError(t, err, "partition create failed")
-	if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
-		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+	if result := partition.tryPlaceholderAllocate(); result != nil {
+		t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
 	}
 	// plugin to let the pre-check fail on node-1 only, means we cannot replace the placeholder
 	plugin := mock.NewPredicatePlugin(false, map[string]int{nodeID1: -1})
@@ -3454,16 +3455,16 @@ func TestFailReplacePlaceholder(t *testing.T) {
 	assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
 
 	// try to allocate a placeholder via normal allocate
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("expected first placeholder to be allocated")
 	}
 	assert.Equal(t, partition.GetTotalAllocationCount(), 1, "placeholder allocation should be counted as alloc")
 	assert.Equal(t, partition.getPhAllocationCount(), 1, "placeholder allocation should be counted as placeholder")
-	assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation not found on node")
-	assert.Assert(t, alloc.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "placeholder alloc should return an allocated result type")
-	assert.Equal(t, alloc.GetNodeID(), nodeID1, "should be allocated on node-1")
+	assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation not found on node")
+	assert.Assert(t, result.Allocation.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
+	assert.Equal(t, result.ResultType, objects.Allocated, "placeholder alloc should return an allocated result type")
+	assert.Equal(t, result.NodeID, nodeID1, "should be allocated on node-1")
 	assert.Assert(t, resources.Equals(app.GetPlaceholderResource(), res), "placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
 	assertLimits(t, getTestUserGroup(), res)
 
@@ -3474,21 +3475,21 @@ func TestFailReplacePlaceholder(t *testing.T) {
 	ask = newAllocationAskTG(allocKey, appID1, taskGroup, res, false)
 	err = app.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask alloc-1 to app with correct TG")
-	alloc = partition.tryPlaceholderAllocate()
-	if alloc == nil {
+	result = partition.tryPlaceholderAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation should have matched placeholder")
 	}
 	assert.Equal(t, partition.GetTotalAllocationCount(), 1, "placeholder replacement should not be counted as alloc")
 	assert.Equal(t, partition.getPhAllocationCount(), 1, "placeholder allocation should not change")
-	assert.Equal(t, alloc.GetResultType(), objects.Replaced, "result type is not the expected allocated replaced")
-	assert.Check(t, alloc.HasRelease(), "released allocation should be present")
+	assert.Equal(t, result.ResultType, objects.Replaced, "result type is not the expected allocated replaced")
+	assert.Check(t, result.Allocation.HasRelease(), "released allocation should be present")
 	// allocation must be added as it is on a different node
-	assert.Equal(t, alloc.GetNodeID(), nodeID2, "should be allocated on node-2")
+	assert.Equal(t, result.NodeID, nodeID2, "should be allocated on node-2")
 	assert.Assert(t, resources.IsZero(app.GetAllocatedResource()), "allocated resources should be zero")
 	assert.Assert(t, resources.Equals(node.GetAllocatedResource(), res), "node-1 allocation not updated as expected: got %s, expected %s", node.GetAllocatedResource(), res)
 	assert.Assert(t, resources.Equals(node2.GetAllocatedResource(), res), "node-2 allocation not updated as expected: got %s, expected %s", node2.GetAllocatedResource(), res)
 
-	phAllocationKey := alloc.GetRelease().GetAllocationKey()
+	phAllocationKey := result.Allocation.GetRelease().GetAllocationKey()
 	// placeholder is not released until confirmed by the shim
 	assert.Assert(t, resources.Equals(app.GetPlaceholderResource(), res), "placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
 	assertLimits(t, getTestUserGroup(), res)
@@ -3507,7 +3508,7 @@ func TestFailReplacePlaceholder(t *testing.T) {
 	if confirmed == nil {
 		t.Fatal("confirmed allocation should not be nil")
 	}
-	assert.Equal(t, confirmed.GetAllocationKey(), alloc.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
+	assert.Equal(t, confirmed.GetAllocationKey(), result.Allocation.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
 	assert.Assert(t, resources.IsZero(app.GetPlaceholderResource()), "placeholder resources should be zero")
 	assert.Assert(t, resources.Equals(app.GetAllocatedResource(), res), "allocations not updated as expected: got %s, expected %s", app.GetAllocatedResource(), res)
 	assert.Assert(t, resources.IsZero(node.GetAllocatedResource()), "node-1 allocated resources should be zero")
@@ -3732,8 +3733,8 @@ func TestTryAllocateMaxRunning(t *testing.T) {
 	if partition == nil {
 		t.Fatal("partition create failed")
 	}
-	if alloc := partition.tryAllocate(); alloc != nil {
-		t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+	if result := partition.tryAllocate(); result != nil {
+		t.Fatalf("empty cluster allocate returned allocation: %s", result)
 	}
 
 	// set max running apps
@@ -3757,14 +3758,14 @@ func TestTryAllocateMaxRunning(t *testing.T) {
 	assert.Equal(t, app.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
 
 	// allocate should work: app stays in accepted state (placeholder!)
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc to be allocated")
 	assert.Equal(t, app.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
 
 	// add second app to the partition
@@ -3775,41 +3776,41 @@ func TestTryAllocateMaxRunning(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-2")
 
 	// allocation should fail max running app is reached on parent via accepted allocating
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation should not have returned as parent limit is reached")
 	}
 
 	// allocate should work: app moves to Starting all placeholder allocated
 	err = app.AddAllocationAsk(newAllocationAskTG("alloc-2", appID1, "ph1", res, true))
 	assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
 	assert.Equal(t, app.CurrentState(), objects.Running.String(), "application should have moved to running state")
 
 	// allocation should still fail: max running apps on parent reached
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation should not have returned as parent limit is reached")
 	}
 
 	// update the parent queue max running
 	parent.SetMaxRunningApps(2)
 	// allocation works
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-	assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
-	assert.Equal(t, alloc.GetApplicationID(), appID2, "expected application app-2 to be allocated")
-	assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+	assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+	assert.Equal(t, result.Allocation.GetApplicationID(), appID2, "expected application app-2 to be allocated")
+	assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 }
 
 func TestNewQueueEvents(t *testing.T) {
@@ -3872,15 +3873,15 @@ func TestUserHeadroom(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-2")
 
 	// app 1 would be allocated as there is headroom available for the user
-	alloc := partition.tryAllocate()
-	if alloc == nil {
+	result := partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
 
 	// app 2 allocation won't happen as there is no headroom for the user
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation should not happen")
 	}
 
@@ -3894,11 +3895,11 @@ func TestUserHeadroom(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-3")
 
 	// app 3 would be allocated as there is headroom available for the user
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
 
 	app4 := newApplication("app-4", "default", "root.leaf")
 	err = partition.AddApplication(app4)
@@ -3907,8 +3908,8 @@ func TestUserHeadroom(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-4")
 
 	// app 4 allocation won't happen as there is no headroom for the user
-	alloc = partition.tryAllocate()
-	if alloc != nil {
+	result = partition.tryAllocate()
+	if result != nil {
 		t.Fatal("allocation should not happen")
 	}
 	partition.removeApplication(appID1)
@@ -3937,19 +3938,19 @@ func TestUserHeadroom(t *testing.T) {
 	node1 := partition.GetNode(nodeID1)
 	node1.SetSchedulable(false)
 
-	alloc = partition.tryReservedAllocate()
-	if alloc == nil {
+	result = partition.tryReservedAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "allocation result type should have been allocated")
+	assert.Equal(t, objects.AllocatedReserved, result.ResultType, "allocation result type should have been allocated")
 
 	// create a reservation and ensure reservation has not been allocated because there is no headroom for the user
 	ask = newAllocationAsk("alloc-2", "app-5", res)
 	err = app5.AddAllocationAsk(ask)
 	assert.NilError(t, err, "failed to add ask to app")
 	partition.reserve(app5, node2, ask)
-	alloc = partition.tryReservedAllocate()
-	if alloc != nil {
+	result = partition.tryReservedAllocate()
+	if result != nil {
 		t.Fatal("allocation should not happen on other nodes as well")
 	}
 	partition.removeApplication("app-5")
@@ -3967,11 +3968,11 @@ func TestUserHeadroom(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask alloc-1 to app-6")
 
 	// app 6 would be allocated as headroom is nil because no limits configured for 'testuser1' user an
-	alloc = partition.tryAllocate()
-	if alloc == nil {
+	result = partition.tryAllocate()
+	if result == nil || result.Allocation == nil {
 		t.Fatal("allocation did not return any allocation")
 	}
-	assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+	assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
 }
 
 func TestPlaceholderAllocationTracking(t *testing.T) {
@@ -4002,26 +4003,26 @@ func TestPlaceholderAllocationTracking(t *testing.T) {
 	assert.NilError(t, err, "failed to add ask to app")
 
 	// allocate first placeholder
-	alloc := partition.tryAllocate()
-	ph1AllocationKey := alloc.GetAllocationKey()
-	assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+	result := partition.tryAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+	ph1AllocationKey := result.Allocation.GetAllocationKey()
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
-	alloc1 := partition.tryPlaceholderAllocate()
-	assert.Assert(t, alloc1 != nil, "ask should have been allocated")
+	result1 := partition.tryPlaceholderAllocate()
+	assert.Assert(t, result1 != nil && result1.Allocation != nil, "ask should have been allocated")
 	assert.Equal(t, 1, partition.GetTotalAllocationCount(), "should see no change in alloc count")
 	assert.Equal(t, 1, partition.getPhAllocationCount(), "should see no change in placeholder count")
 
 	// allocate second placeholder
-	alloc = partition.tryAllocate()
-	ph2AllocationKey := alloc.GetAllocationKey()
-	assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+	result = partition.tryAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+	ph2AllocationKey := result.Allocation.GetAllocationKey()
 	assert.Equal(t, 2, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
 	assert.Equal(t, 2, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
 	// allocate third placeholder
-	alloc = partition.tryAllocate()
-	ph3AllocationKey := alloc.GetAllocationKey()
-	assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+	result = partition.tryAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+	ph3AllocationKey := result.Allocation.GetAllocationKey()
 	assert.Equal(t, 3, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
 	assert.Equal(t, 3, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
 
@@ -4068,13 +4069,14 @@ func TestReservationTracking(t *testing.T) {
 	err = app.AddAllocationAsk(ask2)
 	assert.NilError(t, err, "failed to add ask")
 
-	alloc := partition.tryAllocate() // ask1 occupies node1
-	allocationKey := alloc.GetAllocationKey()
-	assert.Equal(t, objects.Allocated, alloc.GetResultType())
-	assert.Equal(t, "alloc-1", alloc.GetAllocationKey())
+	result := partition.tryAllocate() // ask1 occupies node1
+	assert.Assert(t, result != nil && result.Allocation != nil, "no alloc")
+	assert.Equal(t, objects.Allocated, result.ResultType)
+	allocationKey := result.Allocation.GetAllocationKey()
+	assert.Equal(t, "alloc-1", allocationKey)
 	assert.Equal(t, 0, partition.getReservationCount())
-	alloc = partition.tryAllocate() // ask2 gets reserved
-	assert.Assert(t, alloc == nil)
+	result = partition.tryAllocate() // ask2 gets reserved
+	assert.Assert(t, result == nil)
 	assert.Equal(t, 1, partition.getReservationCount())
 
 	partition.removeAllocation(&si.AllocationRelease{
@@ -4082,9 +4084,10 @@ func TestReservationTracking(t *testing.T) {
 		ApplicationID:   appID1,
 		TerminationType: si.TerminationType_STOPPED_BY_RM,
 	}) // terminate ask1
-	alloc = partition.tryReservedAllocate() // allocate reservation
+	result = partition.tryReservedAllocate() // allocate reservation
+	assert.Assert(t, result != nil && result.Allocation != nil, "no alloc")
 	assert.Equal(t, 0, partition.getReservationCount())
-	assert.Equal(t, "alloc-2", alloc.GetAllocationKey())
+	assert.Equal(t, "alloc-2", result.Allocation.GetAllocationKey())
 }
 
 //nolint:funlen
@@ -4220,13 +4223,13 @@ func TestLimitMaxApplications(t *testing.T) {
 			err = app1.AddAllocationAsk(newAllocationAsk(allocKey, appID1, res))
 			assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
-			alloc := partition.tryAllocate()
-			if alloc == nil {
+			result := partition.tryAllocate()
+			if result == nil || result.Allocation == nil {
 				t.Fatal("allocation did not return any allocation")
 			}
-			assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
-			assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
-			assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+			assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+			assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+			assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
 
 			// add app2
 			app2 := newApplication(appID2, "default", defQueue)
@@ -4236,8 +4239,8 @@ func TestLimitMaxApplications(t *testing.T) {
 			assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
 			assert.Equal(t, app2.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
 
-			alloc = partition.tryAllocate()
-			assert.Equal(t, alloc == nil, true, "allocation should not have happened as max apps reached")
+			result = partition.tryAllocate()
+			assert.Equal(t, result == nil, true, "allocation should not have happened as max apps reached")
 		})
 	}
 }
@@ -4378,13 +4381,13 @@ func TestLimitMaxApplicationsForReservedAllocation(t *testing.T) {
 			assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
 
 			partition.reserve(app1, node, app1AllocAsk)
-			alloc := partition.tryReservedAllocate()
-			if alloc == nil {
+			result := partition.tryReservedAllocate()
+			if result == nil || result.Allocation == nil {
 				t.Fatal("allocation did not return any allocation")
 			}
-			assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected allocated reserved")
-			assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated reserved")
-			assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated reserved")
+			assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected allocated reserved")
+			assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated reserved")
+			assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated reserved")
 
 			// add app2
 			app2 := newApplication(appID2, "default", defQueue)
@@ -4396,8 +4399,8 @@ func TestLimitMaxApplicationsForReservedAllocation(t *testing.T) {
 			assert.Equal(t, app2.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
 
 			partition.reserve(app2, node, app2AllocAsk)
-			alloc = partition.tryReservedAllocate()
-			assert.Equal(t, alloc == nil, true, "allocation should not have happened as max apps reached")
+			result = partition.tryReservedAllocate()
+			assert.Assert(t, result == nil, "allocation should not have happened as max apps reached")
 		})
 	}
 }
@@ -4503,19 +4506,19 @@ func TestPlaceholderAllocationAndReplacementAfterRecovery(t *testing.T) {
 	assert.NilError(t, err, "failed to add real ask")
 
 	// get an allocation for "placeholder2"
-	alloc := partition.tryAllocate()
-	assert.Assert(t, alloc != nil, "no allocation occurred")
-	assert.Equal(t, objects.Allocated, alloc.GetResultType())
-	assert.Equal(t, "placeholder2", alloc.GetAllocationKey())
-	assert.Equal(t, "tg-2", alloc.GetTaskGroup())
-	assert.Equal(t, "node-1", alloc.GetNodeID())
+	result := partition.tryAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "no allocation occurred")
+	assert.Equal(t, objects.Allocated, result.ResultType)
+	assert.Equal(t, "placeholder2", result.Allocation.GetAllocationKey())
+	assert.Equal(t, "tg-2", result.Allocation.GetTaskGroup())
+	assert.Equal(t, "node-1", result.NodeID)
 
 	// real allocation gets replaced
-	alloc = partition.tryPlaceholderAllocate()
-	assert.Assert(t, alloc != nil, "no placeholder replacement occurred")
-	assert.Equal(t, objects.Replaced, alloc.GetResultType())
-	assert.Equal(t, "real-alloc", alloc.GetAllocationKey())
-	assert.Equal(t, "tg-1", alloc.GetTaskGroup())
+	result = partition.tryPlaceholderAllocate()
+	assert.Assert(t, result != nil && result.Allocation != nil, "no placeholder replacement occurred")
+	assert.Equal(t, objects.Replaced, result.ResultType)
+	assert.Equal(t, "real-alloc", result.Allocation.GetAllocationKey())
+	assert.Equal(t, "tg-1", result.Allocation.GetTaskGroup())
 
 	// remove the terminated placeholder allocation
 	released, confirmed := partition.removeAllocation(&si.AllocationRelease{


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@yunikorn.apache.org
For additional commands, e-mail: issues-help@yunikorn.apache.org