'use strict';
var Promise = require('bluebird');
/**
* An enumeration of {@link Worker} states
* @memberof Worker
* @enum {number}
* @constant
*/
var State = {
/** Worker is inactive */
INACTIVE: 0,
/** Worker is being activated */
ACTIVATING: 1,
/** Worker is active */
ACTIVE: 2,
/** Worker is being destroyed */
DESTROYING: 3,
/** Worker has been destroyed */
DESTROYED: 4
};
/**
* Enumeration of {@link Worker} creation causes
* @memberof Worker
* @enum {number}
* @constant
*/
var CreateCause = {
/** Worker was created for the first time. */
NEW: 0,
/** Worker was created as a result of recovery process. */
RECOVERY: 1
};
/**
* Enumeration of {@link Worker} destroy causes
* @memberof Worker
* @enum {number}
* @constant
*/
var DestroyCause = {
/** Worker is destroyed by itself. */
SELF: 0,
/** Worker is destroyed by the system. (server shutdown, etc) */
SYSTEM: 1
};
/**
* Default {@link Worker} load
* @memberof Worker
* @enum {number}
* @constant
*/
var DEFAULT_LOAD = 1;
/**
* Worker class constructor.
* Application must subclass this to implement abstract members.
* Do not instantiate directly from application. Worker instances are created by {@link Broker}.
* The subclass must pass all the arguments to this base Worker class. (See example)
* @example
* var util = require('util');
* var Worker = require('dworker').Worker;
*
* function MyWorker() {
* Worker.apply(this, arguments);
* // Your code here
* }
*
* util.inherits(MyWorker, Worker);
*
* // Override abstract method
* MyWorker.prototype.onCreate = function (info) {
* // Your implementation
* };
* // Override abstract method
* MyWorker.prototype.onDestroy = function (info) {
* // Your implementation
* };
* // Override abstract method
* MyWorker.prototype.onAsk = function (method, data) {
* // Your implementation
* };
* // Override abstract method
* MyWorker.prototype.onTell = function (method, data) {
* // Your implementation
* };
*
* @constructor
* @interface
* @property {string} id Worker ID (read-only)
* @property {number} state Current worker state (read-only)
* @property {object} attributes Attributes given by creator of this worker. (read-only)
* @property {number} load Current load imposed by this worker. (read/write)
*/
function Worker(id, broker, attributes) {
this.__priv = {
id: id,
br: broker,
attributes: attributes || {},
state: State.INACTIVE, // modified by broker
curLoad: 0
};
// Define getter 'id'
this.__defineGetter__("id", function () {
return this.__priv.id;
});
// Define getter 'state'
this.__defineGetter__("state", function () {
return this.__priv.state;
});
// Define getter 'attributes'
this.__defineGetter__("attributes", function () {
return this.__priv.attributes;
});
// Define getter 'load'
this.__defineGetter__("load", function () {
return this.__priv.curLoad;
});
// Define setter 'load'
this.__defineSetter__("load", function (newLoad) {
if (this.state !== State.DESTROYED && newLoad >= 0) {
newLoad = Math.floor(newLoad);
var prevLoad = this.__priv.curLoad;
this.__priv.curLoad = newLoad;
this.__priv.br._updateLoad(this, newLoad - prevLoad);
}
});
}
/**
* Destroy this worker.
* Call of this method will trigger {@link onDestroy} callback with
* info.cause being {@link DestroyCause#SELF}.
* @param {object} [option] Options.
* @param {boolean} [option.noRecover] No recover option. This is set to true by default.
* When this option is set to false, and this worker is created with recoverable option
* set to true, this worker will be recreated right away somewhere in the same cluster.
* This option is provide only for development purpose. (e.g. to test restoration of
* context data on DB, etc.) Do not set this option to false in production for
* obvious reasons.
* @returns {void}
*/
Worker.prototype.destroy = function (option) {
this.load = 0;
this.__priv.br._destroyWorker(this, option);
};
/**
* Callback function for Worker#onAsk.
* @callback Worker~onAskCallback
* @param {Error} err Error object.
* @param {object} data Request data.
*/
/**
* Called when ask operation is received.
* Application must override this method to handle ask operation.
* @abstract
* @param {string} method Method name.
* @param {object} data Data sent by requesting entity.
* @param {Worker~onAskCallback} [cb] Callback from this method.
* @returns {Promise} Returns a Promise if `cb` is not supplied. See {@link Worker~onAskCallback}
*/
Worker.prototype.onAsk = function (method, data, cb) {
/*jshint unused:false */
return Promise.reject(new Error("Not implemented")).nodeify(cb);
};
/**
* Called when tell operation is received.
* Application must override this method to handle tell operation.
* @abstract
* @param {string} method Method name.
* @param {object} data Data sent by requesting entity.
*/
Worker.prototype.onTell = function (method, data) {
/*jshint unused:false */
};
/**
* Callback function for Worker#onCreate.
* @callback Worker~onCreateCallback
* @param {Error} err Error object.
* @param {object} data Request data.
*/
/**
* Called when this worker is created.
* @abstract
* @param {object} info Information of this callback.
* @param {number} info.cause Cause of the creation.
* @param {Worker~onCreateCallback} [cb] Callback from this method.
* @see Worker.CreateCause
* @returns {Promise} Returns a Promise if `cb` is not supplied. See {@link Worker~onCreateCallback}
* Error return, or rejection of promise, will be ignored by
* the caller.
*/
Worker.prototype.onCreate = function (info, cb) {
void(info);
this.load = DEFAULT_LOAD;
return Promise.resolve().nodeify(cb);
};
/**
* Callback function for Worker#onDestroy.
* @callback Worker~onDestroyCallback
* @param {Error} err Error object.
* @param {object} data Request data.
*/
/**
* Called when this worker is about to be destroyed.
* @param {object} info Information of this callback.
* @param {number} info.cause Cause of the destruction.
* @param {Worker~onDestroyCallback} [cb] Callback from this method.
* @see Worker.DestroyCause
* @returns {Promise} Returns a Promise if `cb` is not supplied. See {@link Worker~onDestroyCallback}
* Error return, or rejection of promise, will be ignored by
* the caller.
*/
Worker.prototype.onDestroy = function (info, cb) {
void(cb); // base implementation doest not use callback.
return Promise.resolve().nodeify(cb);
};
/**
* Optional custom Agent class property. Set to undefined by default (uses base Agent class).
* @memberof Worker
* @type {Agent}
* @name agent
*/
Worker.State = State;
Worker.CreateCause = CreateCause;
Worker.DestroyCause = DestroyCause;
Worker.DEFAULT_LOAD = DEFAULT_LOAD;
exports.Worker = Worker;