Skip to content

Instantly share code, notes, and snippets.

@marcello3d
Created February 11, 2011 05:42
Show Gist options
  • Save marcello3d/821977 to your computer and use it in GitHub Desktop.
Save marcello3d/821977 to your computer and use it in GitHub Desktop.
hot swapping for node.js
/*
* This file is part of the Spludo Framework.
* Copyright (c) 2009-2010 DracoBlue, http://dracoblue.net/
*
* Licensed under the terms of MIT License. For the full copyright and license
* information, please see the LICENSE file in the root folder.
*/
/*
* based on https://github.com/DracoBlue/spludo/blob/master/build/run_dev_server.js
* Rewritten by marcello@cellosoft.com
*/
var child_process = require('child_process'),
fs = require("fs"),
util = require("util"),
path = require("path")
if (process.ARGV.length < 3) {
util.debug("usage: %s %s <server.js>", process.ARGV[0], process.ARGV[1])
process.exit(1)
}
var child = null,
watchedFiles = [],
restarting = false,
shutdown = false,
selfPath = path.resolve(__filename),
pidPath = selfPath + '.pid',
mainScript = process.ARGV[2] || "dev_server.js"
function restart() {
if (!restarting) {
restarting = true
if (child) {
stop()
} else {
start()
}
}
}
function start() {
try {
var pidData = fs.readFileSync(pidPath);
var oldPid = parseInt(pidData)
if (oldPid) {
util.debug('Killing old server ('+oldPid+')')
process.kill(oldPid)
}
} catch (e) {}
watchFiles()
child = child_process.spawn(process.ARGV[0], [mainScript])
util.debug("<"+ mainScript + "> Started... (pid = "+child.pid+")")
fs.writeFileSync(pidPath, String(child.pid))
child.stdout.on('data', function (data) {
process.stdout.write(data)
});
child.stderr.on('data', function (data) {
util.print(data)
});
child.on('exit', function (code, signal) {
child = null
try {
fs.unlinkSync(pidPath)
} catch (e) {}
if (restarting && !shutdown) {
unwatchFiles()
start()
} else if ((code || signal) && !shutdown) {
util.debug("<" + mainScript + "> Exited with code " + (code || signal) + ", waiting for file change...\n")
} else {
process.exit(code)
}
restarting = false
});
}
function stop() {
child && child.kill()
}
function watchFiles() {
child_process.exec('find .', function(error, stdout, stderr) {
var files = stdout.trim().split("\n")
files.forEach(function(file) {
var resolvedFile = path.resolve(file)
if (path.resolve(pidPath) != resolvedFile) {
var isRunScript = resolvedFile == selfPath
watchedFiles.push(file);
fs.watchFile(file, {interval:500}, function(current, previous) {
if (!shutdown && (current.mtime.valueOf() != previous.mtime.valueOf() ||
current.ctime.valueOf() != previous.ctime.valueOf())) {
if (isRunScript) {
util.debug("<" + file + "> changed! (i.e. this hot swap code) Shutting down...")
shutdown = true
stop()
} else {
util.debug('<' + file + '> changed')
restart()
}
}
})
}
})
})
}
function unwatchFiles() {
watchedFiles.forEach(function(file) { fs.unwatchFile(file) })
watchedFiles = []
}
process.on('exit', stop)
start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment