Merge pull request #116 from medicomp/master
Compatibility with Node.js cluster module
This commit is contained in:
commit
94249c24ea
8 changed files with 1392 additions and 35 deletions
82
README.md
82
README.md
|
@ -107,6 +107,7 @@ Set these variables in the `ipc.config` scope to overwrite or set default values
|
||||||
retry : 500,
|
retry : 500,
|
||||||
maxRetries : false,
|
maxRetries : false,
|
||||||
stopRetrying : false,
|
stopRetrying : false,
|
||||||
|
unlink : true,
|
||||||
interfaces : {
|
interfaces : {
|
||||||
localAddress: false,
|
localAddress: false,
|
||||||
localPort : false,
|
localPort : false,
|
||||||
|
@ -136,6 +137,7 @@ Set these variables in the `ipc.config` scope to overwrite or set default values
|
||||||
| retry | this is the time in milliseconds a client will wait before trying to reconnect to a server if the connection is lost. This does not effect UDP sockets since they do not have a client server relationship like Unix Sockets and TCP Sockets. |
|
| retry | this is the time in milliseconds a client will wait before trying to reconnect to a server if the connection is lost. This does not effect UDP sockets since they do not have a client server relationship like Unix Sockets and TCP Sockets. |
|
||||||
| maxRetries | if set, it represents the maximum number of retries after each disconnect before giving up and completely killing a specific connection |
|
| maxRetries | if set, it represents the maximum number of retries after each disconnect before giving up and completely killing a specific connection |
|
||||||
| stopRetrying| Defaults to false meaning clients will continue to retry to connect to servers indefinitely at the retry interval. If set to any number the client will stop retrying when that number is exceeded after each disconnect. If set to true in real time it will immediately stop trying to connect regardless of maxRetries. If set to 0, the client will ***NOT*** try to reconnect. |
|
| stopRetrying| Defaults to false meaning clients will continue to retry to connect to servers indefinitely at the retry interval. If set to any number the client will stop retrying when that number is exceeded after each disconnect. If set to true in real time it will immediately stop trying to connect regardless of maxRetries. If set to 0, the client will ***NOT*** try to reconnect. |
|
||||||
|
| unlink| Defaults to true meaning that the module will take care of deleting the IPC socket prior to startup. If you use `node-ipc` in a clustered environment where there will be multiple listeners on the same socket, you must set this to `false` and then take care of deleting the socket in your own code. |
|
||||||
| interfaces| primarily used when specifying which interface a client should connect through. see the [socket.connect documentation in the node.js api](https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener) |
|
| interfaces| primarily used when specifying which interface a client should connect through. see the [socket.connect documentation in the node.js api](https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener) |
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -790,5 +792,85 @@ Writing explicit buffers, int types, doubles, floats etc. as well as big endian
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Server with the `cluster` Module
|
||||||
|
`node-ipc` can be used with Node.js' [cluster module](https://nodejs.org/api/cluster.html) to provide the ability to have multiple readers for a single socket. Doing so simply requires you to set the `unlink` property in the config to `false` and take care of unlinking the socket path in the master process:
|
||||||
|
|
||||||
|
##### Server
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const ipc=require('../../../node-ipc');
|
||||||
|
const cpuCount = require('os').cpus().length;
|
||||||
|
const cluster = require('cluster');
|
||||||
|
const socketPath = '/tmp/ipc.sock';
|
||||||
|
|
||||||
|
ipc.config.unlink = false;
|
||||||
|
|
||||||
|
if (cluster.isMaster) {
|
||||||
|
if (fs.existsSync(socketPath)) {
|
||||||
|
fs.unlinkSync(socketPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < cpuCount; i++) {
|
||||||
|
cluster.fork();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
ipc.serve(
|
||||||
|
socketPath,
|
||||||
|
function() {
|
||||||
|
ipc.server.on(
|
||||||
|
'currentDate',
|
||||||
|
function(data,socket) {
|
||||||
|
console.log(`pid ${process.pid} got: `, data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipc.server.start();
|
||||||
|
console.log(`pid ${process.pid} listening on ${socketPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Client
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const ipc = require('../../node-ipc');
|
||||||
|
|
||||||
|
const socketPath = '/tmp/ipc.sock';
|
||||||
|
|
||||||
|
//loop forever so you can see the pid of the cluster sever change in the logs
|
||||||
|
setInterval(
|
||||||
|
function() {
|
||||||
|
ipc.connectTo(
|
||||||
|
'world',
|
||||||
|
socketPath,
|
||||||
|
connecting
|
||||||
|
);
|
||||||
|
},
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
|
||||||
|
function connecting(socket) {
|
||||||
|
ipc.of.world.on(
|
||||||
|
'connect',
|
||||||
|
function() {
|
||||||
|
ipc.of.world.emit(
|
||||||
|
'currentDate',
|
||||||
|
{
|
||||||
|
message: new Date().toISOString()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ipc.disconnect('world');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
#### Licensed under DBAD license
|
#### Licensed under DBAD license
|
||||||
See the [DBAD license](https://github.com/philsturgeon/dbad) in your language or our [licence.md](https://github.com/RIAEvangelist/node-phidget-API/blob/master/license.md) file.
|
See the [DBAD license](https://github.com/philsturgeon/dbad) in your language or our [licence.md](https://github.com/RIAEvangelist/node-phidget-API/blob/master/license.md) file.
|
||||||
|
|
|
@ -58,10 +58,14 @@ class Server extends Events{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.unlink(
|
if(this.config.unlink){
|
||||||
this.path,
|
fs.unlink(
|
||||||
startServer.bind(this)
|
this.path,
|
||||||
);
|
startServer.bind(this)
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
startServer.bind(this)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Defaults{
|
||||||
this.encoding='utf8';
|
this.encoding='utf8';
|
||||||
this.rawBuffer=false;
|
this.rawBuffer=false;
|
||||||
this.sync=false;
|
this.sync=false;
|
||||||
|
this.unlink=true;
|
||||||
|
|
||||||
this.delimiter='\f';
|
this.delimiter='\f';
|
||||||
|
|
||||||
|
|
31
example/clusterUnixSocket/cluster-client.js
Normal file
31
example/clusterUnixSocket/cluster-client.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const ipc = require('../../node-ipc');
|
||||||
|
|
||||||
|
const socketPath = '/tmp/ipc.sock';
|
||||||
|
|
||||||
|
//loop forever so you can see the pid of the cluster sever change in the logs
|
||||||
|
setInterval(
|
||||||
|
function() {
|
||||||
|
ipc.connectTo(
|
||||||
|
'world',
|
||||||
|
socketPath,
|
||||||
|
connecting
|
||||||
|
);
|
||||||
|
},
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
|
||||||
|
function connecting(socket) {
|
||||||
|
ipc.of.world.on(
|
||||||
|
'connect',
|
||||||
|
function() {
|
||||||
|
ipc.of.world.emit(
|
||||||
|
'currentDate',
|
||||||
|
{
|
||||||
|
message: new Date().toISOString()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ipc.disconnect('world');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
32
example/clusterUnixSocket/cluster-server.js
Normal file
32
example/clusterUnixSocket/cluster-server.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const ipc=require('../../../node-ipc');
|
||||||
|
const cpuCount = require('os').cpus().length;
|
||||||
|
const cluster = require('cluster');
|
||||||
|
const socketPath = '/tmp/ipc.sock';
|
||||||
|
|
||||||
|
ipc.config.unlink = false;
|
||||||
|
|
||||||
|
if (cluster.isMaster) {
|
||||||
|
if (fs.existsSync(socketPath)) {
|
||||||
|
fs.unlinkSync(socketPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < cpuCount; i++) {
|
||||||
|
cluster.fork();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
ipc.serve(
|
||||||
|
socketPath,
|
||||||
|
function() {
|
||||||
|
ipc.server.on(
|
||||||
|
'currentDate',
|
||||||
|
function(data,socket) {
|
||||||
|
console.log(`pid ${process.pid} got: `, data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipc.server.start();
|
||||||
|
console.log(`pid ${process.pid} listening on ${socketPath}`);
|
||||||
|
}
|
1209
package-lock.json
generated
Normal file
1209
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -15,10 +15,9 @@
|
||||||
"js-queue": "2.0.0"
|
"js-queue": "2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"codacy-coverage": "1.1.3",
|
"codacy-coverage": "2.0.0",
|
||||||
"jasmine": "2.4.1",
|
"jasmine": "2.4.1",
|
||||||
"istanbul": "0.4.1",
|
"istanbul": "0.4.1",
|
||||||
"codacy-coverage": "2.0.0",
|
|
||||||
"node-cmd": "2.0.0"
|
"node-cmd": "2.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -28,7 +27,7 @@
|
||||||
"coverup": "cat ./spec/coverage/lcov.info | codacy-coverage"
|
"coverup": "cat ./spec/coverage/lcov.info | codacy-coverage"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
"cover"
|
"cover"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"IPC",
|
"IPC",
|
||||||
|
|
|
@ -61,13 +61,11 @@ class IPC{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function log(){
|
function log(...args){
|
||||||
if(this.config.silent){
|
if(this.config.silent){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const args=Array.prototype.slice.call(arguments);
|
|
||||||
|
|
||||||
for(let i=0, count=args.length; i<count; i++){
|
for(let i=0, count=args.length; i<count; i++){
|
||||||
if(typeof args[i] != 'object'){
|
if(typeof args[i] != 'object'){
|
||||||
continue;
|
continue;
|
||||||
|
@ -111,9 +109,9 @@ function serve(path,callback){
|
||||||
}
|
}
|
||||||
if(!path){
|
if(!path){
|
||||||
this.log(
|
this.log(
|
||||||
'Server path not specified, so defaulting to'.notice,
|
'Server path not specified, so defaulting to',
|
||||||
'ipc.config.socketRoot + ipc.config.appspace + ipc.config.id'.variable,
|
'ipc.config.socketRoot + ipc.config.appspace + ipc.config.id',
|
||||||
(this.config.socketRoot+this.config.appspace+this.config.id).data
|
this.config.socketRoot+this.config.appspace+this.config.id
|
||||||
);
|
);
|
||||||
path=this.config.socketRoot+this.config.appspace+this.config.id;
|
path=this.config.socketRoot+this.config.appspace+this.config.id;
|
||||||
}
|
}
|
||||||
|
@ -153,9 +151,9 @@ function serveNet(host,port,UDPType,callback){
|
||||||
}
|
}
|
||||||
if(!host){
|
if(!host){
|
||||||
this.log(
|
this.log(
|
||||||
'Server host not specified, so defaulting to'.notice,
|
'Server host not specified, so defaulting to',
|
||||||
'ipc.config.networkHost'.variable,
|
'ipc.config.networkHost',
|
||||||
this.config.networkHost.data
|
this.config.networkHost
|
||||||
);
|
);
|
||||||
host=this.config.networkHost;
|
host=this.config.networkHost;
|
||||||
}
|
}
|
||||||
|
@ -178,8 +176,8 @@ function serveNet(host,port,UDPType,callback){
|
||||||
}
|
}
|
||||||
if(!port){
|
if(!port){
|
||||||
this.log(
|
this.log(
|
||||||
'Server port not specified, so defaulting to'.notice,
|
'Server port not specified, so defaulting to',
|
||||||
'ipc.config.networkPort'.variable,
|
'ipc.config.networkPort',
|
||||||
this.config.networkPort
|
this.config.networkPort
|
||||||
);
|
);
|
||||||
port=this.config.networkPort;
|
port=this.config.networkPort;
|
||||||
|
@ -227,16 +225,16 @@ function connect(id,path,callback){
|
||||||
|
|
||||||
if(!id){
|
if(!id){
|
||||||
this.log(
|
this.log(
|
||||||
'Service id required'.warn,
|
'Service id required',
|
||||||
'Requested service connection without specifying service id. Aborting connection attempt'.notice
|
'Requested service connection without specifying service id. Aborting connection attempt'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!path){
|
if(!path){
|
||||||
this.log(
|
this.log(
|
||||||
'Service path not specified, so defaulting to'.notice,
|
'Service path not specified, so defaulting to',
|
||||||
'ipc.config.socketRoot + ipc.config.appspace + id'.variable,
|
'ipc.config.socketRoot + ipc.config.appspace + id',
|
||||||
(this.config.socketRoot+this.config.appspace+id).data
|
(this.config.socketRoot+this.config.appspace+id).data
|
||||||
);
|
);
|
||||||
path=this.config.socketRoot+this.config.appspace+id;
|
path=this.config.socketRoot+this.config.appspace+id;
|
||||||
|
@ -245,9 +243,9 @@ function connect(id,path,callback){
|
||||||
if(this.of[id]){
|
if(this.of[id]){
|
||||||
if(!this.of[id].socket.destroyed){
|
if(!this.of[id].socket.destroyed){
|
||||||
this.log(
|
this.log(
|
||||||
'Already Connected to'.notice,
|
'Already Connected to',
|
||||||
id.variable,
|
id,
|
||||||
'- So executing success without connection'.notice
|
'- So executing success without connection'
|
||||||
);
|
);
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
|
@ -267,8 +265,8 @@ function connect(id,path,callback){
|
||||||
function connectNet(id,host,port,callback){
|
function connectNet(id,host,port,callback){
|
||||||
if(!id){
|
if(!id){
|
||||||
this.log(
|
this.log(
|
||||||
'Service id required'.warn,
|
'Service id required',
|
||||||
'Requested service connection without specifying service id. Aborting connection attempt'.notice
|
'Requested service connection without specifying service id. Aborting connection attempt'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -284,9 +282,9 @@ function connectNet(id,host,port,callback){
|
||||||
}
|
}
|
||||||
if(!host){
|
if(!host){
|
||||||
this.log(
|
this.log(
|
||||||
'Server host not specified, so defaulting to'.notice,
|
'Server host not specified, so defaulting to',
|
||||||
'ipc.config.networkHost'.variable,
|
'ipc.config.networkHost',
|
||||||
this.config.networkHost.data
|
this.config.networkHost
|
||||||
);
|
);
|
||||||
host=this.config.networkHost;
|
host=this.config.networkHost;
|
||||||
}
|
}
|
||||||
|
@ -297,8 +295,8 @@ function connectNet(id,host,port,callback){
|
||||||
}
|
}
|
||||||
if(!port){
|
if(!port){
|
||||||
this.log(
|
this.log(
|
||||||
'Server port not specified, so defaulting to'.notice,
|
'Server port not specified, so defaulting to',
|
||||||
'ipc.config.networkPort'.variable,
|
'ipc.config.networkPort',
|
||||||
this.config.networkPort
|
this.config.networkPort
|
||||||
);
|
);
|
||||||
port=this.config.networkPort;
|
port=this.config.networkPort;
|
||||||
|
@ -314,10 +312,11 @@ function connectNet(id,host,port,callback){
|
||||||
|
|
||||||
if(this.of[id]){
|
if(this.of[id]){
|
||||||
if(!this.of[id].socket.destroyed){
|
if(!this.of[id].socket.destroyed){
|
||||||
|
|
||||||
this.log(
|
this.log(
|
||||||
'Already Connected to'.notice,
|
'Already Connected to',
|
||||||
id.variable,
|
id,
|
||||||
'- So executing success without connection'.notice
|
'- So executing success without connection'
|
||||||
);
|
);
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue