main
ts 44 lines 1.42 KB
Raw
1 import { Worker } from 'node:worker_threads'
2 import { Stats } from 'node:fs'
3 import { PendingPromise, pendingPromise } from './cross'
4 import { quitting } from './first'
5
6 // all stat requests for the same worker are serialized, potentially introducing extra latency
7
8 const pool = new Map<string, (path: string) => Promise<Stats>>()
9
10 export function getStatWorker(key: string) {
11 if (quitting)
12 return () => Promise.reject('quitting')
13 const existing = pool.get(key)
14 if (existing)
15 return existing
16 const worker = new Worker(__dirname + '/statWorker.js')
17 worker.unref()
18 const requests = new Map<string, PendingPromise<Stats>>()
19 worker.on('message', (msg: any) => { // request finished, good or bad
20 const k = msg.path
21 requests.get(k)?.resolve(msg.error ? Promise.reject(Error(msg.error))
22 : Object.setPrototypeOf(msg.result, Stats.prototype) )
23 requests.delete(k)
24 })
25 worker.on('error', (err) => { // worker failure
26 for (const p of requests.values())
27 p.reject(err)
28 requests.clear()
29 worker.terminate().catch(() => {})
30 pool.delete(key)
31 })
32 pool.set(key, query)
33 return query
34
35 function query(path: string) {
36 const was = requests.get(path)
37 if (was)
38 return was
39 const ret = pendingPromise<Stats>()
40 requests.set(path, ret)
41 worker.postMessage(path)
42 return ret
43 }
44 }