mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-11 09:51:06 +00:00
Count Runs That Move Between Status Lists
A run is listed as pending while any of its jobs waits in a concurrency group, so it moves to in_progress the moment its last gate leaves the line. A check made in those seconds read the in_progress list before the move and the pending list after it, missed the run, and let in a second arch the limit had no room for. Runs created in the last day are now listed by creation time as well, and the run doing the check is read directly. Co-authored-by: raistlin7447 <kris.austin@gmail.com>
This commit is contained in:
co-authored by
raistlin7447
parent
bffb5116a5
commit
24cefcba62
@@ -57,6 +57,8 @@ NIGHTLY_LEAD = datetime.timedelta(minutes=10)
|
||||
NIGHTLY_GRACE = datetime.timedelta(minutes=45)
|
||||
|
||||
ACTIVE = {"queued", "in_progress", "waiting", "pending", "requested"}
|
||||
# Runs created this recently are listed whatever their status.
|
||||
RECENT = datetime.timedelta(hours=24)
|
||||
FAILURES_BEFORE_ADMIT = 3
|
||||
|
||||
|
||||
@@ -164,9 +166,16 @@ def measure(api, repo, workflow, run_id, now, priority=False):
|
||||
total, lines = 0, []
|
||||
# A run is listed as queued whenever one of its jobs waits for a runner, and
|
||||
# as pending whenever one waits in a concurrency group, so runs in any of these
|
||||
# can hold runners. A run can move between the lists between the calls.
|
||||
# can hold runners. A run that moves between the lists between the calls is
|
||||
# in neither, as one is whenever the job ahead of this one leaves the line, so
|
||||
# runs created recently are listed by creation time as well, and this run is
|
||||
# read directly.
|
||||
since = (now - RECENT).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
runs = {run["id"]: run for status in ("in_progress", "queued", "pending", "waiting")
|
||||
for run in list_runs(api, repo, workflow, status=status)}
|
||||
runs.update((run["id"], run) for run in list_runs(api, repo, workflow, created=f">={since}")
|
||||
if run["status"] != "completed")
|
||||
runs[run_id] = api.get(f"repos/{repo}/actions/runs/{run_id}")
|
||||
for run in runs.values():
|
||||
jobs = api.get(f"repos/{repo}/actions/runs/{run['id']}/jobs",
|
||||
filter="latest", per_page=100)["jobs"]
|
||||
|
||||
@@ -165,13 +165,16 @@ class FakeApi:
|
||||
|
||||
def get(self, path, **params):
|
||||
self.calls.append((path, params))
|
||||
if path.endswith("/runs") and "status" in params:
|
||||
runs = self.responses.get(("runs", params["status"]), [])
|
||||
if path.endswith("/runs") and ("status" in params or "created" in params):
|
||||
runs = self.responses.get(("runs", params.get("status", "recent")), [])
|
||||
start = (params["page"] - 1) * params["per_page"]
|
||||
return {"total_count": len(runs), "workflow_runs": runs[start:start + params["per_page"]]}
|
||||
if path.endswith("/runs"):
|
||||
return {"workflow_runs": self.responses.get(("runs", params.get("event")), [])[:1]}
|
||||
return {"jobs": self.responses[path]}
|
||||
if path.endswith("/jobs"):
|
||||
return {"jobs": self.responses.get(path, [])}
|
||||
# A run read by its id, by default a pull request with no jobs listed.
|
||||
return self.responses.get(path, dict(PR, id=int(path.rsplit("/", 1)[-1])))
|
||||
|
||||
|
||||
def jobs_path(run_id):
|
||||
@@ -257,6 +260,29 @@ class MeasureTest(unittest.TestCase):
|
||||
total, _ = admission.measure(api, "o/r", "build_all.yml", 2, NOON)
|
||||
self.assertEqual(total, 0)
|
||||
|
||||
def test_counts_its_own_run_when_no_status_list_has_it(self):
|
||||
# The run moves from pending to in_progress as its last gate leaves the
|
||||
# line, and is in neither list while that gate checks.
|
||||
jobs = [gate("x86_64"), build("x86_64", "queued"), gate("arm64", "in_progress", None)]
|
||||
api = FakeApi({jobs_path(2): jobs})
|
||||
self.assertEqual(admission.measure(api, "o/r", "build_all.yml", 2, NOON)[0], 1)
|
||||
|
||||
def test_counts_a_recent_run_that_no_status_list_has(self):
|
||||
api = FakeApi({("runs", "recent"): [PR], jobs_path(2): [gate("arm64"), build("arm64")]})
|
||||
self.assertEqual(admission.measure(api, "o/r", "build_all.yml", 99, NOON)[0], 1)
|
||||
|
||||
def test_lists_recent_runs_from_a_day_before(self):
|
||||
api = FakeApi({})
|
||||
admission.measure(api, "o/r", "build_all.yml", 99, NOON)
|
||||
self.assertIn(">=2026-10-09T12:00:00Z", [params.get("created") for _, params in api.calls])
|
||||
|
||||
def test_finished_recent_runs_are_not_read(self):
|
||||
done = dict(PUSH, status="completed")
|
||||
api = FakeApi({("runs", "recent"): [done]})
|
||||
total, _ = admission.measure(api, "o/r", "build_all.yml", 99, NOON)
|
||||
self.assertEqual(total, 0)
|
||||
self.assertNotIn(jobs_path(1), [path for path, _ in api.calls])
|
||||
|
||||
def test_no_nightly_lookup_outside_its_window(self):
|
||||
api = FakeApi({})
|
||||
admission.measure(api, "o/r", "build_all.yml", 99, NOON)
|
||||
|
||||
Reference in New Issue
Block a user