Skip to content

Instantly share code, notes, and snippets.

@loklaan
Last active September 13, 2015 05:53
Show Gist options
  • Save loklaan/d9bc428d3300a42e7bda to your computer and use it in GitHub Desktop.
Save loklaan/d9bc428d3300a42e7bda to your computer and use it in GitHub Desktop.
Singleton process via sockets

Singleton Process

An application that manages singleton process.

It will print any cli arguments used when executing additonal instances of the application.

Example

$ node SingletonApplication.js
$ Starting: first Application instance
$ Listening for additional Application instances...

And in another terminal instance

$ node SingletonApplication.js --Hello "World"
$ Starting: additional Application instance
$
$   ...Sent args to first Application
$
$ Finishing: additional Application instance

The first terminal instance will produce extra lines

$ Arguments accepted:
$   { _: [], Hello: 'World', '$0': 'SingletonApplication.js' }
var os = require('os');
var fs = require('fs');
var net = require('net');
var path = require('path');
var argv = require('yargs').argv;
// Singleton process class.
//
// When first run, this Application will remain open, listening for additional
// Applications that are executed elsewhere in the system. Additional Applications
// will send their cli arguments to the first Application before closing themselves.
function Application(args) {
var self = this;
self.socketPath = path.join(os.tmpdir(), "atom-"+process.env.USER+".sock");
// Additional Application's will connect.
self.client = net.connect({path: self.socketPath}, self.handleAdditionalApplication.bind(this, args));
// The first Application will fail at connecting, instead starting the server
// for additional Application's to connect onto.
self.client.on('error', self.listenForArgumentsFromNewProcess.bind(this));
}
Application.prototype.handleAdditionalApplication = function(args) {
console.log('Starting: additional Application instance')
var self = this;
this.passArgsToServer(args)
}
Application.prototype.passArgsToServer = function(args) {
var self = this;
self.client.write(JSON.stringify(args), function() {
console.log('\n ...Sent args to first Application\n')
self.client.end();
console.log('Finishing: additional Application instance')
process.exit();
})
}
/**
* The master application process will run a socket server to accept arguments
* from additional processes.
*/
Application.prototype.listenForArgumentsFromNewProcess = function() {
console.log('Starting: first Application instance')
var self = this;
// Clean
self.unlinkSocketFile()
var server = net.createServer(function(connection) {
connection.on('data', function(data) {
self.printArguments(JSON.parse(data))
})
});
console.log('Listening for additional Application instances...')
server.listen(self.socketPath);
server.on('error', function(err) {
console.error('Application server failed', err);
});
}
/**
* Removes our applications socket file.
*/
Application.prototype.unlinkSocketFile = function() {
var self = this;
if (process.platform == 'win32') {
return;
} else {
if (fs.existsSync(self.socketPath)) {
try {
fs.unlinkSync(self.socketPath)
} catch (e) {
throw e;
}
}
}
}
Application.prototype.printArguments = function(args) {
console.log("Arguments accepted:\n", args)
}
var app = new Application(argv);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment