From dfaa7f26798b7037b90174c5a8521dbe89e2abcd Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Jan 03 2015 14:48:31 +0000 Subject: [scheduler] Prioritize packages with last build failed --- diff --git a/config.cfg.template b/config.cfg.template index 4ea59b7..22be334 100644 --- a/config.cfg.template +++ b/config.cfg.template @@ -37,6 +37,7 @@ config = { "newly_added": 3000, # should be higher than the threshold "build_threshold": 256, "package_update": 256, + "failed_build_priority": 200, "t0": 6, "t1": 7 * 24, }, diff --git a/koschei/scheduler.py b/koschei/scheduler.py index 733fe86..0071ae4 100644 --- a/koschei/scheduler.py +++ b/koschei/scheduler.py @@ -21,7 +21,8 @@ from __future__ import print_function import math from datetime import datetime -from sqlalchemy import func, union_all, extract, cast, Integer, case, null +from sqlalchemy import (func, union_all, extract, cast, Integer, case, null, + literal_column) from sqlalchemy.sql.functions import coalesce from . import util @@ -39,6 +40,7 @@ class Scheduler(KojiService): priority_conf = util.config['priorities'] priority_threshold = priority_conf['build_threshold'] + failed_priority = priority_conf['failed_build_priority'] max_builds = util.config['koji_config']['max_builds'] load_threshold = util.config['koji_config']['load_threshold'] @@ -67,6 +69,21 @@ class Scheduler(KojiService): time_expr.label('priority'))\ .group_by(Build.package_id) + def get_failed_build_priority_query(self): + rank = func.rank().over(partition_by=Package.id, + order_by=Build.task_id.desc()).label('rank') + sub = self.db.query(Package.id.label('pkg_id'), Build.state, rank)\ + .outerjoin(Build, + Package.id == Build.package_id)\ + .subquery() + return self.db.query(sub.c.pkg_id, + literal_column(str(self.failed_priority)) + .label('priority'))\ + .filter(((sub.c.rank == 1) & (sub.c.state == 5)) | + ((sub.c.rank == 2) & (sub.c.state != 5)))\ + .group_by(sub.c.pkg_id)\ + .having(func.count(sub.c.pkg_id) == 2) + def get_priority_queries(self): prio = (('manual', Package.manual_priority), ('static', Package.static_priority)) @@ -75,6 +92,7 @@ class Scheduler(KojiService): for name, col in prio} priorities['dependency'] = self.get_dependency_priority_query() priorities['time'] = self.get_time_priority_query() + priorities['failed_build'] = self.get_failed_build_priority_query() return priorities def get_scheduled_package(self): diff --git a/test/common.py b/test/common.py index ab1396a..d6da350 100644 --- a/test/common.py +++ b/test/common.py @@ -125,7 +125,7 @@ class DBTest(AbstractTest): self.s.commit() return pkgs - def prepare_builds(self, repo_id, **builds): + def prepare_builds(self, repo_id=1, **builds): new_builds = [] for pkg_name, state in sorted(builds.items()): states = { diff --git a/test/scheduler_test.py b/test/scheduler_test.py index 8b4e844..8387641 100644 --- a/test/scheduler_test.py +++ b/test/scheduler_test.py @@ -74,7 +74,7 @@ class SchedulerTest(DBTest): self.s.add(pkg) self.s.flush() build = m.Build(package_id=pkg.id, - started=MockDatetime.now() - timedelta(days, hours=1)) + started=MockDatetime.now() - timedelta(days, hours=1)) self.s.add(build) self.s.commit() query = self.get_scheduler().get_time_priority_query() @@ -86,6 +86,17 @@ class SchedulerTest(DBTest): for item, exp in zip(res, expected_prios): self.assertAlmostEqual(exp, item.priority) + @postgres_only + def test_failed_build_priority(self): + pkgs = self.prepare_packages(['rnv', 'eclipse', 'fop', 'i3']) + self.prepare_builds(rnv=True, eclipse=False, i3=True) + self.prepare_builds(rnv=False, eclipse=False, fop=False) + query = self.get_scheduler().get_failed_build_priority_query() + # fop has 1 failed build with no previous one, should it be prioritized? + # self.assertItemsEqual([(pkgs[0].id, 200), (pkgs[1].id, 200)], + # query.all()) + self.assertItemsEqual([(pkgs[0].id, 200)], query.all()) + @contextmanager def prio_table(self, tablename='tmp', **kwargs): try: