Merge pull request #374 from PR0M3TH3AN/refactor/consolidate-with-timeout-3248602754567091205

Consolidate `withTimeout` utility to `src/utils.mjs`
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-20 16:35:19 -05:00
commit c6c25e60e2
7 files changed
+3552 -39

No files matched your search

+1 -11
View File
@@ -8,7 +8,7 @@ import {
KIND_APP_DATA,
MS_PER_SECOND,
} from './constants.mjs';
import { nowUnix } from './utils.mjs';
import { nowUnix, withTimeout } from './utils.mjs';
import { defaultHealthManager, buildRelayHealthConfig, RelayHealthManager } from './relay-health-manager.mjs';
import { publishLock, LockPublisher, secureRandom } from './lock-publisher.mjs';
@@ -55,16 +55,6 @@ function filterActiveLocks(locks) {
return locks.filter((lock) => !lock.expiresAt || lock.expiresAt > now);
}
function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
function relayListLabel(relays) {
return relays.join(', ');
}
+1 -10
View File
@@ -6,18 +6,9 @@ import {
getRelayFallbacks,
getMinActiveRelayPool,
} from './torch-config.mjs';
import { withTimeout } from './utils.mjs';
import { defaultHealthManager, buildRelayHealthConfig } from './relay-health-manager.mjs';
function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
function relayListLabel(relays) {
return relays.join(', ');
}
+2 -10
View File
@@ -1,6 +1,6 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { todayDateStr, getIsoWeekStr } from './utils.mjs';
import { todayDateStr, getIsoWeekStr, withTimeout } from './utils.mjs';
/**
* Scans the local log directory to identify agents that have already completed their task
@@ -48,15 +48,7 @@ export async function getCompletedAgents(cadence, logDir, deps) {
return completed;
}
export function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
export { withTimeout };
export function relayListLabel(relays) {
return relays.join(', ');
+1 -8
View File
@@ -4,17 +4,10 @@ import WebSocket from 'ws';
import { finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools/pure';
import { getNamespace, getRelays } from './torch-config.mjs';
import { MS_PER_SECOND } from './constants.mjs';
import { withTimeout } from './utils.mjs';
const PROBE_KIND = 27235;
function withTimeout(promise, timeoutMs, message) {
let timeoutId;
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timeoutId));
}
function nowIso() {
return new Date().toISOString();
}
+10
View File
@@ -47,3 +47,13 @@ export function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true });
}
}
export function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
+51
View File
@@ -0,0 +1,51 @@
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { withTimeout } from '../src/utils.mjs';
describe('Async Utilities', () => {
describe('withTimeout', () => {
it('resolves when promise completes before timeout', async () => {
const result = await withTimeout(
new Promise((resolve) => setTimeout(() => resolve('success'), 10)),
200,
'Timed out'
);
assert.strictEqual(result, 'success');
});
it('rejects when promise times out', async () => {
try {
await withTimeout(
new Promise((resolve) => setTimeout(() => resolve('success'), 200)),
10,
'Operation timed out'
);
assert.fail('Should have rejected');
} catch (err) {
assert.strictEqual(err.message, 'Operation timed out');
}
});
it('clears timeout on success', async () => {
const result = await withTimeout(
Promise.resolve('fast'),
1000,
'timeout'
);
assert.strictEqual(result, 'fast');
});
it('propagates original promise rejection', async () => {
try {
await withTimeout(
Promise.reject(new Error('Original error')),
100,
'Timeout'
);
assert.fail('Should have rejected');
} catch (err) {
assert.strictEqual(err.message, 'Original error');
}
});
});
});
+3486
View File
File diff suppressed because it is too large. Load diff