Skip to content

Commit

Permalink
remove every-30-second SchedulerManager trigger, in favor of one
Browse files Browse the repository at this point in the history
post-reconfig trigger

This revealed a bug in Periodic (not scheduling a wakeup for the next
periodic build), now fixed. Unit tests were updated too.

I left a "just_poll" flag in place for a future config knob to enable the
multiple-masters-sharing-one-DB mode.
  • Loading branch information
warner committed Feb 17, 2010
1 parent f2b79ee commit 5dcd24c
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 13 deletions.
20 changes: 14 additions & 6 deletions buildbot/master.py
Expand Up @@ -18,11 +18,9 @@
from buildbot.util import now, safeTranslate
from buildbot.pbutil import NewCredPerspective
from buildbot.process.builder import Builder, IDLE
from buildbot.buildrequest import BuildRequest
from buildbot.status.builder import Status, BuildSetStatus
from buildbot.changes.changes import Change
from buildbot.changes.manager import ChangeManager
from buildbot.sourcestamp import SourceStamp
from buildbot.buildslave import BuildSlave
from buildbot import interfaces, locks
from buildbot.process.properties import Properties
Expand Down Expand Up @@ -442,10 +440,20 @@ def __init__(self, basedir, configFileName="master.cfg", db=None):
self.db.subscribe_to("modify-buildset", sm.trigger_modify_buildset)
self.scheduler_manager = sm
sm.setServiceParent(self)
# it'd be nice if TimerService let us set now=False
t = internet.TimerService(30, sm.trigger)
t.setServiceParent(self)
# should we try to remove this? Periodic() requires at least one kick
# TODO: this will turn into a config knob somehow. Set it if you are
# using multiple buildmasters that share a common database, such that
# the masters need to discover what each other is doing by polling
# the database. TODO: this will turn into the DBNotificationServer.
just_poll = False
if just_poll:
# it'd be nice if TimerService let us set now=False
t1 = internet.TimerService(30, sm.trigger)
t1.setServiceParent(self)
t2 = internet.TimerService(30, self.botmaster.loop.trigger)
t2.setServiceParent(self)
# adding schedulers (like when loadConfig happens) will trigger the
# scheduler loop at least once, which we need to jump-start things
# like Periodic.

self.status = Status(self.botmaster, self.db, self.basedir)
self.statusTargets = []
Expand Down
2 changes: 2 additions & 0 deletions buildbot/schedulers/manager.py
Expand Up @@ -39,6 +39,7 @@
from twisted.python import log
from buildbot import loop
from buildbot.util import defaultdict
from buildbot.eventual import eventually

class SchedulerManager(loop.MultiServiceLoop):
def __init__(self, master, db, change_svc):
Expand Down Expand Up @@ -94,6 +95,7 @@ def _attach(ign):
for s in list(self):
if s.upstream_name:
self.upstream_subscribers[s.upstream_name].append(s)
eventually(self.trigger)
d.addCallback(_attach)
d.addErrback(log.err)
return d
Expand Down
7 changes: 4 additions & 3 deletions buildbot/schedulers/timed.py
Expand Up @@ -99,13 +99,14 @@ def _run(self, t):
if last_build is None:
self.start_HEAD_build(t)
self.update_last_build(t, now)
return None
last_build = now
when = last_build + self.periodicBuildTimer
if when < now:
self.start_HEAD_build(t)
self.update_last_build(t, now)
return None
return when - now + 1.0
last_build = now
when = now + self.periodicBuildTimer
return when + 1.0


class Nightly(_Base, ClassifierMixin, TimedBuildMixin):
Expand Down
2 changes: 2 additions & 0 deletions buildbot/test/runs/test_db.py
Expand Up @@ -48,6 +48,7 @@
from buildbot.changes.manager import ChangeManager
from buildbot.test.pollmixin import PollMixin
from buildbot.test.runutils import RunMixin
from buildbot.eventual import flushEventualQueue

class ShouldFailMixin:

Expand Down Expand Up @@ -285,6 +286,7 @@ def _check4(ign):
self.failUnlessEqual(all[0].name, "one")
self.failUnlessEqual(all[1].builderNames, ["builder-two-other"])
d.addCallback(_check4)
d.addCallback(flushEventualQueue)
return d

def stall(self, res, timeout):
Expand Down
14 changes: 10 additions & 4 deletions buildbot/test/unit/test_scheduler.py
Expand Up @@ -18,20 +18,26 @@ def setSchedulers(self, *schedulers):
def testPeriodic1(self):
self.basedir = 'scheduler/Scheduling/testPeriodic1'
self.create_master()
# updateSchedulers itself fires the first trigger
d = self.setSchedulers(scheduler.Periodic("quickly", ["a","b"], 2))
d.addCallback(lambda ign: self.master.scheduler_manager.trigger())
d.addCallback(self.stall, 2)
d.addCallback(lambda ign: self.master.scheduler_manager.when_quiet())
# there should be one buildset submitted at startup, and another a
# few seconds later. We wait until we've seen at least two.
def _pollf():
bsids = self.master.db.get_active_buildset_ids()
return bool(len(bsids) > 1)
d.addCallback(lambda ign: self.poll(_pollf, 0.1))
d.addCallback(self._testPeriodic1_1)
return d
def _testPeriodic1_1(self, res):
bsids = self.master.db.get_active_buildset_ids()
self.failUnless(len(bsids) > 1)

(external_idstring, reason, ssid, complete, results) = self.master.db.get_buildset_info(bsids[0])
(external_idstring, reason, ssid,
complete, results) = self.master.db.get_buildset_info(bsids[0])
reqs = self.master.db.get_buildrequestids_for_buildset(bsids[0])
self.failUnlessEqual(sorted(reqs.keys()), ["a","b"])
self.failUnlessEqual(reason, "The Periodic scheduler named 'quickly' triggered this build")
testPeriodic1.timeout = 20

def testNightly(self):
# now == 15-Nov-2005, 00:05:36 AM . By using mktime, this is
Expand Down

0 comments on commit 5dcd24c

Please sign in to comment.