Skip to content

Commit 26813be

Browse files
committed
Fix replaying journal in tasks with multiple submits
1 parent b021c67 commit 26813be

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
* Fixed crash in auto alloc query in the case of multi-node tasks
1515
* Job and worker IDs are no longer reused after the server is restarted from a pruned journal
16+
* Fixes invalid counters when journal restores job with multiple submits
1617

1718

1819
## v0.27.0

‎crates/hyperqueue/src/server/restore.rs‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn is_task_completed(tasks: &Map<JobTaskId, RestorerTaskInfo>, task_id: JobTaskI
5252

5353
impl RestorerJob {
5454
pub fn restore_job(
55-
mut self,
55+
self,
5656
job_id: JobId,
5757
state: &mut State,
5858
server_ref: &ServerRef,
@@ -76,18 +76,22 @@ impl RestorerJob {
7676
submit.submitted_at(),
7777
);
7878
let job = state.get_job_mut(job_id).unwrap();
79+
let submitted_ids: Vec<JobTaskId> =
80+
new_tasks.tasks.iter().map(|t| t.id.job_task_id()).collect();
7981

8082
new_tasks.tasks.retain_mut(|t| {
8183
t.task_deps
8284
.retain(|d| !is_task_completed(&self.tasks, d.job_task_id()));
8385
!is_task_completed(&self.tasks, t.id.job_task_id())
8486
});
8587

86-
for (task_id, job_task) in job.tasks.iter_mut() {
87-
if let Some(task) = self.tasks.get_mut(task_id) {
88+
for task_id in submitted_ids {
89+
if let (Some(task), Some(job_task)) =
90+
(self.tasks.get(&task_id), job.tasks.get_mut(&task_id))
91+
{
8892
if task.crash_counter > 0 || task.instance_id.is_some() {
8993
new_tasks.adjust_instance_id_and_crash_counters.insert(
90-
TaskId::new(job_id, *task_id),
94+
TaskId::new(job_id, task_id),
9195
(
9296
task.instance_id.map(|x| x.as_num() + 1).unwrap_or(0).into(),
9397
task.crash_counter,

‎tests/test_journal.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,35 @@ def test_restore_open_job_more_submits(hq_env: HqEnv, tmp_path):
305305
wait_for_job_state(hq_env, 1, "OPENED")
306306

307307

308+
def test_restore_open_job_more_submits_counters(hq_env: HqEnv, tmp_path):
309+
journal_path = os.path.join(tmp_path, "my.journal")
310+
311+
hq_env.start_server(args=["--journal", journal_path])
312+
w = hq_env.start_worker()
313+
hq_env.command(["job", "open"])
314+
hq_env.command(["job", "submit", "--job=1", "--array=0-1", "--", "uname"])
315+
wait_for_task_state(hq_env, 1, [0, 1], ["finished", "finished"])
316+
hq_env.command(["worker", "stop", "1"])
317+
wait_for_worker_state(hq_env, 1, "STOPPED", check_running_processes=False)
318+
hq_env.check_process_exited(w)
319+
for _ in range(2):
320+
hq_env.command(["job", "submit", "--job=1", "--", "uname"])
321+
322+
expected = {"aborted": 0, "canceled": 0, "failed": 0, "finished": 2, "running": 0, "waiting": 2}
323+
out = hq_env.command(["--output-mode=json", "job", "info", "1"], as_json=True)
324+
assert out[0]["info"]["task_stats"] == expected
325+
hq_env.stop_server()
326+
327+
hq_env.start_server(args=["--journal", journal_path])
328+
out = hq_env.command(["--output-mode=json", "job", "info", "1"], as_json=True)
329+
assert out[0]["info"]["task_stats"] == expected
330+
331+
hq_env.start_worker()
332+
wait_for_task_state(hq_env, 1, [2, 3], ["finished", "finished"])
333+
out = hq_env.command(["--output-mode=json", "job", "info", "1"], as_json=True)
334+
assert out[0]["info"]["task_stats"]["finished"] == 4
335+
336+
308337
def test_restore_streaming(hq_env: HqEnv, tmp_path):
309338
journal_path = os.path.join(tmp_path, "my.journal")
310339
stream_path = os.path.join(tmp_path, "stream")

0 commit comments

Comments
 (0)