🇺🇦PM2 Instances Events
Data exchange between instances of pm2
services located on decentralized servers (virtual machines), etc.
The usual mechanism embedded in the process notification
process.on('message', async function (packet) {
/* do something with packet.data */
})
does not include distributed virtual instances, but locally causes a pm2 instance crash under heavy load.
Install
npm i node-pm2-events
Initialize
const EventBus = require('node-pm2-events');
Using internal events
// internal events
EventBus.on('channelName', (m) => {
console.log('\tinternal:', m)
})
EventBus.send('channelName', {awesome: 'data'}) // work
EventBus.send('channelName-2', {data: 'awesome'}) // not work - not subscribed
For the examples below - Let's use the configuration example
const Config = {
redis: {
host: 'localhost',
password: "your password",
keepAlive: true,
port: 6379
},
isDev: true,
}
Free Redis server
Exchange events between different instances
(decentralized or not, pm2 or not - it doesn't matter)
Execute on one server and on some other(s)
- Because the server that sends the data itself does not receive it
// execute on one server and on some other(s)
await EventBus.transport.initialize(Config.redis).waitingConnection();
// other server(s) - recivers
EventBus.transport.on('channelName', (message) => {
console.log('\tcb :', message)
})
// one server - the one sending the data - senders
EventBus.transport.send('channelName', {some: 'object data'});
Use with Fastify websocket
const fastify = require('fastify')({
logger: {level: Config.isDev ? 'info' : 'warn'},
trustProxy: true,
});
// Add [fastify web socket plugin](https://github.com/fastify/fastify-websocket)
fastify.register(require('@fastify/websocket'), {
options: {
maxPayload: 10000 // bytes
}
});
fastify.after(async () => {
await EventBus.transport.initialize({...Config.redis, debug: Config.isDev}).waitingConnection();
router.register(fastify); // register your routes - [https://fastify.dev/docs/latest/Reference/Routes]
});
// ....
Add Festify routes
(About Fastify hooks)
local events will be relayed to your websocket connections and to decentralized servers as well
//...
const routes = [];
// From internal to self sockets and emit to other servers, and his sockets
// From external to self sockets
EventBus.websocket.registerDuplexEvents('channelName');
routes.push({
method: 'GET',
url: '/api/websocket/endpoint',
preHandler: auth, // YOUR Auth Handler method - generate session object with session _id!!!
handler: (req, reply) => {
reply.code(404).send(); // or something else for GET response...
},
wsHandler: (connection, req) => EventBus.websocket.wsHandler(connection, req)
});
Handle messages from clients sockets
// override: handle messages from clients sockets
EventBus.websocket.messagesHandler = (message, session, connection) => {
// do something with message ...
// ...
// send internal broadcast
EventBus.send('toSomeWebsocketChannelHandler', message);
// ...
// or do something and send result
// ...
// to the current client (from somewhere else)
EventBus.websocket.sendTo(session._id, {some: 'data', to: 'client'});
// or
connection.socket.send({some: 'data', to: 'client'})
}
Redis is used for exchange: ioredis