Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

Give every job of one graceful cancel the same deadline

cancelInternal read Date.now() per job, so two running jobs could get
cancel_at values a millisecond apart. The alarm for the earlier deadline
then stopped only the first job, and the runtime test that cancels two
running jobs failed now and then.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WEy3wQ4DbP2VQUmrcNhTKn
Claude authored signed1 parent 130fc4acommit 0c91e82058c6e2f19bbd8e2371a51415136e838fBrowse files
1 file changed+2−1
modifiedapps/diffinery/src/repo/actions.ts+2−1View file
@@ -2115,9 +2115,10 @@
21152115 const run = this.runRow(runId);
21162116 if (run.status === "completed") return;
21172117 this.sql.exec("UPDATE runs SET conclusion = 'cancelled', updated_at = ? WHERE id = ?", now(), run.id);
2118+ // One cancel, one deadline: the jobs it lets run their after-cancel steps all end together.
2119+ const at = Date.now();
21182120 for (const j of this.sql.exec<JobRow>("SELECT * FROM jobs WHERE run_id = ? AND status != 'completed'", run.id).toArray()) {
21192121 if (graceful && !j.cancel_at && j.status === "in_progress" && !j.labels && j.container && !j.container.startsWith("self-hosted:")) {
2120- const at = Date.now();
21212122 this.sql.exec("UPDATE jobs SET cancel_at = ?, cancel_reason = ? WHERE id = ?", at, reason, j.id);
21222123 await this.stopContainer(j, true);
21232124 this.repo.alarmBy(at + CANCEL_STOP_MS);