訂判斷及所需輸入
有限示範真的用5 毫秒上層逾時及一個本地 Worker。只有上層逾時,觀察時子仍跑。題內要求連子也取消,更正須等終止完成,才有 childExited=true。
| 情況 | 輸入 JSON |
|---|---|
| 原例測試 | {"timeoutMs":5,"cancelChild":true} |
跑所附比較
執行緒先報 ready 才開始計時,觀察後清理其餘工作,不留下背景任務。短測試不是五分鐘正式期限保證。
| 路徑 | 輸出 JSON |
|---|---|
| 錯誤路徑 | {"parent":"timed-out","childExited":false} |
| 所需路徑 | {"parent":"timed-out","childExited":true} |
import assert from 'node:assert/strict';
const smallWhole=(x,max)=>Number.isSafeInteger(x)&&x>=0&&x<=max;
import {Worker} from 'node:worker_threads';
const run=async function run(i,corrected=true){
if(typeof i.cancelChild!=='boolean'||!smallWhole(i.timeoutMs,20))return {held:true};
const worker=new Worker('const {parentPort}=require("node:worker_threads");parentPort.postMessage("ready");setInterval(()=>{},1000);',{eval:true});
try{await new Promise(resolve=>worker.once('message',resolve));await new Promise(resolve=>setTimeout(resolve,i.timeoutMs));
if(corrected&&i.cancelChild)await worker.terminate();return {parent:'timed-out',childExited:worker.threadId===-1};
}finally{if(worker.threadId!==-1)await worker.terminate();}
};
const cases=[{"input":{"timeoutMs":5,"cancelChild":true},"corrected":false,"expected":{"parent":"timed-out","childExited":false}},{"input":{"timeoutMs":5,"cancelChild":true},"corrected":true,"expected":{"parent":"timed-out","childExited":true}},{"input":{"timeoutMs":5,"cancelChild":false},"corrected":true,"expected":{"parent":"timed-out","childExited":false}},{"input":{"timeoutMs":5,"cancelChild":null},"corrected":true,"expected":{"held":true}}];
for(const test of cases){const actual=await run(test.input,test.corrected);assert.deepEqual(actual,test.expected);console.log(actual);}
按邊界依據作判斷
明訂只管上層,觀察時可仍有子工作;子處理方式欠缺,開工作前先停。
- 啟動受控工作執行緒
- 套上層逾時處理
- 清理前核子有沒有退出
只有上層逾時,不能推子已取消。
| 條件 | 輸入 JSON | 預期輸出 JSON |
|---|---|---|
| 明選只管上層逾時 | {"timeoutMs":5,"cancelChild":false} | {"parent":"timed-out","childExited":false} |
| 子工作處理未訂 | {"timeoutMs":5,"cancelChild":null} | {"held":true} |
原例要求停子工作,還要甚麼依據?
查看參考答案
等終止後,真正執行緒已退出。上層 timed-out 標記本身沒有此依據。