All checks were successful
build-image / build (push) Successful in 13m24s
A full recreate() over 7k+ subscriptions takes ~20 minutes even in a worker thread — fine for not blocking the site, but means a new zone takes ages to show up on the map. Since union only grows when adding a circle, a new subscription can just be merged into the union already stored (one turf.union call) instead of rebuilding the whole chain. changed/removed still trigger a full recreate() (union can't be "subtracted" from safely), and incrementalAdd falls back to a full recreate whenever the stored count isn't exactly one behind what's expected, rather than risk merging into stale state. Both paths now share one serialized queue (FIFO for adds, coalesced for recomputes) so they never race on the same stored union.
29 lines
986 B
JavaScript
29 lines
986 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. If baseUnion is given, subs
|
|
* are merged into it instead of a union computed from scratch.
|
|
*/
|
|
const calcUnionAsync = (subs, baseUnion = null) => new Promise((resolve, reject) => {
|
|
const worker = new Worker(WORKER_PATH, { workerData: { subs, baseUnion } });
|
|
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;
|