[Buildbot-devel] schedulerdb project status update

Brian Warner warner at lothar.com
Thu Oct 15 19:07:06 UTC 2009

Buildbot-schedulerdb status report, 10/15/2009.

= Code =

Latest code is published on github:


  (the -REBASES suffix is a warning that the history of this branch will
   be rewritten frequently, as I rebase to latest trunk, and make the
   deltas easier to read. So if you write patches on top of this branch,
   be prepared to rebase them also, and do not merge this branch to

 Use "git clone -b schedulerdb-REBASES git://github.com/warner/buildbot.git"
 to grab a copy. "git diff master...schedulerdb-REBASES" will show you
 changed relative to trunk.

Schema is defined in buildbot/db.py:


= Architecture =

Basic flow of control is:

 ChangeSource -> [changes tables]
 [changes] -> Scheduler -> [scheduler],[buildrequests]
 [buildrequests] -> Builder

A separate "Notification Loop" is used to control invocation of both
Schedulers, and Builders. This ensures that only one e.g. Scheduler is
running at a time, and provides a place for Schedulers to wake up the
Builders after they've changed something. It also allows a Scheduler to
ask to be woken up later (i.e. for tree-stable-timer or Periodic). (this
is the piece that will become a network-visible service, to enable a
distributed collection of buildmasters).

The Scheduler loop is triggered each time a Change is added to
[changes]. Each uses two separate transactions. In the first, each
Scheduler examines [changes], classifies new ones as important or
unimportant, and writes its conclusions to the DB. In the second, it
reads these conclusions to decide if it is time to submit a
BuildRequest. If it needs to wait for time to pass, it returns a delay
value to the Notification loop. Schedulers must be idempotent, and keep
all of their state (but not their configuration) in the DB. Eventually,
the Scheduler adds a BuildRequest to [buildrequests], and wakes up the
Builder loop.

The Builder loop invokes each Builder in turn. If the Builder has an
available slave and sees an unclaimed BuildRequest, it claims the breq
(by updating 'claimed_at' and 'claimed_by' in [buildrequests]), creates
the BuildRequest objects, and starts the build as usual. When the build
finishes, the request is removed from [buildrequests] (or at least made
inactive), and the Builder loop is retriggered, so it can look for more

Builders are supposed to renew their claims at least once an hour. Other
buildmasters are allowed to claim a build that has been left unclaimed
for over an hour. Each buildmaster can recognize its own (old) claims,
so if a buildmaster is bounced, it can reclaim builds immediately.

= Progress =

About 90 hours on the clock so far.

Framing is 90% complete:
 * tables are mostly feature-complete
 * DB setup/access code works, "buildbot upgrade-master" creates sqlite DB
 * architecture seems sound
 * [todo] what history do we want to preserve? where should it be
   stored? separate tables?

Drywall is 50% complete. Still to do:
 * construct passing unit tests for Builder
 * update SQL to work with mysql, not just sqlite
 * port other Schedulers: Periodic/Nightly, Triggerable/Try
 * port Dependent scheduler: implement BuildSet, feedback from
   build-finished to buildset-complete to downstream-scheduler
 * figure out status interfaces for scheduler pieces:
   BuildRequestStatus, (current) BuilderStatus. Any "statusdb" work is
   explicitly deferred, but the existing interfaces need to keep working
   even if their backing store has been moved from RAM to the DB
 * periodically update the claim (held by Builders on BuildRequests)
 * avoid race condition in claiming buildrequests (only update if the
   claimed_at/claimed_by is unchanged)

Painting is 10% complete:
 * retain compatibility with c['prioritizeBuilders']
 * update unit tests
 * figure out GC: keep DB from unbounded growth, remove old/unused
   SourceStamp/BuildRequest/Properties rows
 * construct buildmaster identity (for buildrequest claim):

 * lost about 15h trying (and failing) to clean up Builder.startBuild,
   to support RETRY cleanly, complicated by test_slaves
   (LatentBuildSlave, slaveping). This may or may not be necessary
   before merging this work into trunk.
 * spent about 5h accomodating surprising new features (nextSlave,
   nextBuild, latent slaves)
 * maybe 2h spent on other Mozilla RelEng support: machine
   allocation/utilization analysis

Likely remaining large changes:
 * move all DB code into a single file?
 * clean up mixed sync/async DB access: decide on what should not block,
   what can block, where the complexity of returning Deferreds is
 * change allocate-next-highest-idnumber technique

More information about the devel mailing list