Skip to content

Commit 4828b0c

Browse files
dmcilvaneyPawelWMS
andauthored
Don't allow multiple build queues (#7928) (#11222)
Co-authored-by: Pawel Winogrodzki <pawelwi@microsoft.com>
1 parent de68b92 commit 4828b0c

3 files changed

Lines changed: 65 additions & 6 deletions

File tree

toolkit/tools/scheduler/scheduler.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,12 @@ func buildAllNodes(stopOnFailure, canUseCache bool, packagesToRebuild, testsToRe
334334
logger.Log.Debugf("Found %d unblocked nodes: %v.", len(nodesToBuild), nodesToBuild)
335335

336336
// Each node that is ready to build must be converted into a build request and submitted to the worker pool.
337-
newRequests := schedulerutils.ConvertNodesToRequests(pkgGraph, graphMutex, nodesToBuild, packagesToRebuild, testsToRerun, buildState, canUseCache)
337+
newRequests, requestError := schedulerutils.ConvertNodesToRequests(pkgGraph, graphMutex, nodesToBuild, packagesToRebuild, testsToRerun, buildState, canUseCache)
338+
if requestError != nil {
339+
err = fmt.Errorf("failed to convert nodes to requests:\n%w", requestError)
340+
stopBuilding = true
341+
break
342+
}
338343
for _, req := range newRequests {
339344
buildState.RecordBuildRequest(req)
340345
// Decide which priority the build should be. Generally we want to get any remote or prebuilt nodes out of the

toolkit/tools/scheduler/schedulerutils/graphbuildstate.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ func (g *GraphBuildState) ActiveBuildFromSRPM(srpmFileName string) *BuildRequest
124124
return nil
125125
}
126126

127+
// IsSRPMBuildActive returns true if a given SRPM is currently queued for building.
128+
func (g *GraphBuildState) IsSRPMBuildActive(srpmFileName string) bool {
129+
return g.ActiveBuildFromSRPM(srpmFileName) != nil
130+
}
131+
127132
// ActiveSRPMs returns a list of all SRPMs, which are currently being built.
128133
func (g *GraphBuildState) ActiveSRPMs() (builtSRPMs []string) {
129134
for _, buildRequest := range g.activeBuilds {
@@ -146,6 +151,23 @@ func (g *GraphBuildState) ActiveTests() (testedSRPMs []string) {
146151
return
147152
}
148153

154+
// ActiveTestFromSRPM returns a test request for the queried SRPM file
155+
// or nil if the SRPM is not among the active builds.
156+
func (g *GraphBuildState) ActiveTestFromSRPM(srpmFileName string) *BuildRequest {
157+
for _, buildRequest := range g.activeBuilds {
158+
if buildRequest.Node.Type == pkggraph.TypeTest && buildRequest.Node.SRPMFileName() == srpmFileName {
159+
return buildRequest
160+
}
161+
}
162+
163+
return nil
164+
}
165+
166+
// IsSRPMTestActive returns true if a given SRPM is currently queued for testing.
167+
func (g *GraphBuildState) IsSRPMTestActive(srpmFileName string) bool {
168+
return g.ActiveTestFromSRPM(srpmFileName) != nil
169+
}
170+
149171
// BuildFailures returns a slice of all failed builds.
150172
func (g *GraphBuildState) BuildFailures() []*BuildResult {
151173
return g.failures

toolkit/tools/scheduler/schedulerutils/preparerequest.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package schedulerutils
55

66
import (
7+
"fmt"
78
"sync"
89

910
"github.com/microsoft/azurelinux/toolkit/tools/internal/logger"
@@ -27,7 +28,7 @@ import (
2728
// and are queued for building in the testNodesToRequests() function.
2829
// At this point the partner build nodes for these test nodes have either already finished building or are being built,
2930
// thus the check for active and cached SRPMs inside testNodesToRequests().
30-
func ConvertNodesToRequests(pkgGraph *pkggraph.PkgGraph, graphMutex *sync.RWMutex, nodesToBuild []*pkggraph.PkgNode, packagesToRebuild, testsToRerun []*pkgjson.PackageVer, buildState *GraphBuildState, isCacheAllowed bool) (requests []*BuildRequest) {
31+
func ConvertNodesToRequests(pkgGraph *pkggraph.PkgGraph, graphMutex *sync.RWMutex, nodesToBuild []*pkggraph.PkgNode, packagesToRebuild, testsToRerun []*pkgjson.PackageVer, buildState *GraphBuildState, isCacheAllowed bool) (requests []*BuildRequest, err error) {
3132
timestamp.StartEvent("generate requests", nil)
3233
defer timestamp.StopEvent(nil)
3334

@@ -57,13 +58,23 @@ func ConvertNodesToRequests(pkgGraph *pkggraph.PkgGraph, graphMutex *sync.RWMute
5758
requests = append(requests, req)
5859
}
5960

60-
requests = append(requests, buildNodesToRequests(pkgGraph, buildState, packagesToRebuild, testsToRerun, buildNodes, isCacheAllowed)...)
61-
requests = append(requests, testNodesToRequests(pkgGraph, buildState, testsToRerun, testNodes)...)
61+
newBuildReqs, err := buildNodesToRequests(pkgGraph, buildState, packagesToRebuild, testsToRerun, buildNodes, isCacheAllowed)
62+
if err != nil {
63+
err = fmt.Errorf("failed to convert build nodes to requests:\n%w", err)
64+
return
65+
}
66+
requests = append(requests, newBuildReqs...)
67+
newTestReqs, err := testNodesToRequests(pkgGraph, buildState, testsToRerun, testNodes)
68+
if err != nil {
69+
err = fmt.Errorf("failed to convert test nodes to requests:\n%w", err)
70+
return
71+
}
72+
requests = append(requests, newTestReqs...)
6273

6374
return
6475
}
6576

66-
func buildNodesToRequests(pkgGraph *pkggraph.PkgGraph, buildState *GraphBuildState, packagesToRebuild, testsToRerun []*pkgjson.PackageVer, buildNodesLists map[string][]*pkggraph.PkgNode, isCacheAllowed bool) (requests []*BuildRequest) {
77+
func buildNodesToRequests(pkgGraph *pkggraph.PkgGraph, buildState *GraphBuildState, packagesToRebuild, testsToRerun []*pkgjson.PackageVer, buildNodesLists map[string][]*pkggraph.PkgNode, isCacheAllowed bool) (requests []*BuildRequest, err error) {
6778
for _, buildNodes := range buildNodesLists {
6879
// Check if any of the build nodes is a delta node and mark it. We will use this to determine if the
6980
// build is a delta build that might have pre-built .rpm files available.
@@ -76,6 +87,17 @@ func buildNodesToRequests(pkgGraph *pkggraph.PkgGraph, buildState *GraphBuildSta
7687
}
7788

7889
defaultNode := buildNodes[0]
90+
91+
// Check if we already queued up this build node for building.
92+
if buildState.IsSRPMBuildActive(defaultNode.SRPMFileName()) || buildState.IsNodeProcessed(defaultNode) {
93+
err = fmt.Errorf("unexpected duplicate build for (%s)", defaultNode.SRPMFileName())
94+
// Temporarily ignore the error, this state is unexpected but not fatal. Error return will be
95+
// restored later once the underlying cause of this error is fixed.
96+
logger.Log.Warnf(err.Error())
97+
err = nil
98+
continue
99+
}
100+
79101
req := buildRequest(pkgGraph, buildState, packagesToRebuild, defaultNode, buildNodes, isCacheAllowed, hasADeltaNode)
80102
requests = append(requests, req)
81103

@@ -152,13 +174,23 @@ func partnerTestNodesToRequest(pkgGraph *pkggraph.PkgGraph, buildState *GraphBui
152174
// which have already been queued to build or finished building.
153175
//
154176
// NOTE: the caller must guarantee the build state does not change while this function is running.
155-
func testNodesToRequests(pkgGraph *pkggraph.PkgGraph, buildState *GraphBuildState, testsToRerun []*pkgjson.PackageVer, testNodesLists map[string][]*pkggraph.PkgNode) (requests []*BuildRequest) {
177+
func testNodesToRequests(pkgGraph *pkggraph.PkgGraph, buildState *GraphBuildState, testsToRerun []*pkgjson.PackageVer, testNodesLists map[string][]*pkggraph.PkgNode) (requests []*BuildRequest, err error) {
156178
const isDelta = false
157179

158180
for _, testNodes := range testNodesLists {
159181
defaultTestNode := testNodes[0]
160182
srpmFileName := defaultTestNode.SRPMFileName()
161183

184+
// Check if we already queued up this build node for building.
185+
if buildState.IsSRPMBuildActive(srpmFileName) || buildState.IsNodeProcessed(defaultTestNode) {
186+
err = fmt.Errorf("unexpected duplicate test for (%s)", srpmFileName)
187+
// Temporarily ignore the error, this state is unexpected but not fatal. Error return will be
188+
// restored later once the underlying cause of this error is fixed.
189+
logger.Log.Warnf(err.Error())
190+
err = nil
191+
continue
192+
}
193+
162194
buildUsedCache := buildState.IsSRPMCached(srpmFileName)
163195
if buildRequest := buildState.ActiveBuildFromSRPM(srpmFileName); buildRequest != nil {
164196
buildUsedCache = buildRequest.UseCache

0 commit comments

Comments
 (0)