Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const os = require('os');
- const cluster = require('cluster');
- const EventEmitter = require('events');
- const net = require('net');
- const http = require('http');
- module.exports = class Cluster extends EventEmitter {
- constructor(config = {}) {
- super();
- this.config = {
- public_ip: null,
- master_address: 'localhost',
- master_port: 2000,
- name: config.name || 'Cluster',
- nb_workers: config.nb_workers || os.cpus().length,
- ipCheckHost: 'google.com',
- ipCheckPort: 80
- };
- this.workers_names = {
- A: 'Alpha', B: 'Bravo', C: 'Charlie', D: 'Delta',
- E: 'Echo', F: 'Foxtrot', G: 'Golf', H: 'Hotel',
- I: 'India', J: 'Juliet', K: 'Kilo', L: 'Lima',
- M: 'Mike', N: 'November', O: 'Oscar', P: 'Papa',
- Q: 'Quebec', R: 'Romeo', S: 'Sierra', T: 'Tango',
- U: 'Uniform', V: 'Victor', W: 'Whiskey', X: 'X-Ray',
- Y: 'Yankee', Z: 'Zulu'
- };
- this.clusters_names = {
- A: 'Acosta', B: 'Belknap', C: 'Churchill', D: 'Douglas',
- E: 'Eisenhower', F: 'Foch', G: 'Gration', H: 'Hongzhang'
- };
- this.startedAt = new Date();
- this.id = this.getRandomId();
- this.name = this.getRandomName('clusters');
- this.ready = false;
- this.workers = [];
- this.on('ping', () => {
- this.emit('pong');
- });
- this.on('ready', address => {
- this.notifyMaster('spawning', {
- address: address,
- workers: this.getWorkersMetadata(),
- cluster_id: this.id,
- type: this.config.name,
- name: this.name,
- uptime: this.startedAt
- }).then(() => this.ready = true)
- .catch(error => console.log(error));
- });
- }
- getPublicIp() {
- return new Promise((resolve, reject) => {
- let client = net.connect({
- port: this.config.ipCheckPort,
- host: this.config.ipCheckHost
- }, () => {
- this.public_ip = client.localAddress;
- resolve(client.localAddress);
- });
- });
- }
- getRandomId() {
- return Math.random().toString(36).substr(2, 9);
- }
- getRandomName(type) {
- let key;
- let count = 0;
- for (let item in this[type + '_names'])
- if (Math.random() < 1 / ++count)
- key = item;
- let name = this[type + '_names'][key];
- delete this[type + '_names'][key];
- return name;
- };
- notifyMaster(event, payload) {
- return new Promise((resolve, reject) => {
- let data = JSON.stringify(payload);
- let request = http.request({
- hostname: this.config.master_address,
- port: this.config.master_port,
- path: '/' + event,
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- }
- }, res => {
- res.on('error', error => reject(error));
- res.on('data', chunk => {
- console.log('Notification response:', chunk.toString());
- });
- res.on('end', () => {
- console.log('No more data in response.');
- resolve();
- });
- });
- request.on('error', error => console.error(error));
- request.write(data);
- request.end();
- })
- }
- getWorkersMetadata() {
- return this.workers.map(worker => {
- return {
- name: worker.name,
- pid: worker.process.pid,
- id: worker.id,
- job_count: worker.job_count
- }
- });
- }
- start() {
- return new Promise((resolve, reject) => {
- if (cluster.isMaster) {
- this.getPublicIp().then(address => {
- for (let i = 0; i < this.config.nb_workers; ++i) {
- let worker = cluster.fork();
- worker.name = this.getRandomName('workers');
- worker.on('online', () => {
- console.log(worker.job_count)
- if (i == this.config.nb_workers - 1)
- this.emit('ready', address);
- console.log(`[${this.config.name}#${this.name}][${worker.name}#${worker.process.pid}] worker spawned`);
- });
- this.workers.push(worker);
- }
- process.stdin.resume();
- process.on('exit', () => this.exit);
- process.on('SIGINT', () => {
- this.exit();
- });
- // process.on('SIGUSR1', () => this.exit);
- // process.on('SIGUSR2', () => this.exit);
- process.on('uncaughtException', () => this.exit);
- });
- } else {
- resolve();
- }
- })
- }
- exit() {
- console.log('closed');
- this.notifyMaster('closed', {
- cluster_id: this.id,
- type: this.config.name,
- name: this.name
- })
- .catch(error => console.log(error));
- setTimeout(() => {
- process.exit()
- }, 1000);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement