todos-contra-el-fuego-web/imports/startup/server/calcUnionAsync.js
vjrj 324936242b
All checks were successful
build-image / build (push) Successful in 12m9s
fix(subsUnion): resolve turf deps by absolute path, not bare specifier
The previous side-effect-import fix didn't work: the app's own npm deps
(installed by `meteor build`) live in programs/server/npm/node_modules,
a SIBLING of programs/server/assets, not an ancestor of it. Node's
require() only walks up parent directories looking for node_modules,
so require('@turf/circle') from the worker asset script could never
find it regardless of what gets imported elsewhere in the app — it
kept failing with "Cannot find module '@turf/circle'" even after that
fix was deployed.

calcUnionAsync.js (Meteor-compiled code, which already knows how to
locate the app's npm deps) now resolves the three turf package paths
itself and hands them to the worker via workerData; the worker
requires them by absolute path instead of bare specifier.
2026-07-30 08:48:50 +02:00

45 lines
1.9 KiB
JavaScript

import path from 'path';
import { Worker } from 'worker_threads';
const WORKER_PATH = path.resolve(process.cwd(), 'assets/app/workers/unionWorker.js');
// The app's own npm dependencies (installed by `meteor build`) live in
// programs/server/npm/node_modules — a directory that's a SIBLING of
// programs/server/assets, not an ancestor of it. Node's require() only walks
// up parent directories looking for node_modules, so a plain
// require('@turf/circle') from the worker script (a raw asset, not part of
// Meteor's own module system that knows about this layout) can never find it
// and fails with "Cannot find module '@turf/circle'". Resolving the absolute
// path here, where Meteor's own module system already knows how to find it,
// and handing it to the worker sidesteps that entirely.
const NPM_MODULES = path.resolve(process.cwd(), 'programs/server/npm/node_modules');
const turfPaths = {
circle: path.join(NPM_MODULES, '@turf/circle'),
union: path.join(NPM_MODULES, '@turf/union'),
truncate: path.join(NPM_MODULES, '@turf/truncate')
};
/**
* 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, turfPaths } });
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;