Skip to content

murdock: implement numeric priorities#18

Open
kaspar030 wants to merge 10 commits intomainfrom
switch_to_priority_queue
Open

murdock: implement numeric priorities#18
kaspar030 wants to merge 10 commits intomainfrom
switch_to_priority_queue

Conversation

@kaspar030
Copy link
Contributor

@kaspar030 kaspar030 commented Nov 15, 2022

This PR drops the fasttrack queue and turns the "regular" queue into a priority queue.
It adds configurable priority modifiers (per-branch, per-label) that get applied to queued or (re-)labeled jobs.

Previously, it was possible to "fasttrack" jobs, moving them ahead of "regular" jobs, essentially supporting two priorities.
With this PR, the job priority becomes numeric. This is limiting.

As an actual use-case, RIOT will move to bors for builds that should get merged, but non-bors quickbuilds for PRs.
The bors builds are expected to take >2hrs, whereas the quickbuilds are below 5min.
PR builds should be prioritized over the long bors builds.
Up to this point, two priorities work fine (fasttrack all PR builds).

Now it would be great if some PR builds could be set to a lower priority (for contributors that want to use CI for build testing without hampering workflow), or even higher priority (for important backports or CI fixes).
Also, it would be great if e.g., adding the "CI: high priority") label would update the job's queue position.
And, if "can_fast_ci_build.py" determines a subset build, the priority can be dynamically adapted.

So this PR implements the following changes:

  • replace the fasttrack and regular queues with one priority queue
  • adds a "priority" field to MurdockJob
  • add an __lt() implementation to MurdockJob (making it sort by priority)
  • make MurdockJob calculate it's priority based on priorities: repo-level (.murdock.yml) configuration
  • adds priorities: .murdock.yml configuration
  • implements requeuing on label change (if the priority changes)

@kaspar030 kaspar030 force-pushed the switch_to_priority_queue branch from 3f46e81 to cc9e821 Compare November 15, 2022 13:16
@kaspar030 kaspar030 marked this pull request as ready for review November 15, 2022 13:16
@codecov
Copy link

codecov bot commented Nov 15, 2022

Codecov Report

Base: 96.35% // Head: 95.14% // Decreases project coverage by -1.21% ⚠️

Coverage data is based on head (2a879d7) compared to base (3ad1537).
Patch coverage: 68.18% of modified lines in pull request are covered.

❗ Current head 2a879d7 differs from pull request most recent head 429950f. Consider uploading reports for the commit 429950f to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #18      +/-   ##
==========================================
- Coverage   96.35%   95.14%   -1.21%     
==========================================
  Files          26       21       -5     
  Lines        3097     2596     -501     
  Branches      362      311      -51     
==========================================
- Hits         2984     2470     -514     
- Misses         81       88       +7     
- Partials       32       38       +6     
Impacted Files Coverage Δ
murdock/job.py 86.86% <50.00%> (-4.24%) ⬇️
murdock/murdock.py 84.42% <72.72%> (ø)
murdock/config.py 100.00% <100.00%> (ø)
murdock/models.py 100.00% <100.00%> (ø)
murdock/task.py 74.64% <0.00%> (-1.03%) ⬇️
murdock/job_containers.py 99.02% <0.00%> (-0.98%) ⬇️
murdock/github.py 94.91% <0.00%> (-0.37%) ⬇️
murdock/tests/conftest.py 100.00% <0.00%> (ø)
... and 16 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@kaspar030
Copy link
Contributor Author

Ok, I've added a priority field to MurdockJob.
I've left the logic on how to set the priority value a bit open, there's now a calculate_priority() static_method on MurdockJob, which currently only takes the fasttrack label into account.

We can discuss whether fasttracking is needed at all, but maybe it's nice to have it as "build that next" hammer.

@aabadie how does the added JobModel field interact with the existing database?

@kaspar030 kaspar030 changed the title murdock: drop fasttrack_queue, use PriorityQueue murdock: implement numeric priorities Nov 22, 2022
@kaspar030
Copy link
Contributor Author

kaspar030 commented Nov 22, 2022

As for how to set priorities, I'd suggest (as discussed before with @aabadie) configuration in .murdock.yml:

priorities:
  labels:
    "CI: high priority": 10
    "CI: low priority": -10
  branches:
    trying: -1
    staging: -1

@kaspar030
Copy link
Contributor Author

adding the priority configuration was straight-forward.
I might need some help with adding tests, I don't understand the test suite (yet).

else False
) # type: ignore[union-attr]
self.priority: int = MurdockJob.calculate_priority(
config, pr, ref, self.fasttracked
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these function parameters are already instance attributes. Thus there's no need for calculate_priority to be a staticmethod. A regular instance method, private, should be enough def _priority(self): and use self.config, self.pr, self.ref and self.fastracked inside.

Copy link
Contributor

@aabadie aabadie Nov 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that an @property method could also be used but it would recompute the priority each time it's accessed. Maybe that's better I don't know

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure, can safely use a class method within __init__()?
(Also it needs to be public so it can react to label changes.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can safely use a class method within init()?

yes, if the method is accessing already defined/initialized attributes.

it needs to be public so it can react to label changes

then I think a property method is more appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a property method would make e.g., "job.priority" actually call the method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assuming the pr field of a job is a reference to updated PR data.
if that's not the case, it's easier to have this staticmethod and supply all needed data at the call site.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you requeue ? In the current state, a new MurdockJob instance is created and the previous matching ones are marked as cancelled.

I also thought that the display order must also be taken into account. This is something that is in another data structure, a simple list. So a sort on priority must be added there.

https://github.com/murdock-ng/murdock/blob/e62397d29e8ffe1ded2bbb2dd0a7f7a0c49ee853/murdock/murdock.py#L561-569

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add re-queueing here:

if action == "labeled":

(if the job is queued, re-calc its priority and compare to the queued one. if it has changed, don't "return" but fall through to "schedule_job()", which would cancel the old job and create a new, sorted into the queue by priority.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit lost. What is the use case exactly ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR blew up from just replacing two unprioritized queues with one prioritized, to making full use of that change. :( I'll update the description.

@aabadie
Copy link
Contributor

aabadie commented Nov 24, 2022

I might need some help with adding tests, I don't understand the test suite (yet).

The test suite is becoming huge I admit. Maybe start by adding a test function in test_job.py to check the job.priority attribute depending on certain cases. Using pytest.mark.parametrize will be useful I think.

To run the tests, just install tox (pip install tox) and run tox. You can give a parameter which the name of the test to skip the others, like tox murdock/tests/test_job.py to only the tests that related to the MurdockJob class.

@kaspar030
Copy link
Contributor Author

  • changed the "priorities" settings to always have sane defaults (eases accessing them instead of checking for optionals)
  • implemented priority label changes (thanks @aabadie for the discussion, much simpler now than my first iteration)
  • changed get_queued_jobs() to also sort by job.priority

@aabadie
Copy link
Contributor

aabadie commented Feb 25, 2023

This needs a rebase!

@kaspar030 kaspar030 force-pushed the switch_to_priority_queue branch from e0c1b29 to 50b9627 Compare February 25, 2023 22:06
if label_name not in config.priorities.labels.keys():
return
elif not self.queued.search_by_pr_number(pull_request.number):
# skip re-queing if there's no queued job
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny typo:

Suggested change
# skip re-queing if there's no queued job
# skip re-queuing if there's no queued job

@aabadie
Copy link
Contributor

aabadie commented Mar 1, 2023

This also needs another rebase, sorry. There are also some failures reported by the CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants