diff --git a/AFTER.md b/AFTER.md new file mode 100644 index 0000000..13a9282 --- /dev/null +++ b/AFTER.md @@ -0,0 +1,12 @@ +Benchmarking "node bin/torch-lock.mjs list" (5 iterations)... +Run 1: 5233.54ms +Run 2: 928.75ms +Run 3: 949.99ms +Run 4: 974.20ms +Run 5: 5214.18ms + +Results: + Count: 5 + Average: 2660.13ms + Min: 928.75ms + Max: 5233.54ms diff --git a/BASELINE.md b/BASELINE.md new file mode 100644 index 0000000..bc8f19c --- /dev/null +++ b/BASELINE.md @@ -0,0 +1,12 @@ +Benchmarking "node bin/torch-lock.mjs list" (5 iterations)... +Run 1: 15259.19ms +Run 2: 15255.13ms +Run 3: 15210.17ms +Run 4: 15190.69ms +Run 5: 15182.21ms + +Results: + Count: 5 + Average: 15219.48ms + Min: 15182.21ms + Max: 15259.19ms diff --git a/DIAGNOSIS.md b/DIAGNOSIS.md new file mode 100644 index 0000000..479da90 --- /dev/null +++ b/DIAGNOSIS.md @@ -0,0 +1,24 @@ +# Diagnosis: 15s Execution Floor in Lock Queries + +## Observation +The command `torch-lock list` and other lock operations consistently take slightly over 15 seconds to complete, even when network conditions are good and relays respond quickly (within <1s). + +## Root Cause Analysis +The `queryLocks` function in `src/lock-ops.mjs` uses `Promise.race` to enforce a timeout (default 15s) on relay queries. + +```javascript + const events = await Promise.race([ + pool.querySync(relays, { ... }), + new Promise((_, reject) => + setTimeout(() => reject(new Error('Relay query timed out')), queryTimeoutMs), + ), + ]); +``` + +When `pool.querySync` completes successfully (e.g., in 600ms), the `Promise.race` resolves immediately. However, the `setTimeout` created in the second promise remains active in the Node.js event loop. Node.js processes do not exit as long as there are active handles (like timers). Thus, the process waits for the remaining ~14.4s until the timer fires (and the callback is executed, though ignored) before exiting. + +## Verification +A reproduction script confirmed that `Promise.race` with an uncleared `setTimeout` prevents process exit until the timeout fires. + +## Proposed Fix +Capture the `timeoutHandle` from `setTimeout` and explicitly clear it using `clearTimeout(timeoutHandle)` in the `finally` block of the `queryLocks` function. diff --git a/build.mjs b/build.mjs index 9261b3a..b45245e 100644 --- a/build.mjs +++ b/build.mjs @@ -9,6 +9,7 @@ const DIST_DIR = path.join(__dirname, 'dist'); const LANDING_SRC = path.join(__dirname, 'landing'); const DASHBOARD_SRC = path.join(__dirname, 'dashboard'); const DOCS_SRC = path.join(__dirname, 'src', 'docs'); +const CONSTANTS_SRC = path.join(__dirname, 'src', 'constants.mjs'); const PROMPTS_SRC = path.join(__dirname, 'src', 'prompts', 'META_PROMPTS.md'); const CONFIG_SRC = path.join(__dirname, 'torch-config.json'); const ASSETS_SRC = path.join(__dirname, 'assets'); @@ -42,6 +43,9 @@ const distDocs = path.join(DIST_DIR, 'src', 'docs'); fs.mkdirSync(distDocs, { recursive: true }); fs.cpSync(DOCS_SRC, distDocs, { recursive: true }); +// 3.5. Copy src/constants.mjs -> dist/src/constants.mjs +fs.copyFileSync(CONSTANTS_SRC, path.join(DIST_DIR, 'src', 'constants.mjs')); + // 4. Copy src/prompts/META_PROMPTS.md -> dist/src/prompts/META_PROMPTS.md const distPromptsDir = path.join(DIST_DIR, 'src', 'prompts'); fs.mkdirSync(distPromptsDir, { recursive: true }); diff --git a/dashboard/index.html b/dashboard/index.html index 3a31af8..ec38436 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -152,6 +152,8 @@