
var EE = require('events').EventEmitter;
var util = require('util');
var cp = require('child_process');
var back = require('back');

module.exports = Fork;

util.inherits(Fork, EE);

//
// Here we accept the fullPath of the process we are going to
// fork and the options object to pass to it. The only conventions we will use
// here is an error message property if something within the child_process goes
// wrong but it is not completely fatal
//
function Fork(options) {
  if (!(this instanceof Fork)) return new Fork(options);
  EE.call(this);
  options = options || {};

  this.path = typeof options != 'string'
    ? options.path
    : options;

  if (!this.path) {
    throw new Error('Must provide a path to process to fork');
  }
  this.retries = options.retries || 0;
  this.backoff = options.backoff || false;
  this.killTimer = options.killTimer || 100;
  //
  // Use a boolean and hack the setTimeout delay in order to make
  // the backoff optional
  //
  this.attempt = {};
  this.attempt.retries = this.retries;
  this.attempt.minDelay = options.backoff ? false : 1;
  this.attempt.maxDelay = options.backoff ? false : 1;
  //
  // Remark: This is the path to the process we are forking
  //
  this.returned = false;

  this._retry = this.retries != 0;
  return this;
}

Fork.prototype.start =
Fork.prototype.fork = function (message, callback) {

  this.message = this.message || message;
  if (callback && typeof callback == 'function') {
    this._callback = callback;
  }
  //
  // Fork Process
  //
  this.process = cp.fork(this.path);
  //
  // Setup the listeners
  //
  this.process.on('error', this.onError.bind(this));
  this.process.on('exit', this.onExit.bind(this));
  this.process.on('message', this.onMessage.bind(this));

  this.process.send(this.message);
  return this;
};

Fork.prototype.onMessage = function (message) {
  this.returned = true;
  if (message.error) {
    return this.onError(message.error);
  }
  return !this._callback
    ? this.emit('response', message)
    : this._callback(null, message);
};

//
// We always cleanup and retry if configured to do so
//
Fork.prototype.onError = function (err) {
  this.cleanup();
  return this._retry
    ? this.retry(err)
    : this.emitError(err);
};

Fork.prototype.retry = function (err) {
  return back(function (fail) {
    if (fail) {
      return this.emitError(err);
    }
    this.emit('retry', this.attempt);
    this.fork();
  }.bind(this), this.attempt);
}

Fork.prototype.emitError = function (err) {
  return !this._callback
    ? this.emit('error', err)
    : this._callback(err)
}

//
// We should be durable here and ensure the process gets killed
//
Fork.prototype.cleanup = function () {
  //
  // Change reference
  //
  var proc = this.process;
  this.process = null;
  this.prevProcesses[];
  proc.disconnect();
  //
  // Hmm should we just kill the process instead?
  //
  setTimeout(function () {

  })
};

Fork.prototype.

@@ -2045,16 +2045,202 @@
 e);%0A%7D;%0A%0A
+Fork.prototype.onExit = function (code, signal) %7B%0A  if (!this.returned) %7B%0A    code = code %7C%7C signal;%0A    return this.onError(new Error('Child process exited with code ' + code));%0A  %7D%0A%7D;%0A
 //%0A// We
@@ -2401,28 +2401,32 @@
 %0A    : this.
-emit
+dispatch
 Error(err);%0A
@@ -2535,20 +2535,24 @@
 rn this.
-emit
+dispatch
 Error(er
@@ -2665,20 +2665,24 @@
 ototype.
-emit
+dispatch
 Error = 
@@ -2783,24 +2783,30 @@
 rr)%0A%7D%0A%0A//%0A//
+ TODO:
  We should b
@@ -2903,86 +2903,33 @@
 %7B%0A  
-//%0A  // Change reference%0A  //%0A  var proc = this.process;%0A  this.process = null
+this.process.disconnect()
 ;%0A  
@@ -2937,44 +2937,24 @@
 his.
-p
 re
-vProcesses%5B%5D;%0A  proc.disconnect()
+turned = false
 ;%0A  
@@ -3015,57 +3015,9 @@
  //%0A
-  setTimeout(function () %7B%0A%0A  %7D)%0A%7D;%0A%0AFork.prototype.
+%0A%7D;%0A
 %0A

remove broken/incomplete code and add onExit handler