In the past, jobsets which are automatically evaluated are evaluated regularly, on a schedule. This schedule means a new evaluation is created every checkInterval seconds (assuming something changed.)
This model works well for architectures where our build farm can easily keep up with demand.
This commit adds a new type of evaluation, called ONE_AT_A_TIME, which only schedules a new evaluation if the previous evaluation of the jobset has no unfinished builds.
This model of evaluation lets us have 'low-tier' architectures.
For example, we could now have a jobset for ARMv7l builds, where the buildfarm only has a single, underpowered ARMv7l builder. Configuring that jobset as ONE_AT_A_TIME will create an evaluation and then won't schedule another evaluation until every job of the existing evaluation is complete.
This way, the cache will have a complete collection of pre-built software for some commits, but the underpowered architecture will never become backlogged in ancient revisions.
UANT7MOVK62YKFDQ5AJU2XETFKPUAEMJ4WJPRNJ7OJXN2E6DOFLQC K6CGDFOTL2YODZPNT36RKQ3JW435323R52LLNWW4XELWR4JRDH3AC W4G5MZZSCK7VGSZJQKLS6XMQPFDIL7D542XWDMFMO4RZEO4FQB2QC 4YCF3KBGI4VYKHJXAREJLCJLY3UWB2FX447CJ4XQWFRKRFKG5WCQC C3AG65SWAGDSML5MBD4ZPRCHI2LNNDN6IQZOI3HLYRJRPAW3QPAAC 3HZY24CX4U2TO74HOY4YX3LBJIYF4DLXHCIY7J2RASAC4COMSMZAC ODNCGFQ5FPKFI624BVMLW7PJ2EFJOR3TY66OCZM42UNNTWBCF2TQC OX6NYJDVCDX2UCJ4QQMTRJVZ535NOMCJGYCHDLCADJPQI7RMCXPQC PCKLFRT5IZVLG47GQQ23GBSROKUR4CUEZW4PRVGREHNDFTCZ7VBAC N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC FYO6NECE4YJC76HQIG35NNJABODV7KNQKREK5YKZU6O2MNNSQTMAC ("select project, j.name, lastCheckedTime, triggerTime, checkInterval from Jobsets j join Projects p on j.project = p.name "
("select project, j.name, lastCheckedTime, triggerTime, checkInterval, j.enabled as jobset_enabled from Jobsets j join Projects p on j.project = p.name "
if (jobset.lastCheckedTime + jobset.checkInterval <= time(0)) {// Time to schedule a fresh evaluationreturn true;
if (jobset.evaluation_style == EvaluationStyle::ONE_AT_A_TIME) {auto evaluation_res = txn.parameterized("select id from JobsetEvals ""where project = $1 and jobset = $2 ""order by id desc limit 1")(jobset.name.first)(jobset.name.second).exec();if (evaluation_res.empty()) {// First evaluation, so allow scheduling.debug("shouldEvaluate(one-at-a-time) %s:%s? yes: no prior eval",jobset.name.first, jobset.name.second);return true;}auto evaluation_id = evaluation_res[0][0].as<int>();auto unfinished_build_res = txn.parameterized("select id from Builds ""join JobsetEvalMembers "" on (JobsetEvalMembers.build = Builds.id) ""where JobsetEvalMembers.eval = $1 "" and builds.finished = 0 "" limit 1")(evaluation_id).exec();// If the previous evaluation has no unfinished builds// schedule!if (unfinished_build_res.empty()) {debug("shouldEvaluate(one-at-a-time) %s:%s? yes: no unfinished builds",jobset.name.first, jobset.name.second);return true;} else {debug("shouldEvaluate(one-at-a-time) %s:%s? no: at least one unfinished build",jobset.name.first, jobset.name.second);return false;}} else {// EvaluationStyle::ONESHOT, EvaluationStyle::SCHEDULEDdebug("shouldEvaluate(oneshot/scheduled) %s:%s? yes: checkInterval elapsed",jobset.name.first, jobset.name.second);return true;}
<td>[% IF jobset.enabled == 0; "Disabled"; ELSIF jobset.enabled == 1; "Enabled"; ELSIF jobset.enabled == 2; "One-shot"; END %]</td>
<td>[% IF jobset.enabled == 0; "Disabled"; ELSIF jobset.enabled == 1; "Enabled"; ELSIF jobset.enabled == 2; "One-shot"; ELSIF jobset.enabled == 3; "One-at-a-time"; END %]</td>