Skip to content

stan-alam/NodeJS

Repository files navigation

Core Node JS course work

Global Objects, Process, and Buffer

const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');

process.stdn.on('readable', () => {
  const chunk = process.stdn.read();
  if (chunk != null ) {
    const buffer = Buffer.from([chunk]);
    console.log('with .toString function:', buffer.toString());
    console.log('With StringDecoder: function', decoder.write(buffer));
  }
});

Require() function and 'stuff' about modules

$ node
> console.log(module);
{ id: 'repl',
  exports:
   { writer: { [Function: inspect] colors: [Object], styles: [Object] },
     _builtinLibs:
      [ 'assert',
        'buffer',
        'child_process',
        'cluster',
        'crypto',
        'dgram',
        'dns',
        'domain',
        'events',
        'fs',
        'http',
        'https',
        'net',
        'os',
        'path',
        'punycode',
        'querystring',
        'readline',
        'stream',
        'string_decoder',
        'tls',
        'tty',
        'url',
        'util',
        'vm',
        'zlib',
        'smalloc' ],
     REPLServer: { [Function: REPLServer] super_: [Object] },
     start: [Function],
     repl:
      { _domain: [Object],
        useGlobal: true,
        ignoreUndefined: false,
        rli: [Circular],
        eval: [Object],
        inputStream: [Object],
        outputStream: [Object],
        lines: [Object],
        context: [Object],
        _events: [Object],
        bufferedCommand: '',
        _sawReturn: true,
        domain: null,
        _maxListeners: undefined,
        output: [Object],
        input: [Object],
        completer: [Function: complete],
        _initialPrompt: '> ',
        _prompt: '> ',
        terminal: true,
        line: '',
        cursor: 0,
        history: [Object],
        historyIndex: -1,
        commands: [Object],
        writer: [Function],
        useColors: true,
        prevRows: 0 } },
  parent: undefined,
  filename: 'C:\\git\\NodeJS\\coreNode\\07\\repl',
  loaded: false,
  children: [],
  paths:
   [ 'C:\\git\\NodeJS\\coreNode\\07\\repl\\node_modules',
     'C:\\git\\NodeJS\\coreNode\\07\\node_modules',
     'C:\\git\\NodeJS\\coreNode\\node_modules',
     'C:\\git\\NodeJS\\node_modules',
     'C:\\git\\node_modules',
     'C:\\node_modules' ] }
undefined

Addons

require.extensions
{ '.js': [Function],
  '.json': [Function],
  '.node': [Function: dlopen] }
// hello.cc edited by Stan Alam taken from https://nodejs.org/api/addons.html
#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Multiverse(s)"));
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

}  // namespace demo

> require.extensions['.json'].toString()
'function (module, filename) {\n  var content = fs.readFileSync(filename, \'utf8
\');\n  try {\n    module.exports = JSON.parse(stripBOM(content));\n  } catch (e
rr) {\n    err.message = filename + \': \' + err.message;\n    throw err;\n  }\n
}'
> require.extensions['.node'].toString()
'function dlopen() { [native code] }'
>

Wrapping, Caching modules

> require('module').wrapper
[ '(function (exports, require, module, __filename, __dirname) { ',
  '\n});' ]
>

const print = (stars, header) => {
  console.log('*'.repeat(stars));
  console.log(header);
  console.log('*'.repeat(stars));
};
// node >= 8
// or use harmony flag

Concurrency Model and Event Loop

const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout() => {
   console.log('execute timeout');
 }, 0); //set timeout is at 0 milliseconds
  setImmediate(() => {
    console.log('execute setImmediate');
  });
});
/*
$ node setImmediate.js
execute setImmediate
execute setTimeout
$
*/

const fs = require('fs');

function fileSize (fileName, mycallBack) {
  if (typeof fileName !== 'string') {
    return mycallBack(new TypeError('argument should have been a string'));
  }

  fs.stat(fileName, (err, stats) => {
    if(err) {
      return mycallBack(err);
    }

    mycallBack(null, stats.size);
  });
}

fileSize(__filename, (err, size) => {
  if (err) throw err;

  console.log(`Size in KB: ${size/1024}`);
});

console.log('Hello, Multiverse!');

const fs = require('fs');

const readFileAsArray = function(file, callback) {
    fs.readFile(file, function(err, data) {
        if (err) {
            return callback(error);
        }

        const lines = data.toString().trim().split('\n');
        callback(null, lines);
    });
};

readFileAsArray('./numbers', (err, lines) => {
    if (err) throw err;

    const numbers = lines.map(Number);
    const oddNumbers = numbers.filter(number => number % 2 === 1);
    console.log('odd number count is : ', oddNumbers.length);
});

const fs = require('fs');

const readFileAsArray = function(file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, function(err, data) {
      if(err) {
        return reject(err);
      }

      const lines = data.toString().trim().split('\n');
      resolve(lines);
    });
  });
};

// here's where you make the call
readFileAsArray('./numbers').then(lines => {
  const numbers = lines.map(Number);
  const oddNumbers = numbers.filter(number => number % 2 === 1);
  console.log('odd numbers count:', oddNumbers.length);
})
.catch(console.error);

const fs = require('fs');

const readFileAsArray = function(file, callback = () => {}) { //notice the empty function
  return new Promise((resolve, reject) => {
    fs.readFile(file, function(err, data) {
      if(err) {
        reject(err);
        return callback(err); // you can see you're still returning, this time with a callback
      }

      const lines = data.toString().trim().split('\n');
      resolve(lines);
      callback(null, lines);
    });
  });
};

// here's where you make the call
readFileAsArray('./numbers').then(lines => {
  const numbers = lines.map(Number);
  const oddNumbers = numbers.filter(number => number % 2 === 1);
  console.log('odd numbers count:', oddNumbers.length);
})
.catch(console.error);

async function countEven() {
//  (%) is the modulus operator, it will let you have the remainder of place/sequence.length. taken from stackoverflow
try {
  const lines = await readFileAsArray('./numbers');
  const numbers = lines.map(Number);
  const evenCount = numbers.filter(number => number % 2 !== 1).length
  console.log('even number count is : ', evenCount);
} catch(err) {
  console.error(err);
}
  }
}

countEven(); // wow! async code running synchronously ... good for test automation!

//sync_event.js
const EventEmitter = require('events');

class Logger extends EventEmitter {
  execute(theTask) {
    console.log('State before execution');
    this.emit('Begin');
    theTask();
    this.emit('fin');
    console.log('State after execution');
  }
}

const logger = new Logger();

logger.on('begin', () => console.log('About to execute'));
logger.on('end', () => console.log('Done with executing'));

logger.execute(() => console.log('***** execute task ******* '));

Shell Output

$ node sync_event.js
State before execution
***** execute task *******
State after execution

Notice that the execution of sync_event.js is synchronous.

//sync_event2.js
const EventEmitter = require('events');

class Logger extends EventEmitter {
  execute(theTask) {
    console.log('State before execution');
    this.emit('Begin');
    theTask();
    this.emit('fin');
    console.log('State after execution');
  }
}

const logger = new Logger();

logger.on('begin', () => console.log('About to execute'));
logger.on('end', () => console.log('Done with executing'));

logger.execute(() => setTimeout(
  () => console.log('***** execute task ******* '),
  1000
  )
);

const fs = require('fs');
const EventEmitter = require('events');

class ElapsedTime extends EventEmitter {
execute(asyncFunc, ...args) {
  console.time('execute');
  this.emit('begin');
  asyncFunc(...args, (err, data) => {
    if(err) {
      return this.emit('error', err);
    }

    this.emit('data', data);
    console.timeEnd('execute');
    this.emit('end');
  });
  }
}

const elapsedTime = new ElapsedTime();

elapsedTime.on('begin', () => console.log('ready to exec'));
elapsedTime.on('end', () => console.log('completed execution'));

elapsedTime.execute(fs.readFile, __filename);

Shell Output

$ node async_event.js
ready to exec
execute: 47.151ms
completed execution

const fs = require('fs');
const EventEmitter = require('events');

class ElapsedTime extends EventEmitter {
execute(asyncFunc, ...args) {
  console.time('execute');
  this.emit('begin');
  asyncFunc(...args, (err, data) => {
    if(err) {
      return this.emit('error', err);
    }

    this.emit('data', data);
    console.timeEnd('execute');
    this.emit('end');
  });
  }
}

const elapsedTime = new ElapsedTime();

elapsedTime.on('data', (data) => {
  console.log(`Length: ${data.length}`);
});
elapsedTime.execute(fs.readFile, __filename);

Shell Output

$ node async_event2.js
Length: 571
execute: 3.550ms

const fs = require('fs');
const EventEmitter = require('events');

class ElapsedTime extends EventEmitter {
execute(asyncFunc, ...args) {
  console.time('execute');
  this.emit('begin');
  asyncFunc(...args, (err, data) => {
    if(err) {
      return this.emit('error', err);
    }

    this.emit('data', data);
    console.timeEnd('execute');
    this.emit('end');
  });
  }
}

const elapsedTime = new ElapsedTime();

elapsedTime.on('data', (data) => {
  console.log(`Length: ${data.length}`);
});

elapsedTime.execute(fs.readFile, ''); //notice blank in argument, will crash
elapsedTime.execute(fs.readFile, __filename);

const EventEmitter = require('events');

class Server extends EventEmitter {
  constructor(client) { //define the constructor to receive the client *within the server class
    super();  
  }
}
//created a function not just an object
module.exports = (client) => new Server(client); // Server(client) instantiate the server object with the client object
//the function (client) is going to receive the client
//client
const EventEmitter = require('events');
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin, output:process.stdout
});

//client event emmiter
const client = new EventEmitter(); //instantiate an object directly from EventEmitter
const server = require('./server')(client); //import server object
/* the client is going to emit events, while
the server is going to listen to those events
*/

rl.on('line', (input) => { //here register a listener for the line event, that receives an input

});
//client with latest update to read input from cli and echo input with readline.process.stdout
const EventEmitter = require('events');
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

//client event emmiter
const client = new EventEmitter(); //instantiate an object directly from EventEmitter
const server = require('./server')(client); //import server object, also export a FUNCTION with the client as an arg
/* the client is going to emit events, while
the server is going to listen to those events
*/
//use the readline interInterface
rl.on('line', (input) => { //here register a listener for the line event, that receives an input
  console.log(input); //log the inpout line, to test the client
});
//output  
$ node client.js
yo
yo

const EventEmitter = require('events');
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

//client event emmiter
const client = new EventEmitter(); //instantiate an object directly from EventEmitter
const server = require('./server')(client); //import server object
/* the client is going to emit events, while
the server is going to listen to those events
*/
//use the readline interInterface
rl.on('line', (input) => { //here register a listener for the line event, that receives an input
  client.emit('command', input);  // now everytime the user presses ENTER,
}); // the client is going to emit an input EVENT to the server

The idea is to enter a value such as 'help' which is the command value and the Server will read and respond accordingly.

// client is able to clear the terminal when a command is entered
// client echos the command, and the correct command too. from the server
const EventEmitter = require('events');
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

//client event emmiter
const client = new EventEmitter(); //instantiate an object directly from EventEmitter
const server = require('./server')(client); //import server object
/* the client is going to emit events, while
the server is going to listen to those events
*/
server.on('response', (resp) => { //when the server emits a response event, the listener will access the response as a function
  //console.log(`Response: ${resp}`);
  process.stdout.write('\u001B[2J\u001B[0;0f'); //clear terminal
  process.stdout.write(resp);
  process.stdout.write('\n\>');
});
//use the readline interInterface
rl.on('line', (input) => { //here register a listener for the line event, that receives an input
  client.emit('command', input);  // now everytime the user presses ENTER,
});  // the client is going to emit an input EVENT to the server

Server is able to take four commands and echo invalid commands

//server is able to handle four commands, and update accordingly, also can handle invalid commands
const EventEmitter = require('events');

class Server extends EventEmitter {
  constructor(client) { //define the constructor to receive the client *within the server class
    super();
    client.on('command', (command) => {
      console.log(`Command: ${command}`);
      switch(command) {
        case 'help':
        case 'add':
        case 'del':
        case 'ls':
        this[command]();
        break;
      default: // case in which is unknown command
        this.emit('response', 'unknown command:' + `${command}`);
      }
      // help, add, del, ls
    });
  }
    help() { //create an instance method for each command
      this.emit('response', 'help is on the way ...');
    }
    add() {
      this.emit('response', 'adding ...');
      }
   del() {
     this.emit('response', 'deleting ...');
   }
   ls(){
     this.emit('response', 'ls-Ing...');
   }
}
//created a function not just an object
module.exports = (client) => new Server(client); // Server(client) instantiate the server object with the client object
//the function (client) is going to receive the client
//terminal output
$ node client.js
help is on the way ...
>

Server

//complete server.js
const EventEmitter = require('events');

class Server extends EventEmitter {
    constructor(client) { //define the constructor to receive the client *within the server class
        super();
        //this.emit('response', 'Welcome -- enter a command or help for list of commands'); // THIS IS NOT WORKING!
        /* this.emit does not work because it will be executed when
        const server = require(./server)(client) in client.js will be executed
         This is the sequential order, so the handler of the reponse event is not being defined at execution time
         */
        this.tasks = {}; //task object to hold task info
        this.taskId = 1; //task Id to keep track of number tasks starting at 1, counter holder for new tasks
        process.nextTick(() => {
            this.emit('response', 'Welcome - type a command or enter help for list of valid command options');
        });
        client.on('command', (command, args) => { //now server can accept a command and an array of arguments
            console.log(`Command: ${command}`);
            switch (command) {
                case 'help':
                case 'add':
                case 'del':
                case 'ls':
                    this[command](args); // NOW THE ARRAY OF ARGS CAN BE PASSED TO EVERY COMMAND TO BE EXECUTED.
                    break;
                default: // case in which is unknown command
                    this.emit('response', 'unknown command: ' + `${command}`);
            }
            // help, add, del, ls
        });
    }

    tasksString() {
      return Object.keys(this.tasks).map(key => { //loop over key, return task, for every key return string to ls
        return `${key}: ${this.tasks[key]}`;
      }).join('\n');
    }

    help() { //create an instance method for each command
        this.emit('response', `Available commands:
        add, del {id}, ls`);
    }
    add(args) {
        this.tasks[this.taskId] = args.join(' ');  // each task is now added to task object
        this.emit('response', `Added task ${this.taskId}`); //emit the number of the task to user
        this.taskId++;
    }
    del() {
       delete(this.tasks[args[0]]); //for deleting the task, delete the id indicated by user
       this.emit('response', `Deleting task ${args[0]}`); //print to console task has been deleted
    }
    ls() {
        this.emit('response', `List of Tasks\n${this.tasksString()}`);
    }
}
//created a function not just an object
module.exports = (client) => new Server(client); // Server(client) instantiate the server object with the client object
//the function (client) is going to receive the client

Client

//complete client
const EventEmitter = require('events');
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

//client event emmiter
const client = new EventEmitter(); //instantiate an object directly from EventEmitter
const server = require('./server')(client); //import server object
/* the client is going to emit events, while
the server is going to listen to those events
*/
server.on('response', (resp) => { //when the server emits a response event, the listener will access the response as a function
    //console.log(`Response: ${resp}`);
    process.stdout.write('\u001B[2J\u001B[0;0f'); //clear terminal
    process.stdout.write(resp);
    process.stdout.write('\n\>');
});
//use the readline interInterface
let command, args;
rl.on('line', (input) => { //here register a listener for the line event, that receives an input
  [command, ...args] = input.split(' '); //split on space, the first "token" will be on command, the rest will be passed in the arguments(args)
  client.emit('command', command, args); //pass both command and argument, it will be parsed at the first space after command
}); // the client is going to emit an input EVENT to the server

Node Networking

process.stdout.write('\u001B[2J\u001B[0;0f'); //again clear node terminal

const server = require('net').createServer(); // here use the createServer method from net module

server.on('connection', socket => {
  console.log('Client is connected!');
  socket.write('Welcome!');
});

server.listen(3000, () => console.log('I am Server'));

process.stdout.write('\u001B[2J\u001B[0;0f'); //again clear node terminal

const server = require('net').createServer(); // here use the createServer method from net module

server.on('connection', socket => {
  console.log('Client is connected!');
  socket.write('Welcome!\n');

  socket.on('data', data => {
    console.log('data is', data);
    socket.write('data is ');
    socket.write(data);
  });

  socket.on('end', () => {
    console.log('Client is now disconnected');
  });
});

server.listen(3000, () => console.log('I am Server'));

process.stdout.write('\u001B[2J\u001B[0;0f'); //again clear node terminal
let counter = 0;
const server = require('net').createServer(); // here use the createServer method from net module

server.on('connection', socket => {
  socket.id = counter++; //everytime a client connects assign an id, and add to the counter for next socket Id
  console.log('Client is connected!');
  socket.write('Welcome!\n');

  socket.on('data', data => {
    socket.write(`${socket.id}: `);
    console.log('data is', data);
    socket.write('data is ');
    socket.write(data);
  });

  socket.on('end', () => {
    console.log('Client is now disconnected');
  });
});

server.listen(3000, () => console.log('I am Server'));
// use tmux to connect with multiple clients -- i.e. fingers should
//never leave the keyboard!

process.stdout.write('\u001B[2J\u001B[0;0f'); //again clear node terminal
const server = require('net').createServer(); // here use the createServer method from net module
let counter = 0;
let sockets = {};

server.on('connection', socket => {
  socket.id = counter++; //everytime a client connects assign an id, and add to the counter for next socket Id
  sockets[sockets.id] = socket;

  console.log('Client is connected!');
  socket.write('Welcome!\n');

  socket.on('data', data => {
   Object.entries(sockets).forEach(([, cs]) => {  //the empty value would be key, but there is none
    cs.write(`${socket.id}: `);
  //  console.log('data is', data);
    cs.write(data);
  });
});
  socket.on('end', () => {
    console.log('Client is now disconnected');
  });
});

server.listen(3000, () => console.log('I am Server'));
// use tmux to connect with multiple clients -- i.e. fingers should
//never leave the keyboard!

process.stdout.write('\u001B[2J\u001B[0;0f'); //again clear node terminal
const server = require('net').createServer(); // here use the createServer method from net module
let counter = 0;
let sockets = {};

server.on('connection', socket => {
  socket.id = counter++; //everytime a client connects assign an id, and add to the counter for next socket Id
  sockets[sockets.id] = socket;

  console.log('Client is connected!');
  socket.write('Welcome!\n');

  socket.on('data', data => {
   Object.entries(sockets).forEach(([key, cs]) => {  //the empty value would be key, but there is none
    if (socket.id == key)
      return;
    cs.write(`${socket.id}: `);
  //  console.log('data is', data);
    cs.write(data);
  });
});  

  socket.on('end', () => {
    delete sockets[socket.id];
    console.log('Client is now disconnected');
  });
});

server.listen(3000, () => console.log('I am Server'));
// use tmux to connect with multiple clients -- i.e. fingers should
//never leave the keyboard!

const dgram = require('dgram');

const server = dgram.createSocket('udp4');

server.on('listening', () => console.log('UDP Server is listening up and listening!')); // listening event

server.on('message', (msg, rinfo) => { // register handle for message event, callback exposes message and -->
  console.log(`${rinfo.address}:${rinfo.port} - ${msg}`); // remote address and port
});

const PORT = 3333;
const HOST = '127.0.0.1'; //home
server.bind(PORT, HOST);

const dgram = require('dgram');
const PORT = 3333;
const HOST = '127.0.0.1'; //home

//server
const server = dgram.createSocket('udp4');

server.on('listening', () => console.log('UDP Server is listening up and listening!')); // listening event

server.on('message', (msg, rinfo) => { // register handle for message event, callback exposes message and -->
  console.log(`${rinfo.address}:${rinfo.port} - ${msg}`); // remote address and port
});


server.bind(PORT, HOST);

//clients
setInterval(function () {
  const client = dgram.createSocket('udp4');

  client.send('Mozart is awesome!', PORT, HOST, (err) => {
    if (err) throw err;

    console.log('message sent by UDP');
    client.close();
  });
}, 1000); // 1 second interval
$ node stanUDP.js
UDP Server is up and listening!
message sent by UDP
127.0.0.1:61164 - Mozart is awesome!
message sent by UDP
127.0.0.1:52090 - Mozart is awesome!
message sent by UDP
127.0.0.1:52091 - Mozart is awesome!
message sent by UDP
127.0.0.1:52092 - Mozart is awesome!

Here we're using sending a buffer instead of string

const dgram = require('dgram');
const PORT = 3333;
const HOST = '127.0.0.1'; //home


//server
const server = dgram.createSocket('udp4');

server.on('listening', () => console.log('UDP Server is up and listening! ')); // listening event

server.on('message', (msg, rinfo) => { // register handle for message event, callback exposes message and -->
  console.log(`${rinfo.address}:${rinfo.port} - ${msg}`); // remote address and port
});


server.bind(PORT, HOST);

//clients
setInterval(function () {
  const client = dgram.createSocket('udp4');
  const msg = Buffer.from('Mozart ROCKS!!!')

  client.send(msg, 0, msg.length, PORT, HOST, (err) => {
    if (err) throw err;

    console.log('message sent by UDP');
    client.close();
  });
}, 1000);

Output is the same

$ node stanUDPbuff.js
UDP Server is up and listening!
message sent by UDP
127.0.0.1:58048 - Mozart ROCKS!!!
message sent by UDP
127.0.0.1:58049 - Mozart ROCKS!!!
message sent by UDP
127.0.0.1:56642 - Mozart ROCKS!!!
message sent by UDP
127.0.0.1:56643 - Mozart ROCKS!!!
message sent by UDP
127.0.0.1:56644 - Mozart ROCKS!!!

Here we specify an offset, you can even send an array of messages as 1st argument

const dgram = require('dgram');
const PORT = 3333;
const HOST = '127.0.0.1'; //home


//server
const server = dgram.createSocket('udp4');

server.on('listening', () => console.log('UDP Server is up and listening!')); // listening event

server.on('message', (msg, rinfo) => { // register handle for message event, callback exposes message and -->
  console.log(`${rinfo.address}:${rinfo.port} - ${msg}`); // remote address and port
});


server.bind(PORT, HOST);

//clients
setInterval(function () {
  const client = dgram.createSocket('udp4');
  const msg = Buffer.from('Mozart ROCKS!!!')

  client.send(msg, 0, 7,  PORT, HOST, (err) => {
    if (err) throw err;

  client.send(msg, 7, 6, PORT, HOST, (err) => {
      if (err) throw err;

    console.log('message sent by UDP');
    client.close();
  });
});  
}, 1000);

UDP Server is up and listening!
message sent by UDP
127.0.0.1:51492 - Mozart
message sent by UDP
127.0.0.1:51494 - Mozart
127.0.0.1:51494 - ROCKS!
message sent by UDP
127.0.0.1:51495 - Mozart
127.0.0.1:51495 - ROCKS!

const server = require('http').createServer();

server.on('request', (req, res) => {
  res.writeHead(200, { 'content-type': 'text/plain' });
  res.end('Hola, Multiverse(s)!\n');
});

server.listen(8000);

//stanHTTP_2.js
const server = require('http').createServer();

server.on('request', (req, res) => {
  res.writeHead(200, { 'content-type': 'text/plain' });
  res.write('Hola, Multiverse(s)!\n');

setTimeout(function () {
  res.write('Mozart rocks!\n');
  }, 1000);

setTimeout(function () {
  res.write('Beethoven rules!\n');
  }, 1000);
});

server.listen(8000);

const fs = require('fs');
const server = require('https')
  .createServer({
  key: fs.readFileSync('./key.pem'), //readFileSync for reading file only once
  cert: fs.readFileSync('./cert.pem'),
});
//use openssl toolkit
server.on('request', (req, res) => {
  res.writeHead(200, { 'content-type': 'text/plain' });
  res.write('Hola, Multiverse(s)!\n');
});

server.listen(443);

//openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes

const http = require('http');

http.request({hostname: 'www.nannerl.io'},
(res) => {
  console.log(res);
});

const http = require('http');

const req = http.request(
  { hostname: 'www.nannerl.io'},
(res) => {
  console.log(res);
  }
);

req.on('error', (e) => console.log(e));

req.end();

$ node stanRequest.js

https://github.com/stan-alam/NodeJS/blob/develop/coreNode/10/15-30/src/web/stanRequestOutput.txt

Node REPL output for http.globalAgent (used by node to manage sockets ...etc )

$ node
> http.globalAgent
Agent {
  domain:
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] },
  _events: { free: [Function] },
  _eventsCount: 1,
  _maxListeners: undefined,
  defaultPort: 80,
  protocol: 'http:',
  options: { path: null },
  requests: {},
  sockets: {},
  freeSockets: {},
  keepAliveMsecs: 1000,
  keepAlive: false,
  maxSockets: Infinity,
  maxFreeSockets: 256 }
>

Routes in Node

const fs = require('fs');
const server = require('http').createServer();

server.on('request', (req, res) => {
  switch (req.url) {
  case '/home':
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(fs.readFileSync('./home.html'));
    break;
  case '/':

    break;
  default:

  }
});

server.listen(8000);
$ curl localhost:8000/home
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   289    0   289    0     0   2627      0 --:--:-- --:--:-- --:--:--  3074<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset ="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale-1.0">
  <met http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Nannerl.io</title>
</head>
<body>
  Welcome to Nannerl.io
</body>
</html>

const fs = require('fs');
const server = require('http').createServer();

server.on('request', (req, res) => {
  switch (req.url) {
  case '/home':
  case '/about':
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(fs.readFileSync(`.${req.url}.html`));
    break;
  case '/':

    break;
  default:

  }
});

server.listen(8000);
$ curl localhost:8000/about
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   294    0   294    0     0    294      0 --:--:-- --:--:-- --:--:--  287k<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset ="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale-1.0">
  <met http-equiv="X-UA-Compatible" content="ie=edge">
  <title>About</title>
</head>
<body>
  Nannerl.io, by Stan Enterprises
</body>
</html>

const fs = require('fs');
const server = require('http').createServer();

server.on('request', (req, res) => {
  switch (req.url) {
  case '/home':
  case '/about':
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(fs.readFileSync(`.${req.url}.html`));
    break;
  case '/':
    res.writeHead(301, { 'Location': '/home' });
    res.end();
    break;
  default:

  }
});

server.listen(8000);
$ curl -i localhost:8000/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0HTTP/1.1 301 Moved Permanently
Location: /home
Date: Sat, 31 Mar 2018 18:45:03 GMT
Connection: keep-alive
Transfer-Encoding: chunked
const fs = require('fs');
const server = require('http').createServer();
const colorData = {
  "colors": [
    {
      "color": "black",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,255,255,1],
        "hex": "#000"
      }
    },
    {
      "color": "white",
      "category": "value",
      "code": {
        "rgba": [0,0,0,1],
        "hex": "#FFF"
      }
    },
    {
      "color": "red",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,0,0,1],
        "hex": "#FF0"
      }
    },
    {
      "color": "blue",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [0,0,255,1],
        "hex": "#00F"
      }
    },
    {
      "color": "yellow",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,255,0,1],
        "hex": "#FF0"
      }
    },
    {
      "color": "green",
      "category": "hue",
      "type": "secondary",
      "code": {
        "rgba": [0,255,0,1],
        "hex": "#0F0"
      }
    },
  ]
}

server.on('request', (req, res) => {
  switch (req.url) {
  case '/api':
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(colorData));
    break;
  case '/home':
  case '/about':
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(fs.readFileSync(`.${req.url}.html`));
    break;
  case '/':
    res.writeHead(301, { 'Location': '/home' });
    res.end();
    break;
  default:
    res.writeHead(404);
    res.end();
  }
});

server.listen(8000);

$ curl -i localhost:8000/api
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   559    0   559    0     0  34937      0 --:--:-- --:--:-- --:--:-- 34937HTTP/1.1 200 OK
Content-Type: application/json
Date: Sat, 31 Mar 2018 19:14:47 GMT
Connection: keep-alive
Transfer-Encoding: chunked

{"colors":[{"color":"black","category":"hue","type":"primary","code":{"rgba":[255,255,255,1],"hex":"#000"}},{"color":"white","category":"value","code":{"rgba":[0,0,0,1],"hex":"#FFF"}},{"color":"red","category":"hue","type":"primary","code":{"rgba":[255,0,0,1],"hex":"#FF0"}},{"color":"blue","category":"hue","type":"primary","code":{"rgba":[0,0,255,1],"hex":"#00F"}},{"color":"yellow","category":"hue","type":"primary","code":{"rgba":[255,255,0,1],"hex":"#FF0"}},{"color":"green","category":"hue","type":"secondary","code":{"rgba":[0,255,0,1],"hex":"#0F0"}}]}

When trying curl -i localhost:8000/garbage

$ curl -i localhost:8000/garbage
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0HTTP/1.1 404 Not Found
Date: Sat, 31 Mar 2018 19:14:55 GMT
Connection: keep-alive
Transfer-Encoding: chunked

This diagram is from the NODE.org api page for the URL module

parsing the following url: http://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash

┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│                                            href                                             │
├──────────┬──┬─────────────────────┬─────────────────────┬───────────────────────────┬───────┤
│ protocol │  │        auth         │        host         │           path            │ hash  │
│          │  │                     ├──────────────┬──────┼──────────┬────────────────┤       │
│          │  │                     │   hostname   │ port │ pathname │     search     │       │
│          │  │                     │              │      │          ├─┬──────────────┤       │
│          │  │                     │              │      │          │ │    query     │       │
"  https:   //    user   :   pass   @ sub.host.com : 8080   /p/a/t/h  ?  query=string   #hash "
│          │  │          │          │   hostname   │ port │          │                │       │
│          │  │          │          ├──────────────┴──────┤          │                │       │
│ protocol │  │ username │ password │        host         │          │                │       │
├──────────┴──┼──────────┴──────────┼─────────────────────┤          │                │       │
│   origin    │                     │       origin        │ pathname │     search     │ hash  │
├─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────────┴───────┤
│                                            href                                             │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
(all spaces in the "" line should be ignored -- they are purely for formatting)

const fs = require('fs');
const path = require('path');
const dirname = path.join(__dirname, 'files');
const files = fs.readdirSync(dirname);
const Day = 24*60*60*1000; // millaseconds in a Day

files.forEach(file => {
  const filePath = path.join(dirname, file);
  fs.stat(filePath, (err, stats) => {
    if (err)
      throw err;
    if((Data.now() - stats.mtime.getTime() > 7*Day)) {
      fs.unlink(filePath, (err) => {
        if (err)
          throw err;
        console.log(`deleted ${filePath}`);
      });
    }
  });
});

const fs = require('fs');
const path = require('path');
const dirname = path.join(__dirname, 'files');
const files = fs.readdirSync(dirname);

const logWithTime = (message) =>
  console.log(`${new Date().toUTCString()}: ${message}`);

fs.watch(dirname, (eventType, filename) => {
  if (eventType === 'rename') {
    const index = currentFiles.indexOf(filename);
    if (index >= 0) {
      currentFiles.splice(index, 1);
      logWithTime(`${filename} has been expunged`);
      return;
    }

    currentFiles.push(filename);
    logWithTime(`${filename} has been added`);
    return;
  }

  logWithTime(`${filename} a change has occured`);
});

> console

> console
Console {
  log: [Function: bound consoleCall],
  info: [Function: bound consoleCall],
  warn: [Function: bound consoleCall],
  error: [Function: bound consoleCall],
  dir: [Function: bound consoleCall],
  time: [Function: bound consoleCall],
  timeEnd: [Function: bound consoleCall],
  trace: [Function: bound consoleCall],
  assert: [Function: bound consoleCall],
  clear: [Function: bound consoleCall],
  count: [Function: bound consoleCall],
  countReset: [Function: bound countReset],
  group: [Function: bound consoleCall],
  groupCollapsed: [Function: bound consoleCall],
  groupEnd: [Function: bound consoleCall],
  Console: [Function: Console],
  debug: [Function: debug],
  dirxml: [Function: dirxml],
  table: [Function: table],
  markTimeline: [Function: markTimeline],
  profile: [Function: profile],
  profileEnd: [Function: profileEnd],
  timeline: [Function: timeline],
  timelineEnd: [Function: timelineEnd],
  timeStamp: [Function: timeStamp],
  context: [Function: context],
  [Symbol(counts)]: Map {} }
>

> assert

$ node
> assert
{ [Function: ok]
  fail: [Function: fail],
  AssertionError: [Function: AssertionError],
  ok: [Circular],
  equal: [Function: equal],
  notEqual: [Function: notEqual],
  deepEqual: [Function: deepEqual],
  deepStrictEqual: [Function: deepStrictEqual],
  notDeepEqual: [Function: notDeepEqual],
  notDeepStrictEqual: [Function: notDeepStrictEqual],
  strictEqual: [Function: strictEqual],
  notStrictEqual: [Function: notStrictEqual],
  throws: [Function: throws],
  doesNotThrow: [Function: doesNotThrow],
  ifError: [Function: ifError] }
>

function negativeSummation(...args) {
  return args.reduce((arg, total) => {
    return total-arg;
  }, 0);
}

console.log((negativeSummation, 1, 3, 11));
//this is not working? So lets use the debugger to
//step through the code!


$ node debug negativeSummation.js
(node:18124) [DEP0068] DeprecationWarning: `node debug` is deprecated. Please us
e `node inspect` instead.
< Debugger listening on ws://127.0.0.1:9229/14f57090-774a-40b4-820a-9a83cd90e7b3

< For help see https://nodejs.org/en/docs/inspector
Break on start in negativeSummation.js:1
> 1 (function (exports, require, module, __filename, __dirname) { function negat
iveSummation(...args) {
  2   return args.reduce((arg, total) => {
  3     return total-arg;
debug>

const fs = require('fs');
const server = require('http').createServer();

server.on('request', (req, res) => {
  const src = fs.createReadStream('./giganticFile.txt');
  src.pipe(res); //here wer'e piping the contents of the file to the res obj
});

server.listen(8888);

Four Types of Streams in Node

//readStream2.js
const { Readable } = require('stream'); // implement a readable stream, require a READABLE interface, and construct an object

const streamIn = new Readable({
  read(size) {
    setTimeout(() => {
      if(this.currentCharCode > 90){ //stop at letter z
        this.push(null);
        return;
      }
      this.push(String.fromCharCode(this.currentCharCode++));
  }, 100);
 }
});

streamIn.currentCharCode = 65;
streamIn.pipe(process.stdout);
//writeStream.js
const { Writable } = require('stream');

const streamOut = new Writable({
  write(chunk, encoding, callback) {
  console.log(chunk.toString());
  callback();
  }
});

// basically anything this receives will echo right back.
process.stdin.pipe(streamOut); // piping stdin which is a readable stream into streamOut

At bash, type node readStream3.js | head -c3

//readStream3.js
//run this on linux
const { Readable } = require('stream'); // implement a readable stream, require a READABLE interface, and construct an object

const streamIn = new Readable({
  read(size) {
    setTimeout(() => {
      if(this.currentCharCode > 90){ //stop at letter z
        this.push(null);
        return;
      }
      this.push(String.fromCharCode(this.currentCharCode++));
  }, 100);
 }
});

streamIn.currentCharCode = 65;
streamIn.pipe(process.stdout);

process.on('exit', () => {
  console.error(`\n\ncurrentCharCode : ${streamIn.currentCharCode}`);
});
//stdout is not a tty got this on git-bash for win
process.stdout.on('error', process.exit); //register an error on stdout, and call process.exit when error occurs

//stanZip2.js
const fs = require('fs');
const zlib = require('zlib');
const file = process.argv[2];

fs.createReadStream(file)
  .pipe(zlib.createGzip())
  .on('data', () => process.stdout.write('☻'))  //listening to data and update progress bar
  .pipe(fs.createWriteStream(file + '.gz'))
  .on('finish', () => console.log('Completed'));

console output

$ node stanZip2.js tux.txt
☻☻Completed

//stanZip3.js
const fs = require('fs');
const zlib = require('zlib');
const file = process.argv[2];
const crypto = require('crypto');

const { Transform } = require('stream');

const progress = new Transform({
  transform(chunk, encoding, callback) {
    process.stdout.write('☻');
    callback(null, chunk);
  }
});

fs.createReadStream(file)
  .pipe(zlib.createGzip())
  .pipe(crypto.createCipher('aes192', 'a_secret'))
  .pipe(progress)
  .pipe(fs.createWriteStream(file + '.zz'))
  .on('finish', () => console.log('Completed'));

//spawnList.js
const { spawn } = require('child_process');
const child = spawn('ls');

child.on('exit', function (code, signal) {
  console.log(`child process exited with code ${code}, ${signal}`)}); //here if the command fails, it will signal to Jenkins, and
  //test will be marked as failed.

//spawnPipeWC.js
const { spawn } = require('child_process');
const child = spawn('wc');

process.stdin.pipe(child.stdin);

child.stdout.on('data', (data) => {
  console.log(`child stdout:\n${data}`);
});

//spwnPipeFindWC.js
const { spawn } = require('child_process');
const find = spawn('find', ['.', '-type', 'f']);
const wc = spawn('wc', ['-l']);

process.stdin.pipe(wc.stdin);

wc.stdout.on('data', (data) => {
  console.log(`child stdout:\n${data}`);
});

//spawnFind.js
const { spawn } = require('child_process');
const child = spawn('find', ['.', '-type', 'f'], {
  stdio: 'inherit'
});

//parent.js
const { fork } = require('child_process');
const forked = fork('child.js');

forked.on('message', (msg) => {
  console.log('Message from child', msg);
});

forked.send({ hola: 'multiverse' });
//child.js
process.on('message', (msg) => {
  console.log('Message from parent:', msg);
});

let counter = 0;

setInterval(() => {
  process.send({ counter: counter++ });
}, 1000);

//HttpServer.js
const http = require('http');
const pid = process.pid;

http.createServer((req, res) => {
  for (let i=0; i<1e7; i++); //to simulate CPU work
  res.end(`Work handled by process ${pid}`);

}).listen(8080, () => {
  console.log(`Beginning process start ${pid}`);
});

Apache AB on a Windows machine

C:\xampp\apache\bin>ab -c200 -t10 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Finished 1442 requests


Server Software:
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        28 bytes

Concurrency Level:      200
Time taken for tests:   10.002 seconds
Complete requests:      1442
Failed requests:        0
Total transferred:      148526 bytes
HTML transferred:       40376 bytes
Requests per second:    144.17 [#/sec] (mean)
Time per request:       1387.246 [ms] (mean)
Time per request:       6.936 [ms] (mean, across all concurrent requests)
Transfer rate:          14.50 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1  12.6      0     478
Processing:  1100 1239 303.8   1133    2479
Waiting:     1100 1239 303.8   1133    2479
Total:       1100 1240 304.0   1133    2480

Percentage of the requests served within a certain time (ms)
  50%   1133
  66%   1137
  75%   1146
  80%   1154
  90%   1678
  95%   2095
  98%   2329
  99%   2403
 100%   2480 (longest request)

C:\xampp\apache\bin>

//cluster.js
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
  const cpus = os.cpus().length;

  console.log(`Forking for ${cpus} CPUs`);
  for (let i = 0; i <cpus; i++) {
    cluster.fork();
  }
} else {
  require('./HttpServer');
}
C:\xampp\apache\bin>ab -c200 -t10 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Finished 2989 requests


Server Software:
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        28 bytes

Concurrency Level:      200
Time taken for tests:   10.003 seconds
Complete requests:      2989
Failed requests:        0
Total transferred:      307867 bytes
HTML transferred:       83692 bytes
Requests per second:    298.82 [#/sec] (mean)
Time per request:       669.296 [ms] (mean)
Time per request:       3.346 [ms] (mean, across all concurrent requests)
Transfer rate:          30.06 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.5      0      24
Processing:    85  645 107.6    661     795
Waiting:       81  644 107.7    660     795
Total:         85  645 107.6    661     795

Percentage of the requests served within a certain time (ms)
  50%    661
  66%    685
  75%    696
  80%    703
  90%    735
  95%    766
  98%    776
  99%    779
 100%    795 (longest request)

C:\xampp\apache\bin>

//BroadCast/cluster.js
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
  const cpus = os.cpus().length;

  console.log(`Forking for ${cpus} CPUs`);
  for (let i = 0; i <cpus; i++) {
    cluster.fork();
  }

  console.dir(cluster.workers, { depth: 0 });
  Object.values(cluster.workers).forEach(worker => {
    worker.send(`Hi Worker ${worker.id}`)
  });
} else {
  require('./HttpServer');
}

Terminal Output for BroadCasting messages via fork api in cluster.js

$ node cluster.js
Forking for 4 CPUs
{ '1': [Object], '2': [Object], '3': [Object], '4': [Object] }
Beginning process start 5980
Beginning process start 9816
Beginning process start 7144
Beginning process start 3212

//BroadCast/HttpServer.js broadcasting messages!
const http = require('http');
const pid = process.pid;

http.createServer((req, res) => {
  for (let i=0; i<1e7; i++); //to simulate CPU work
  res.end(`Work handled by process ${pid}`);

}).listen(8080, () => {
  console.log(`Beginning process start ${pid}`);
});

process.on('message', msg => {
  console.log(`Message from master: ${msg}`);
});

messages are not in order

$ node cluster.js
Forking for 4 CPUs
{ '1': [Object], '2': [Object], '3': [Object], '4': [Object] }
Message from master: Hi Worker 1
Beginning process start 428
Message from master: Hi Worker 2
Message from master: Hi Worker 3
Beginning process start 7192
Message from master: Hi Worker 4
Beginning process start 8336
Beginning process start 7092

//cluster2.js
const cluster = require('cluster');
const os = require('os');

//make db call (mock)
const usersDB = function() {
  this.count = this.count || 5;
  this.count = this.count * this.count;
  return this.count;
}
if (cluster.isMaster) {
  const cpus = os.cpus().length;

  console.log(`Forking for ${cpus} CPUs`);
  for (let i = 0; i <cpus; i++) {
    cluster.fork();
  }

const updateWorkers = () => {
  console.dir(cluster.workers, { depth: 0 });
  const usersCount = usersDB();
  Object.values(cluster.workers).forEach(worker => {
      worker.send({usersCount}); //broadcast number of users

  });
};

setInterval(updateWorkers, 1000); //update workers on 10 second interval, every 10 seconds worker(s) will receive count over comm channel    
} else {
  require('./HttpServer2');
}
//HttpServer2.js
const http = require('http');
const pid = process.pid;

let usersCount; //variable is set at the global level

http.createServer((req, res) => {
  for (let i=0; i<1e7; i++); //to simulate CPU work
  res.write(`Work handled by process ${pid}`); //changed write to output both messages
  res.end(`Users: ${usersCount}`); //here the userCounts variable is controlled by the message interface
}).listen(8080, () => {
  console.log(`Beginning process start ${pid}`);
});

process.on('message', msg => {
//  console.log(`Message from master: ${msg.toString()}`);
  usersCount = msg.usersCount;
});
// the master process in cluster2.js will reset the userscount every 10 secs through invocation of the mock db call

//MasterCluster.js
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster){
  const cpus = os.cpus().length;
  for (let i = 0; i < cpus; i++) {
    cluster.fork();
   }

   cluster.on('exit', (worker, code, signal) => {
     if (code !== 0 && !worker.exitedAfterDisconnect) {
       console.log(`Worker ${worker.id} has crashed. ` +
         'Spinning up a new worker...');
      cluster.fork();
     }
  });
} else {
  require('./HttpServer');
}
//Availability/HttpServer.js
const http = require('http');
const pid = process.pid;

http.createServer((req, res) => {
  for (let i=0; i<1e7; i++); //to simulate CPU work
  res.end(`Work handled by process ${pid}`);

}).listen(8080, () => {
  console.log(`Beginning process start ${pid}`);
});

setTimeout(() => {
  process.exit(1) // kill at random

}, Math.random() * 10000);

Terminal Output

$ node MasterCluster.js
Beginning process start 9692
Beginning process start 7092
Beginning process start 5532
Beginning process start 7192
Worker 4 has crashed. Spinning up a new worker...
Beginning process start 6472
Worker 2 has crashed. Spinning up a new worker...
Beginning process start 10716
Worker 6 has crashed. Spinning up a new worker...
Beginning process start 12180
Worker 1 has crashed. Spinning up a new worker...
Beginning process start 12204
Worker 8 has crashed. Spinning up a new worker...
Beginning process start 796
Worker 5 has crashed. Spinning up a new worker...
Beginning process start 10224
Worker 9 has crashed. Spinning up a new worker...
Beginning process start 10688
Worker 3 has crashed. Spinning up a new worker...
Beginning process start 11208
Worker 12 has crashed. Spinning up a new worker...

AB terminal output for MasterCluster.js

C:\xampp\apache\bin>ab -c200 -t10 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
apr_socket_recv: An existing connection was forcibly closed by the remote host.
  (730054)
Total of 482 requests completed

//zeroDwnTime/MstrCluster.js
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster){
  const cpus = os.cpus().length;
  for (let i = 0; i < cpus; i++) {
    cluster.fork();
   }

   cluster.on('exit', (worker, code, signal) => {
     if (code !== 0 && !worker.exitedAfterDisconnect) {
       console.log(`Worker ${worker.id} has crashed. ` +
         'Spinning up a new worker...');
      cluster.fork();
     }
  });

process.on('SIGUSR2', () => {
  const workers = Object.values(cluster.workers);

  const restartWorker = (workerIndex) => {
    const worker = workers[workerIndex];
    if (!worker)
      return;

    worker.on('exit', () => {
      if (!worker.exitedAfterDisconnect) //set flag if true, fork new worker
      console.log(`Exited process ${worker.process.pid}`)
      cluster.fork().on('Listening ... ', () => {
        restartWorker(workerIndex + 1);
      });
    });
      worker.disconnect();
  };

  restartWorker(0);
});

} else {
  require('./HttpServer');
}

PM2 - is cool!

just use pm2 reload all for zero downtime reload

https://github.com/Unitech/pm2

(3) BDD with Node

// Code Stub 01

// Code Stub 02

// Code Stub 03

// Code Stub 04

Old Notes (scanned)

Node Style Guide >>>

     https://github.com/felixge/node-style-guide

About

Node stuff

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages