mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
Rename samples subdirectories
This commit is contained in:
256
samples/CoffeeScript/rack_application.coffee
Normal file
256
samples/CoffeeScript/rack_application.coffee
Normal file
@@ -0,0 +1,256 @@
|
||||
# The `RackApplication` class is responsible for managing a
|
||||
# [Nack](http://josh.github.com/nack/) pool for a given Rack
|
||||
# application. Incoming HTTP requests are dispatched to
|
||||
# `RackApplication` instances by an `HttpServer`, where they are
|
||||
# subsequently handled by a pool of Nack worker processes. By default,
|
||||
# Pow tells Nack to use a maximum of two worker processes per
|
||||
# application, but this can be overridden with the configuration's
|
||||
# `workers` option.
|
||||
#
|
||||
# Before creating the Nack pool, Pow executes the `.powrc` and
|
||||
# `.powenv` scripts if they're present in the application root,
|
||||
# captures their environment variables, and passes them along to the
|
||||
# Nack worker processes. This lets you modify your `RUBYOPT` to use
|
||||
# different Ruby options, for example.
|
||||
#
|
||||
# If [rvm](http://rvm.beginrescueend.com/) is installed and an
|
||||
# `.rvmrc` file is present in the application's root, Pow will load
|
||||
# both before creating the Nack pool. This makes it easy to run an
|
||||
# app with a specific version of Ruby.
|
||||
#
|
||||
# Nack workers remain running until they're killed, restarted (by
|
||||
# touching the `tmp/restart.txt` file in the application root), or
|
||||
# until the application has not served requests for the length of time
|
||||
# specified in the configuration's `timeout` option (15 minutes by
|
||||
# default).
|
||||
|
||||
async = require "async"
|
||||
fs = require "fs"
|
||||
nack = require "nack"
|
||||
|
||||
{bufferLines, pause, sourceScriptEnv} = require "./util"
|
||||
{join, exists, basename, resolve} = require "path"
|
||||
|
||||
module.exports = class RackApplication
|
||||
# Create a `RackApplication` for the given configuration and
|
||||
# root path. The application begins life in the uninitialized
|
||||
# state.
|
||||
constructor: (@configuration, @root, @firstHost) ->
|
||||
@logger = @configuration.getLogger join "apps", basename @root
|
||||
@readyCallbacks = []
|
||||
@quitCallbacks = []
|
||||
@statCallbacks = []
|
||||
|
||||
# Queue `callback` to be invoked when the application becomes ready,
|
||||
# then start the initialization process. If the application's state
|
||||
# is ready, the callback is invoked immediately.
|
||||
ready: (callback) ->
|
||||
if @state is "ready"
|
||||
callback()
|
||||
else
|
||||
@readyCallbacks.push callback
|
||||
@initialize()
|
||||
|
||||
# Tell the application to quit and queue `callback` to be invoked
|
||||
# when all workers have exited. If the application has already quit,
|
||||
# the callback is invoked immediately.
|
||||
quit: (callback) ->
|
||||
if @state
|
||||
@quitCallbacks.push callback if callback
|
||||
@terminate()
|
||||
else
|
||||
callback?()
|
||||
|
||||
# Stat `tmp/restart.txt` in the application root and invoke the
|
||||
# given callback with a single argument indicating whether or not
|
||||
# the file has been touched since the last call to
|
||||
# `queryRestartFile`.
|
||||
queryRestartFile: (callback) ->
|
||||
fs.stat join(@root, "tmp/restart.txt"), (err, stats) =>
|
||||
if err
|
||||
@mtime = null
|
||||
callback false
|
||||
else
|
||||
lastMtime = @mtime
|
||||
@mtime = stats.mtime.getTime()
|
||||
callback lastMtime isnt @mtime
|
||||
|
||||
# Check to see if `tmp/always_restart.txt` is present in the
|
||||
# application root, and set the pool's `runOnce` option
|
||||
# accordingly. Invoke `callback` when the existence check has
|
||||
# finished. (Multiple calls to this method are aggregated.)
|
||||
setPoolRunOnceFlag: (callback) ->
|
||||
unless @statCallbacks.length
|
||||
exists join(@root, "tmp/always_restart.txt"), (alwaysRestart) =>
|
||||
@pool.runOnce = alwaysRestart
|
||||
statCallback() for statCallback in @statCallbacks
|
||||
@statCallbacks = []
|
||||
|
||||
@statCallbacks.push callback
|
||||
|
||||
# Collect environment variables from `.powrc` and `.powenv`, in that
|
||||
# order, if present. The idea is that `.powrc` files can be checked
|
||||
# into a source code repository for global configuration, leaving
|
||||
# `.powenv` free for any necessary local overrides.
|
||||
loadScriptEnvironment: (env, callback) ->
|
||||
async.reduce [".powrc", ".envrc", ".powenv"], env, (env, filename, callback) =>
|
||||
exists script = join(@root, filename), (scriptExists) ->
|
||||
if scriptExists
|
||||
sourceScriptEnv script, env, callback
|
||||
else
|
||||
callback null, env
|
||||
, callback
|
||||
|
||||
# If `.rvmrc` and `$HOME/.rvm/scripts/rvm` are present, load rvm,
|
||||
# source `.rvmrc`, and invoke `callback` with the resulting
|
||||
# environment variables. If `.rvmrc` is present but rvm is not
|
||||
# installed, invoke `callback` without sourcing `.rvmrc`.
|
||||
# Before loading rvm, Pow invokes a helper script that shows a
|
||||
# deprecation notice if it has not yet been displayed.
|
||||
loadRvmEnvironment: (env, callback) ->
|
||||
exists script = join(@root, ".rvmrc"), (rvmrcExists) =>
|
||||
if rvmrcExists
|
||||
exists rvm = @configuration.rvmPath, (rvmExists) =>
|
||||
if rvmExists
|
||||
libexecPath = resolve "#{__dirname}/../libexec"
|
||||
before = """
|
||||
'#{libexecPath}/pow_rvm_deprecation_notice' '#{[@firstHost]}'
|
||||
source '#{rvm}' > /dev/null
|
||||
""".trim()
|
||||
sourceScriptEnv script, env, {before}, callback
|
||||
else
|
||||
callback null, env
|
||||
else
|
||||
callback null, env
|
||||
|
||||
# Stat `tmp/restart.txt` to cache its mtime, then load the
|
||||
# application's full environment from `.powrc`, `.powenv`, and
|
||||
# `.rvmrc`.
|
||||
loadEnvironment: (callback) ->
|
||||
@queryRestartFile =>
|
||||
@loadScriptEnvironment @configuration.env, (err, env) =>
|
||||
if err then callback err
|
||||
else @loadRvmEnvironment env, (err, env) =>
|
||||
if err then callback err
|
||||
else callback null, env
|
||||
|
||||
# Begin the initialization process if the application is in the
|
||||
# uninitialized state. (If the application is terminating, queue a
|
||||
# call to `initialize` after all workers have exited.)
|
||||
initialize: ->
|
||||
if @state
|
||||
if @state is "terminating"
|
||||
@quit => @initialize()
|
||||
return
|
||||
|
||||
@state = "initializing"
|
||||
|
||||
# Load the application's environment. If an error is raised or
|
||||
# either of the environment scripts exits with a non-zero status,
|
||||
# reset the application's state and log the error.
|
||||
@loadEnvironment (err, env) =>
|
||||
if err
|
||||
@state = null
|
||||
@logger.error err.message
|
||||
@logger.error "stdout: #{err.stdout}"
|
||||
@logger.error "stderr: #{err.stderr}"
|
||||
|
||||
# Set the application's state to ready. Then create the Nack
|
||||
# pool instance using the `workers` and `timeout` options from
|
||||
# the application's environment or the global configuration.
|
||||
else
|
||||
@state = "ready"
|
||||
|
||||
@pool = nack.createPool join(@root, "config.ru"),
|
||||
env: env
|
||||
size: env?.POW_WORKERS ? @configuration.workers
|
||||
idle: (env?.POW_TIMEOUT ? @configuration.timeout) * 1000
|
||||
|
||||
# Log the workers' stderr and stdout, and log each worker's
|
||||
# PID as it spawns and exits.
|
||||
bufferLines @pool.stdout, (line) => @logger.info line
|
||||
bufferLines @pool.stderr, (line) => @logger.warning line
|
||||
|
||||
@pool.on "worker:spawn", (process) =>
|
||||
@logger.debug "nack worker #{process.child.pid} spawned"
|
||||
|
||||
@pool.on "worker:exit", (process) =>
|
||||
@logger.debug "nack worker exited"
|
||||
|
||||
# Invoke and remove all queued callbacks, passing along the
|
||||
# error, if any.
|
||||
readyCallback err for readyCallback in @readyCallbacks
|
||||
@readyCallbacks = []
|
||||
|
||||
# Begin the termination process. (If the application is initializing,
|
||||
# wait until it is ready before shutting down.)
|
||||
terminate: ->
|
||||
if @state is "initializing"
|
||||
@ready => @terminate()
|
||||
|
||||
else if @state is "ready"
|
||||
@state = "terminating"
|
||||
|
||||
# Instruct all workers to exit. After the processes have
|
||||
# terminated, reset the application's state, then invoke and
|
||||
# remove all queued callbacks.
|
||||
@pool.quit =>
|
||||
@state = null
|
||||
@mtime = null
|
||||
@pool = null
|
||||
|
||||
quitCallback() for quitCallback in @quitCallbacks
|
||||
@quitCallbacks = []
|
||||
|
||||
# Handle an incoming HTTP request. Wait until the application is in
|
||||
# the ready state, restart the workers if necessary, then pass the
|
||||
# request along to the Nack pool. If the Nack worker raises an
|
||||
# exception handling the request, reset the application.
|
||||
handle: (req, res, next, callback) ->
|
||||
resume = pause req
|
||||
@ready (err) =>
|
||||
return next err if err
|
||||
@setPoolRunOnceFlag =>
|
||||
@restartIfNecessary =>
|
||||
req.proxyMetaVariables =
|
||||
SERVER_PORT: @configuration.dstPort.toString()
|
||||
try
|
||||
@pool.proxy req, res, (err) =>
|
||||
@quit() if err
|
||||
next err
|
||||
finally
|
||||
resume()
|
||||
callback?()
|
||||
|
||||
# Terminate the application, re-initialize it, and invoke the given
|
||||
# callback when the application's state becomes ready.
|
||||
restart: (callback) ->
|
||||
@quit =>
|
||||
@ready callback
|
||||
|
||||
# Restart the application if `tmp/restart.txt` has been touched
|
||||
# since the last call to this function.
|
||||
restartIfNecessary: (callback) ->
|
||||
@queryRestartFile (mtimeChanged) =>
|
||||
if mtimeChanged
|
||||
@restart callback
|
||||
else
|
||||
callback()
|
||||
|
||||
# Append RVM autoload boilerplate to the application's `.powrc`
|
||||
# file. This is called by the RVM deprecation notice mini-app.
|
||||
writeRvmBoilerplate: ->
|
||||
powrc = join @root, ".powrc"
|
||||
boilerplate = @constructor.rvmBoilerplate
|
||||
|
||||
fs.readFile powrc, "utf8", (err, contents) ->
|
||||
contents ?= ""
|
||||
if contents.indexOf(boilerplate) is -1
|
||||
fs.writeFile powrc, "#{boilerplate}\n#{contents}"
|
||||
|
||||
@rvmBoilerplate: """
|
||||
if [ -f "$rvm_path/scripts/rvm" ] && [ -f ".rvmrc" ]; then
|
||||
source "$rvm_path/scripts/rvm"
|
||||
source ".rvmrc"
|
||||
fi
|
||||
"""
|
||||
Reference in New Issue
Block a user