mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-12 16:10:30 +02:00
all commands sent between main instance and workers need to contain a server id to prevent senders from reacting to their own messages, causing loops this PR makes sure all sent messages contain a sender id by default as part of constructing a sending redis client. --------- Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { jsonParse, LoggerProxy } from 'n8n-workflow';
|
|
import type { RedisServiceCommandObject } from '@/services/redis/RedisServiceCommands';
|
|
import { COMMAND_REDIS_CHANNEL } from '@/services/redis/RedisServiceHelper';
|
|
import type { RedisServicePubSubPublisher } from '@/services/redis/RedisServicePubSubPublisher';
|
|
import * as os from 'os';
|
|
import Container from 'typedi';
|
|
import { License } from '@/License';
|
|
import { MessageEventBus } from '../eventbus/MessageEventBus/MessageEventBus';
|
|
|
|
export function getWorkerCommandReceivedHandler(options: {
|
|
queueModeId: string;
|
|
instanceId: string;
|
|
redisPublisher: RedisServicePubSubPublisher;
|
|
getRunningJobIds: () => string[];
|
|
}) {
|
|
return async (channel: string, messageString: string) => {
|
|
if (channel === COMMAND_REDIS_CHANNEL) {
|
|
if (!messageString) return;
|
|
let message: RedisServiceCommandObject;
|
|
try {
|
|
message = jsonParse<RedisServiceCommandObject>(messageString);
|
|
} catch {
|
|
LoggerProxy.debug(
|
|
`Received invalid message via channel ${COMMAND_REDIS_CHANNEL}: "${messageString}"`,
|
|
);
|
|
return;
|
|
}
|
|
if (message) {
|
|
if (message.targets && !message.targets.includes(options.queueModeId)) {
|
|
return; // early return if the message is not for this worker
|
|
}
|
|
switch (message.command) {
|
|
case 'getStatus':
|
|
await options.redisPublisher.publishToWorkerChannel({
|
|
workerId: options.queueModeId,
|
|
command: message.command,
|
|
payload: {
|
|
workerId: options.queueModeId,
|
|
runningJobs: options.getRunningJobIds(),
|
|
freeMem: os.freemem(),
|
|
totalMem: os.totalmem(),
|
|
uptime: process.uptime(),
|
|
loadAvg: os.loadavg(),
|
|
cpus: os.cpus().map((cpu) => `${cpu.model} - speed: ${cpu.speed}`),
|
|
arch: os.arch(),
|
|
platform: os.platform(),
|
|
hostname: os.hostname(),
|
|
net: Object.values(os.networkInterfaces()).flatMap(
|
|
(interfaces) =>
|
|
interfaces?.map((net) => `${net.family} - address: ${net.address}`) ?? '',
|
|
),
|
|
},
|
|
});
|
|
break;
|
|
case 'getId':
|
|
await options.redisPublisher.publishToWorkerChannel({
|
|
workerId: options.queueModeId,
|
|
command: message.command,
|
|
});
|
|
break;
|
|
case 'restartEventBus':
|
|
await Container.get(MessageEventBus).restart();
|
|
await options.redisPublisher.publishToWorkerChannel({
|
|
workerId: options.queueModeId,
|
|
command: message.command,
|
|
payload: {
|
|
result: 'success',
|
|
},
|
|
});
|
|
break;
|
|
case 'reloadLicense':
|
|
await Container.get(License).reload();
|
|
break;
|
|
case 'stopWorker':
|
|
// TODO: implement proper shutdown
|
|
// await this.stopProcess();
|
|
break;
|
|
default:
|
|
LoggerProxy.debug(
|
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
`Received unknown command via channel ${COMMAND_REDIS_CHANNEL}: "${message.command}"`,
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|