balena-supervisor/application.coffee
2013-07-21 03:42:13 +03:00

87 lines
2.3 KiB
CoffeeScript

{spawn} = require('child_process')
{getpwnam} = require('posix')
async = require('async')
class Application
constructor: (@repo, @path, @user) ->
@process = null
@inprogress = false
@queue = []
@options =
cwd: @path
stdio: 'inherit'
uid: getpwnam(@user).uid
env:
USER: @user
USERNAME: @user
_init: (callback) ->
tasks = [
# Create the directory for the project
(callback) =>
spawn('mkdir', ['-p', @path]).on('exit', callback).on('error', callback)
# Change the owner to the user
(callback) =>
spawn('chown', [@user, @path]).on('exit', callback).on('error', callback)
# Initalize a new empty git repo
(callback) =>
spawn('git', ['init'], @options).on('exit', callback).on('error', callback)
# Add the remote origin to the repo
(callback) =>
spawn('git', ['remote', 'add', 'origin', @repo], @options).on('exit', callback).on('error', callback)
]
async.series(tasks, callback)
_start: (callback) ->
if not @process
@process = spawn('foreman', ['start'], @options)
callback?()
_stop: (callback) ->
# Kill will return false if process has already died
handler = =>
@process = null
callback?()
spawn('pkill', ['-TERM', '-P', @process.pid], @options).on('exit', handler).on('error', handler)
_update: (callback) ->
shouldRestartApp = Boolean(@process)
tasks = [
# Stop the application if running
(callback) => shouldRestartApp and @_stop(callback) or callback()
# Pull new commits
(callback) =>
spawn('git', ['pull', 'origin', 'master'], @options).on('exit', callback).on('error', callback)
# Install npm dependencies
(callback) =>
spawn('npm', ['install'], @options).on('exit', callback).on('error', callback)
# Start the app
(callback) => shouldRestartApp and @_start(callback) or callback()
]
async.series(tasks, callback)
# These methods shouldn't be called in parallel, queue them if they conflict
['start', 'stop', 'init', 'update'].forEach((method) ->
Application::[method] = (callback) ->
if @inprogress
@queue.push([method, arguments])
else
@inprogress = true
@['_' + method](=>
@inprogress = false
if @queue.length isnt 0
[next, args] = @queue.shift()
@[next](args...)
callback?(arguments...)
)
)
module.exports = Application