-
Notifications
You must be signed in to change notification settings - Fork 413
Cluster fixes #789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Cluster fixes #789
Changes from all commits
48b737f
7776ed3
fe74473
fe9ccad
4ac8805
3e1c116
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||
| * cluster master. | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const { debuglog } = require('node:util'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const Registry = require('./registry'); | ||||||||||||||||||||||||||||||||||||||||||||||
| // We need to lazy-load the 'cluster' module as some application servers - | ||||||||||||||||||||||||||||||||||||||||||||||
| // namely Passenger - crash when it is imported. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -31,17 +32,25 @@ let cluster = () => { | |||||||||||||||||||||||||||||||||||||||||||||
| return data; | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const debug = debuglog('prom:metrics:cluster'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const ANNOUNCEMENT = '@prometheus-io/client:announcement'; | ||||||||||||||||||||||||||||||||||||||||||||||
| const GET_METRICS_REQ = '@prometheus-io/client:getMetricsReq'; | ||||||||||||||||||||||||||||||||||||||||||||||
| const GET_METRICS_RES = '@prometheus-io/client:getMetricsRes'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| let registries = [Registry.globalRegistry]; | ||||||||||||||||||||||||||||||||||||||||||||||
| let requestCtr = 0; // Concurrency control | ||||||||||||||||||||||||||||||||||||||||||||||
| let listenersAdded = false; | ||||||||||||||||||||||||||||||||||||||||||||||
| const requests = new Map(); // Pending requests for workers' local metrics. | ||||||||||||||||||||||||||||||||||||||||||||||
| const workers = new Map(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| class AggregatorRegistry extends Registry { | ||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * Create a Registry. | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param regContentType | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| constructor(regContentType = Registry.PROMETHEUS_CONTENT_TYPE) { | ||||||||||||||||||||||||||||||||||||||||||||||
| super(regContentType); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| addListeners(); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -53,9 +62,9 @@ class AggregatorRegistry extends Registry { | |||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| clusterMetrics() { | ||||||||||||||||||||||||||||||||||||||||||||||
| const requestId = requestCtr++; | ||||||||||||||||||||||||||||||||||||||||||||||
| const workers = Object.values(cluster().workers) | ||||||||||||||||||||||||||||||||||||||||||||||
| .filter(worker => worker.isConnected()) | ||||||||||||||||||||||||||||||||||||||||||||||
| .sort((left, right) => left.id - right.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| const orderedWorkers = [...workers.values()].sort( | ||||||||||||||||||||||||||||||||||||||||||||||
| (left, right) => left.id - right.id, | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| let settled = false; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -78,36 +87,43 @@ class AggregatorRegistry extends Registry { | |||||||||||||||||||||||||||||||||||||||||||||
| responseHandlers, | ||||||||||||||||||||||||||||||||||||||||||||||
| done, | ||||||||||||||||||||||||||||||||||||||||||||||
| errorTimeout: setTimeout(() => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const err = new Error('Operation timed out.'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const err = new Error( | ||||||||||||||||||||||||||||||||||||||||||||||
| `Operation timed out. ${request.responseHandlers.size} outstanding responses.`, | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| request.done(err); | ||||||||||||||||||||||||||||||||||||||||||||||
| }, 5000), | ||||||||||||||||||||||||||||||||||||||||||||||
| }, 5_000), | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
| requests.set(requestId, request); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const message = { | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_REQ, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (workers.length === 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| // No workers were up | ||||||||||||||||||||||||||||||||||||||||||||||
| process.nextTick(() => done(undefined, '')); | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const responsePromises = workers.map( | ||||||||||||||||||||||||||||||||||||||||||||||
| const workerMetrics = orderedWorkers.map( | ||||||||||||||||||||||||||||||||||||||||||||||
| worker => | ||||||||||||||||||||||||||||||||||||||||||||||
| new Promise((resolveResponse, rejectResponse) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| responseHandlers.set(worker.id, { | ||||||||||||||||||||||||||||||||||||||||||||||
| resolve: resolveResponse, | ||||||||||||||||||||||||||||||||||||||||||||||
| reject: rejectResponse, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| worker.send(message); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| worker.send({ | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_REQ, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Promise.all(responsePromises) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then(metrics => Registry.aggregate(metrics.flat()).metrics()) | ||||||||||||||||||||||||||||||||||||||||||||||
| const myMetrics = Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||||
| registries.map(r => r.getMetricsAsJSON()), | ||||||||||||||||||||||||||||||||||||||||||||||
| ).then(metrics => { | ||||||||||||||||||||||||||||||||||||||||||||||
| return { metrics }; | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (workerMetrics.length === 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('No workers found for requestId', requestId); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const allMetrics = [myMetrics, ...workerMetrics]; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Promise.all(allMetrics) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then(responses => responses.flatMap(response => response.metrics)) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then(metrics => Registry.aggregate(metrics).metrics()) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then(result => done(undefined, result), done); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -158,54 +174,145 @@ class AggregatorRegistry extends Registry { | |||||||||||||||||||||||||||||||||||||||||||||
| * @returns {void} | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| function addListeners() { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (listenersAdded) return; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (listenersAdded) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| listenersAdded = true; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (cluster().isPrimary) { | ||||||||||||||||||||||||||||||||||||||||||||||
| // Listen for worker responses to requests for local metrics | ||||||||||||||||||||||||||||||||||||||||||||||
| cluster().on('message', (worker, message) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (message.type === GET_METRICS_RES) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const request = requests.get(message.requestId); | ||||||||||||||||||||||||||||||||||||||||||||||
| replaceListener('message', cluster(), primaryListener); | ||||||||||||||||||||||||||||||||||||||||||||||
| replaceListener('disconnect', cluster(), disconnect); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (request === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| announce(); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| replaceListener('message', process, workerListener); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+184
to
+189
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've been trying to understand an issue flagged by LLM. "replaceListener" was removing listeners from the "old" registry, but that means you can lose metrics as they won't be called anymore. So reverting to simply doing It does reintroduce #155 warning in "listeners don't accumulate" in test/clusterTest.js, but there is a way to fix it apparently (in a separate PR):
Suggested change
Regression test for this:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Major edit: Because the responses are being aggregated through a promise, only the first result was ever being seen anyway. In fact what you were probably always seeing before was the oldest or second oldest metrics per process, based on when the event was delivered and processing time to gather the metrics. Which is exactly the wrong data for functional and integration tests. To the best of my knowledge prom-client has never worked with hot reload. Let alone well. And anyone would see that it doesn't within a few minutes of trying, especially if they used older versions that were especially crabby about this. We have a bigger problem with what to do about dead workers. Because their metrics disappear when they do, and since we are gathering them, we are getting the wrong answers for counts and gauges. #803 which is a problem since the general wisdom is 'let the process crash' when unhandledException or unhandledRejection fires. What I think that suggests is an update to the README, suggesting you let a Prometheus sidecar handle the aggregation in Serious Projects rather than using cluster.js or worker.js |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const response = request.responseHandlers.get(worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (response === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| request.responseHandlers.delete(worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof process.send !== 'function') { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('worker has no process.send()'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else if (!process.connected) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('worker is not connected to parent process'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ type: ANNOUNCEMENT }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (message.error) { | ||||||||||||||||||||||||||||||||||||||||||||||
| response.reject(new Error(message.error)); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| response.resolve(message.metrics); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * Watch for metrics events and aggregator announcements | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * Whereas clusters are a top-level activity, multiple modules may start their | ||||||||||||||||||||||||||||||||||||||||||||||
| * own workers and require telemetry collection. | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param message {MessageEvent} | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| async function workerListener(message) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (message.type === ANNOUNCEMENT) { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ type: ANNOUNCEMENT }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else if (message.type === GET_METRICS_REQ) { | ||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||
| const metrics = await Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||||
| registries.map(r => r.getMetricsAsJSON()), | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (!process.connected) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('Connection to primary lost.'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_RES, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId: message.requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| metrics, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| // Respond to master's requests for worker's local metrics. | ||||||||||||||||||||||||||||||||||||||||||||||
| process.on('message', message => { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (message.type === GET_METRICS_REQ) { | ||||||||||||||||||||||||||||||||||||||||||||||
| Promise.all(registries.map(r => r.getMetricsAsJSON())) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then(metrics => { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_RES, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId: message.requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| metrics, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||
| .catch(error => { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_RES, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId: message.requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| error: error.message, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('Error sending to primary', error); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!process.connected) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('Connection to primary lost.'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| process.send({ | ||||||||||||||||||||||||||||||||||||||||||||||
| type: GET_METRICS_RES, | ||||||||||||||||||||||||||||||||||||||||||||||
| requestId: message.requestId, | ||||||||||||||||||||||||||||||||||||||||||||||
| error: error.message, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * Add workers to the aggregation list when they are announced. | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * Whereas clusters are a top-level activity, multiple modules may start their | ||||||||||||||||||||||||||||||||||||||||||||||
| * own workers and require telemetry collection. | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param event {MessageEvent} | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| async function primaryListener(worker, event) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (event.type === ANNOUNCEMENT) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (workers.has(worker.id)) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('duplicate worker announcement', worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| workers.set(worker.id, worker); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else if (event.type === GET_METRICS_RES) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const request = requests.get(event.requestId); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (request === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('unexpected results from worker', worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const response = request.responseHandlers.get(worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (response === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| request.responseHandlers.delete(worker.id); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (event.error) { | ||||||||||||||||||||||||||||||||||||||||||||||
| response.reject(new Error(event.error)); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| response.resolve({ | ||||||||||||||||||||||||||||||||||||||||||||||
| threadId: worker.id, | ||||||||||||||||||||||||||||||||||||||||||||||
| metrics: event.metrics, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function disconnect(event) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('worker disconnected', event.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| workers.delete(event.id); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function announce() { | ||||||||||||||||||||||||||||||||||||||||||||||
| for (const worker of Object.values(cluster().workers)) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (worker.isConnected()) { | ||||||||||||||||||||||||||||||||||||||||||||||
| worker.send({ type: ANNOUNCEMENT }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||
| * Replace any listeners with new ones. | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param messageType | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param emitter {EventEmitter} | ||||||||||||||||||||||||||||||||||||||||||||||
| * @param fn | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
| function replaceListener(messageType, emitter, fn) { | ||||||||||||||||||||||||||||||||||||||||||||||
| // Reloading a module creates a unique instance of each function, so the | ||||||||||||||||||||||||||||||||||||||||||||||
| // identity checks is cluster.off() will fail. | ||||||||||||||||||||||||||||||||||||||||||||||
| const functionString = fn.toString(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| for (const listener of emitter.listeners(messageType)) { | ||||||||||||||||||||||||||||||||||||||||||||||
| // eslint-disable-next-line eqeqeq | ||||||||||||||||||||||||||||||||||||||||||||||
| if (functionString == listener) { | ||||||||||||||||||||||||||||||||||||||||||||||
| debug('removing duplicate listener', messageType); | ||||||||||||||||||||||||||||||||||||||||||||||
| emitter.off(messageType, listener); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| emitter.on(messageType, fn); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+295
to
317
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For above.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
| module.exports = AggregatorRegistry; | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: