Commit c1c7f7b

Eric Bower  ·  2026-04-29 09:46:08 -0400 EDT
parent 0ce812c
feat(wait): summary of failed tasks and actionable commands to run

This simply prints the failed tasks and shows some commands to run to see what
went wrong.
1 files changed,  +46, -13
+46, -13
......@@ -1477,11 +1477,12 @@ fn wait(cfg: *Cfg, matchers: std.ArrayList(SessionMatch)) !void {
14771477 var max_seen: i32 = 0;
14781478 var zero_match_iters: u32 = 0;
14791479
1480+ var agg_exit_code: u8 = 0;
14801481 while (true) {
1482+ agg_exit_code = 0;
14811483 var sessions = try util.get_session_entries(alloc, cfg.socket_dir);
14821484 var total: i32 = 0;
14831485 var done: i32 = 0;
1484- var agg_exit_code: u8 = 0;
14851486
14861487 for (sessions.items) |session| {
14871488 var found = false;
......@@ -1502,8 +1503,8 @@ fn wait(cfg: *Cfg, matchers: std.ArrayList(SessionMatch)) !void {
15021503 // persist as task_ended_at==0 forever → infinite "still
15031504 // waiting". Count it as done+failed so wait terminates.
15041505 try stderr.print(
1505- "task unreachable: {s} ({s})\n",
1506- .{ session.name, session.error_name orelse "unknown" },
1506+ "[{d}] task unreachable: {s} ({s})\n",
1507+ .{ std.time.timestamp(), session.name, session.error_name orelse "unknown" },
15071508 );
15081509 try stderr.flush();
15091510 agg_exit_code = 1;
......@@ -1511,11 +1512,17 @@ fn wait(cfg: *Cfg, matchers: std.ArrayList(SessionMatch)) !void {
15111512 continue;
15121513 }
15131514 if (session.task_ended_at == 0) {
1514- try stdout.print("waiting task={s}\n", .{session.name});
1515+ try stdout.print(
1516+ "[{d}] waiting task={s}\n",
1517+ .{ std.time.timestamp(), session.name },
1518+ );
15151519 try stdout.flush();
15161520 continue;
15171521 }
1518- try stdout.print("completed task={s} exit_code={d}\n", .{ session.name, session.task_exit_code.? });
1522+ try stdout.print(
1523+ "[{d}] completed task={s} exit_code={d}\n",
1524+ .{ session.task_ended_at.?, session.name, session.task_exit_code.? },
1525+ );
15191526 try stdout.flush();
15201527 if (session.task_exit_code != 0) {
15211528 agg_exit_code = session.task_exit_code orelse 0;
......@@ -1543,14 +1550,7 @@ fn wait(cfg: *Cfg, matchers: std.ArrayList(SessionMatch)) !void {
15431550 max_seen = total;
15441551
15451552 if (total > 0 and total == done) {
1546- if (agg_exit_code == 0) {
1547- try stdout.print("task(s) completed!\n", .{});
1548- } else {
1549- try stdout.print("task(s) failed!\n", .{});
1550- }
1551- try stdout.flush();
1552- std.process.exit(agg_exit_code);
1553- return;
1553+ break;
15541554 }
15551555
15561556 if (max_seen == 0) {
......@@ -1569,6 +1569,39 @@ fn wait(cfg: *Cfg, matchers: std.ArrayList(SessionMatch)) !void {
15691569
15701570 std.Thread.sleep(1000 * std.time.ns_per_ms);
15711571 }
1572+
1573+ if (agg_exit_code == 0) {
1574+ try stdout.print("task(s) completed!\n", .{});
1575+ } else {
1576+ try stdout.print("task(s) failed!\n", .{});
1577+ }
1578+ try stdout.flush();
1579+
1580+ const sessions = try util.get_session_entries(alloc, cfg.socket_dir);
1581+ for (sessions.items) |session| {
1582+ var found = false;
1583+ for (matchers.items) |m| {
1584+ if (m.matches(session.name)) {
1585+ found = true;
1586+ break;
1587+ }
1588+ }
1589+ if (!found) {
1590+ continue;
1591+ }
1592+ if (session.task_exit_code.? > 0) {
1593+ try stdout.print("---\n", .{});
1594+ try stdout.print("[{d}] failed task={s} exit_status={d}\n\n", .{
1595+ session.task_ended_at.?,
1596+ session.name,
1597+ session.task_exit_code.?,
1598+ });
1599+ try stdout.print("See the logs:\nzmx history {s}\nzmx attach {s}\n", .{ session.name, session.name });
1600+ try stdout.flush();
1601+ }
1602+ }
1603+
1604+ std.process.exit(agg_exit_code);
15721605 }
15731606
15741607 fn list(cfg: *Cfg, short: bool) !void {