Skip to content

Commit

Permalink
debounce new buildrequests events.
Browse files Browse the repository at this point in the history
The brd has an api that can schedule several builders for requests,
but we don't use it unless at startup.

This change uses the debouncer so that we wait until there is no
new buildrequest event for 1 s before starting them all
  • Loading branch information
tardyp committed Oct 31, 2021
1 parent 90b8620 commit df2506c
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions master/buildbot/process/botmaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from buildbot.process.results import CANCELLED
from buildbot.process.results import RETRY
from buildbot.process.workerforbuilder import States
from buildbot.util import debounce
from buildbot.util import service


Expand Down Expand Up @@ -100,6 +101,7 @@ def __init__(self):
# a distributor for incoming build requests; see below
self.brd = BuildRequestDistributor(self)
self.brd.setServiceParent(self)
self._pending_builderids = set()

@defer.inlineCallbacks
def cleanShutdown(self, quickMode=False, stopReactor=True):
Expand Down Expand Up @@ -198,6 +200,24 @@ def getBuildernames(self):
def getBuilders(self):
return list(self.builders.values())

def _buildrequest_added(self, key, msg):
self._pending_builderids.add(msg['builderid'])
self._flush_pending_builders()

# flush pending builders needs to be debounced, as per design the
# buildrequests events will arrive in burst.
# We debounce them to let the brd manage them as a whole
# without having to debounce the brd itself
@debounce.method(wait=.1, until_idle=True)
def _flush_pending_builders(self):
buildernames = []
for builderid in self._pending_builderids:
buildername = self._builderid_to_buildername.get(builderid)
if buildername:
buildernames.append(buildername)
self._pending_builderids.clear()
self.brd.maybeStartBuildsOn(buildernames)

@defer.inlineCallbacks
def getBuilderById(self, builderid):
for builder in self.getBuilders():
Expand All @@ -207,20 +227,13 @@ def getBuilderById(self, builderid):

@defer.inlineCallbacks
def startService(self):
@defer.inlineCallbacks
def buildRequestAdded(key, msg):
builderid = msg['builderid']
builder = yield self.getBuilderById(builderid)
if builder is not None:
self.maybeStartBuildsForBuilder(builder.name)

# consume both 'new' and 'unclaimed' build requests
# consume both 'new' and 'unclaimed' build requests events
startConsuming = self.master.mq.startConsuming
self.buildrequest_consumer_new = yield startConsuming(
buildRequestAdded,
self._buildrequest_added,
('buildrequests', None, "new"))
self.buildrequest_consumer_unclaimed = yield startConsuming(
buildRequestAdded,
self._buildrequest_added,
('buildrequests', None, 'unclaimed'))
yield super().startService()

Expand Down Expand Up @@ -281,6 +294,9 @@ def reconfigServiceBuilders(self, new_config):
yield builder.setServiceParent(self)

self.builderNames = list(self.builders)
self._builderid_to_buildername = {}
for builder in self.builders.values():
self._builderid_to_buildername[(yield builder.getBuilderId())] = builder.name

yield self.master.data.updates.updateBuilderList(
self.master.masterid,
Expand All @@ -298,6 +314,7 @@ def stopService(self):
if self.buildrequest_consumer_unclaimed:
self.buildrequest_consumer_unclaimed.stopConsuming()
self.buildrequest_consumer_unclaimed = None
self._flush_pending_builders.stop()
return super().stopService()

def maybeStartBuildsForBuilder(self, buildername):
Expand Down

0 comments on commit df2506c

Please sign in to comment.