Refactor: Ensure heartbeat alarm is always cleared

This commit is contained in:
2025-11-06 19:36:45 -08:00
parent 0c6bef335b
commit fe7eb38253

View File

@@ -82,6 +82,15 @@ export class MyDurableObject {
bcast(obj) { this.sockets.forEach(ws => this.send(ws, obj)); }
notify(msg, pri = 3, tags = []) {
if (!this.env.NTFY_TOPIC) return;
this.state.waitUntil(fetch(`https://ntfy.sh/${this.env.NTFY_TOPIC}`, {
method: 'POST',
body: msg,
headers: { 'Title': 'Sune ORP', 'Priority': `${pri}`, 'Tags': tags.join(',') },
}).catch(e => console.error('ntfy failed:', e)));
}
async autopsy() {
if (this.rid) return;
const snap = await this.state.storage.get('run').catch(() => null);
@@ -103,6 +112,7 @@ export class MyDurableObject {
this.phase = 'evicted';
this.error = 'The run was interrupted due to system eviction.';
this.saveSnapshot();
this.notify(`Run ${this.rid} evicted`, 4, ['warning']);
await this.stopHeartbeat();
}
}
@@ -337,6 +347,7 @@ export class MyDurableObject {
try { this.oaStream?.controller?.abort(); } catch {}
this.saveSnapshot();
this.bcast({ type: 'err', message: this.error });
this.notify(`Run ${this.rid} failed: ${this.error}`, 4, ['rotating_light']);
this.state.waitUntil(this.stopHeartbeat());
}
@@ -348,12 +359,14 @@ export class MyDurableObject {
async stopHeartbeat() {
this.hbActive = false;
const ageSeconds = (this.age * HB_INTERVAL_MS) / 1000;
this.notify(`Run ${this.rid} ended. Phase: ${this.phase}. Age: ${ageSeconds.toFixed(1)}s.`, 3, ['stop_sign']);
await this.state.storage.setAlarm(null).catch(() => {});
}
async Heart() {
if (this.phase !== 'running' || !this.hbActive) return this.stopHeartbeat();
if (++this.age * HB_INTERVAL_MS >= MAX_RUN_MS) return this.fail('Run timed out after 15 minutes.');
if (++this.age * HB_INTERVAL_MS >= MAX_RUN_MS) return this.fail(`Run timed out after ${MAX_RUN_MS / 60000} minutes.`);
await this.state.storage.setAlarm(Date.now() + HB_INTERVAL_MS).catch(() => {});
}
@@ -408,4 +421,3 @@ export class MyDurableObject {
return contents;
}
}