Chore: dispatch write to workers

This commit is contained in:
SukkaW
2026-08-02 00:09:56 +08:00
parent 6d8070d5f3
commit fa9c02d27d
9 changed files with 528 additions and 199 deletions

View File

@@ -0,0 +1,37 @@
import { workerJob } from '../../trace';
import type { RawSpan, WorkerJobResult } from '../../trace';
import { resolveStrategyOutputPath, reviveStrategy, writeDataToStrategies } from './strategy-write-data';
import type { OutputWorkerPayload } from './strategy-write-data';
/**
* The off-main-thread half of FileOutput#write. Everything from "raw collections"
* to "bytes on disk" happens here: punycode, keyword filtering, sorting, the
* per-strategy format fanout (incl. the sing-box JSON stringify), banner and
* content hash, compare and write. All fs calls are synchronous on purpose --
* blocking this worker thread is free, and it avoids bouncing libuv completions
* off a busy main-thread event loop.
*/
export function writeOutput(rawSpan: RawSpan | undefined, payload: OutputWorkerPayload): Promise<WorkerJobResult<void>> {
return workerJob(rawSpan, (span) => {
const strategies = payload.strategies.map(reviveStrategy);
span.traceChildSync('write to strategies', () => writeDataToStrategies(payload.data, strategies));
const date = new Date(payload.dateMs);
return span.traceChildAsync('output to disk', async (childSpan) => {
// Sequential on purpose: the writes are synchronous, so there is nothing to
// overlap, and this keeps the emitted trace in strategy order.
for (let i = 0, len = strategies.length; i < len; i++) {
const strategy = strategies[i];
const filePath = resolveStrategyOutputPath(strategy, payload.id);
// eslint-disable-next-line no-await-in-loop -- see above
await childSpan.traceChildAsync(
'write ' + strategy.name,
(strategySpan) => strategy.outputInWorker(strategySpan, payload.title, payload.description, date, filePath)
);
}
});
});
}