refactor: deduplicate sleep helpers into src/utils (#399)
This commit is contained in:
@@ -20,6 +20,7 @@ import { randomUUID } from 'node:crypto';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import type { AgentStore, LastMessageTarget } from './types.js';
|
||||
import { getDataDir } from '../utils/paths.js';
|
||||
import { sleepSync } from '../utils/time.js';
|
||||
import { createLogger } from '../logger.js';
|
||||
|
||||
const log = createLogger('Store');
|
||||
@@ -28,7 +29,6 @@ const DEFAULT_STORE_PATH = 'lettabot-agent.json';
|
||||
const LOCK_RETRY_MS = 25;
|
||||
const LOCK_TIMEOUT_MS = 5_000;
|
||||
const LOCK_STALE_MS = 30_000;
|
||||
const SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));
|
||||
|
||||
interface StoreV2 {
|
||||
version: 2;
|
||||
@@ -40,23 +40,6 @@ interface ParsedStore {
|
||||
wasV1: boolean;
|
||||
}
|
||||
|
||||
let warnedAboutBusyWait = false;
|
||||
|
||||
function sleepSync(ms: number): void {
|
||||
if (typeof Atomics.wait === 'function') {
|
||||
Atomics.wait(SLEEP_BUFFER, 0, 0, ms);
|
||||
return;
|
||||
}
|
||||
if (!warnedAboutBusyWait) {
|
||||
log.warn('Atomics.wait unavailable, falling back to busy-wait for lock retries');
|
||||
warnedAboutBusyWait = true;
|
||||
}
|
||||
const end = Date.now() + ms;
|
||||
while (Date.now() < end) {
|
||||
// Busy-wait fallback -- should not be reached in standard Node.js (v8+)
|
||||
}
|
||||
}
|
||||
|
||||
export class Store {
|
||||
private readonly storePath: string;
|
||||
private readonly lockPath: string;
|
||||
@@ -197,7 +180,9 @@ export class Store {
|
||||
if (Date.now() - start >= LOCK_TIMEOUT_MS) {
|
||||
throw new Error(`Timed out waiting for store lock: ${this.lockPath}`);
|
||||
}
|
||||
sleepSync(LOCK_RETRY_MS);
|
||||
sleepSync(LOCK_RETRY_MS, () => {
|
||||
log.warn('Atomics.wait unavailable, falling back to busy-wait for lock retries');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
import { isLettaApiUrl } from './utils/server.js';
|
||||
import { getDataDir, getWorkingDir, hasRailwayVolume } from './utils/paths.js';
|
||||
import { parseCsvList, parseNonNegativeNumber } from './utils/parse.js';
|
||||
import { sleep } from './utils/time.js';
|
||||
import { createLogger, setLogLevel } from './logger.js';
|
||||
|
||||
const log = createLogger('Config');
|
||||
@@ -211,10 +212,6 @@ const DISCOVERY_LOCK_TIMEOUT_MS = 15_000;
|
||||
const DISCOVERY_LOCK_STALE_MS = 60_000;
|
||||
const DISCOVERY_LOCK_RETRY_MS = 100;
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function getDiscoveryLockPath(agentName: string): string {
|
||||
const safe = agentName
|
||||
.trim()
|
||||
|
||||
16
src/utils/time.test.ts
Normal file
16
src/utils/time.test.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { sleep, sleepSync } from './time.js';
|
||||
|
||||
describe('sleep', () => {
|
||||
it('waits asynchronously', async () => {
|
||||
const start = Date.now();
|
||||
await sleep(10);
|
||||
expect(Date.now() - start).toBeGreaterThanOrEqual(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sleepSync', () => {
|
||||
it('does not throw for zero delay', () => {
|
||||
expect(() => sleepSync(0)).not.toThrow();
|
||||
});
|
||||
});
|
||||
25
src/utils/time.ts
Normal file
25
src/utils/time.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Shared timing helpers used across startup and persistence paths.
|
||||
*/
|
||||
|
||||
const SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));
|
||||
let warnedAboutBusyWait = false;
|
||||
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export function sleepSync(ms: number, onBusyWait?: () => void): void {
|
||||
if (typeof Atomics.wait === 'function') {
|
||||
Atomics.wait(SLEEP_BUFFER, 0, 0, ms);
|
||||
return;
|
||||
}
|
||||
if (!warnedAboutBusyWait) {
|
||||
onBusyWait?.();
|
||||
warnedAboutBusyWait = true;
|
||||
}
|
||||
const end = Date.now() + ms;
|
||||
while (Date.now() < end) {
|
||||
// Busy-wait fallback -- should not be reached in standard Node.js (v8+)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user