All checks were successful
build-image / build (push) Successful in 13m13s
The previous fix (yielding to the event loop between turf.union calls) was not enough: once the merged polygon gets complex with thousands of subscriptions, a single turf.union call can itself take seconds, and yielding between iterations doesn't help when one iteration alone blocks that long. Confirmed in staging: the site was still fully unresponsive (Cloudflare 524, curl hanging 2+ minutes, healthcheck failing) while a recompute ran. Validation/decoration (addNoisy/noNoisy, cheap) stays on the main thread; the actual circle+union chain now runs in a worker_thread (private/workers/unionWorker.js, plain CommonJS so meteor build copies it verbatim instead of compiling it) so the main event loop serving DDP/HTTP is never blocked by it, regardless of how slow any single turf call gets.
28 lines
863 B
JavaScript
28 lines
863 B
JavaScript
import path from 'path';
|
|
import { Worker } from 'worker_threads';
|
|
|
|
const WORKER_PATH = path.resolve(process.cwd(), 'assets/app/workers/unionWorker.js');
|
|
|
|
/**
|
|
* Circle-union of already-validated, already-decorated subscriptions, run in a
|
|
* worker thread so the main event loop (DDP/HTTP) stays free regardless of
|
|
* how long any single turf.union call takes. subs must be an array of plain
|
|
* { location: { lat, lon }, distance } objects.
|
|
*/
|
|
const calcUnionAsync = subs => new Promise((resolve, reject) => {
|
|
const worker = new Worker(WORKER_PATH, { workerData: { subs } });
|
|
worker.once('message', (msg) => {
|
|
worker.terminate();
|
|
if (msg.error) {
|
|
reject(new Error(msg.error));
|
|
} else {
|
|
resolve(msg.union);
|
|
}
|
|
});
|
|
worker.once('error', (err) => {
|
|
worker.terminate();
|
|
reject(err);
|
|
});
|
|
});
|
|
|
|
export default calcUnionAsync;
|