mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-02-25 00:25:03 +08:00
Summary: - We now make verbose log files continuously as you use the app - We ship the logs to LogStash via S3 when an exception occurs - We log the DatabaseStore, ActionBridge and Analytics packages - We are now on the latest version of Electron 0.26.0 - We are now on Chrome 42 and io.js 1.4.3 - We should be setup to use ASAR soon. Update atom.sh to reflect that we're now electron oniguruma was unnecessary correctly find log files that haven't been shipped yet Fix a small issue with nodeIsVisible after upgrade to Chrome 42 Delete old logs, better logging from database store, don't ship empty logs Test Plan: Run existing tests Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D1531
155 lines
5.1 KiB
CoffeeScript
155 lines
5.1 KiB
CoffeeScript
_ = require 'underscore'
|
|
{fork} = require 'child_process'
|
|
{Emitter} = require 'emissary'
|
|
Grim = require 'grim'
|
|
|
|
# Extended: Run a node script in a separate process.
|
|
#
|
|
# Used by the fuzzy-finder and [find in project](https://github.com/atom/atom/blob/master/src/scan-handler.coffee).
|
|
#
|
|
# For a real-world example, see the [scan-handler](https://github.com/atom/atom/blob/master/src/scan-handler.coffee)
|
|
# and the [instantiation of the task](https://github.com/atom/atom/blob/4a20f13162f65afc816b512ad7201e528c3443d7/src/project.coffee#L245).
|
|
#
|
|
# ## Examples
|
|
#
|
|
# In your package code:
|
|
#
|
|
# ```coffee
|
|
# {Task} = require 'atom'
|
|
#
|
|
# task = Task.once '/path/to/task-file.coffee', parameter1, parameter2, ->
|
|
# console.log 'task has finished'
|
|
#
|
|
# task.on 'some-event-from-the-task', (data) =>
|
|
# console.log data.someString # prints 'yep this is it'
|
|
# ```
|
|
#
|
|
# In `'/path/to/task-file.coffee'`:
|
|
#
|
|
# ```coffee
|
|
# module.exports = (parameter1, parameter2) ->
|
|
# # Indicates that this task will be async.
|
|
# # Call the `callback` to finish the task
|
|
# callback = @async()
|
|
#
|
|
# emit('some-event-from-the-task', {someString: 'yep this is it'})
|
|
#
|
|
# callback()
|
|
# ```
|
|
module.exports =
|
|
class Task
|
|
Emitter.includeInto(this)
|
|
|
|
# Public: A helper method to easily launch and run a task once.
|
|
#
|
|
# * `taskPath` The {String} path to the CoffeeScript/JavaScript file which
|
|
# exports a single {Function} to execute.
|
|
# * `args` The arguments to pass to the exported function.
|
|
#
|
|
# Returns the created {Task}.
|
|
@once: (taskPath, args...) ->
|
|
task = new Task(taskPath)
|
|
task.once 'task:completed', -> task.terminate()
|
|
task.start(args...)
|
|
task
|
|
|
|
# Called upon task completion.
|
|
#
|
|
# It receives the same arguments that were passed to the task.
|
|
#
|
|
# If subclassed, this is intended to be overridden. However if {::start}
|
|
# receives a completion callback, this is overridden.
|
|
callback: null
|
|
|
|
# Public: Creates a task. You should probably use {.once}
|
|
#
|
|
# * `taskPath` The {String} path to the CoffeeScript/JavaScript file that
|
|
# exports a single {Function} to execute.
|
|
constructor: (taskPath) ->
|
|
coffeeCacheRequire = "require('#{require.resolve('./coffee-cache')}').register();"
|
|
coffeeScriptRequire = "require('#{require.resolve('coffee-script')}').register();"
|
|
taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');"
|
|
bootstrap = """
|
|
#{coffeeScriptRequire}
|
|
#{coffeeCacheRequire}
|
|
#{taskBootstrapRequire}
|
|
"""
|
|
bootstrap = bootstrap.replace(/\\/g, "\\\\")
|
|
|
|
taskPath = require.resolve(taskPath)
|
|
taskPath = taskPath.replace(/\\/g, "\\\\")
|
|
|
|
env = _.extend({}, process.env, {taskPath, userAgent: process.env.userAgent})
|
|
@childProcess = fork '--eval', [bootstrap], {env, silent: true}
|
|
|
|
@on "task:log", -> console.log(arguments...)
|
|
@on "task:warn", -> console.warn(arguments...)
|
|
@on "task:error", -> console.error(arguments...)
|
|
@on "task:deprecations", (deprecations) ->
|
|
Grim.addSerializedDeprecation(deprecation) for deprecation in deprecations
|
|
return
|
|
@on "task:completed", (args...) => @callback?(args...)
|
|
|
|
@handleEvents()
|
|
|
|
# Routes messages from the child to the appropriate event.
|
|
handleEvents: ->
|
|
@childProcess.removeAllListeners()
|
|
@childProcess.on 'message', ({event, args}) =>
|
|
@emit(event, args...) if @childProcess?
|
|
# Catch the errors that happened before task-bootstrap.
|
|
@childProcess.stdout.on 'data', (data) ->
|
|
console.log data.toString()
|
|
@childProcess.stderr.on 'data', (data) ->
|
|
console.error data.toString()
|
|
|
|
# Public: Starts the task.
|
|
#
|
|
# Throws an error if this task has already been terminated or if sending a
|
|
# message to the child process fails.
|
|
#
|
|
# * `args` The arguments to pass to the function exported by this task's script.
|
|
# * `callback` (optional) A {Function} to call when the task completes.
|
|
start: (args..., callback) ->
|
|
throw new Error('Cannot start terminated process') unless @childProcess?
|
|
|
|
@handleEvents()
|
|
if _.isFunction(callback)
|
|
@callback = callback
|
|
else
|
|
args.push(callback)
|
|
@send({event: 'start', args})
|
|
undefined
|
|
|
|
# Public: Send message to the task.
|
|
#
|
|
# Throws an error if this task has already been terminated or if sending a
|
|
# message to the child process fails.
|
|
#
|
|
# * `message` The message to send to the task.
|
|
send: (message) ->
|
|
if @childProcess?
|
|
@childProcess.send(message)
|
|
else
|
|
throw new Error('Cannot send message to terminated process')
|
|
undefined
|
|
|
|
# Public: Call a function when an event is emitted by the child process
|
|
#
|
|
# * `eventName` The {String} name of the event to handle.
|
|
# * `callback` The {Function} to call when the event is emitted.
|
|
#
|
|
# Returns a {Disposable} that can be used to stop listening for the event.
|
|
on: (eventName, callback) -> Emitter::on.call(this, eventName, callback)
|
|
|
|
# Public: Forcefully stop the running task.
|
|
#
|
|
# No more events are emitted once this method is called.
|
|
terminate: ->
|
|
return unless @childProcess?
|
|
|
|
@childProcess.removeAllListeners()
|
|
@childProcess.kill()
|
|
@childProcess = null
|
|
|
|
undefined
|