occaecatidicta
Version:
160 lines (150 loc) • 5.93 kB
text/typescript
import { getLogger } from 'omelox-logger';
let logger = getLogger('omelox-rpc', 'failprocess');
import { constants } from '../util/constants';
import * as utils from '../util/utils';
export function failureProcess(this: any, code: string, tracer: any, serverId: string, msg: object, opts: {failMode: string}) {
let cb = tracer && tracer.cb;
let mode = opts.failMode;
let FAIL_MODE = constants.FAIL_MODE;
let method = failfast;
if (mode === FAIL_MODE.FAILOVER) {
method = failover;
} else if (mode === FAIL_MODE.FAILBACK) {
method = failback;
} else if (mode === FAIL_MODE.FAILFAST) {
}
// switch (mode) {
// case constants.FAIL_MODE.FAILOVER:
// method = failover;
// break;
// case constants.FAIL_MODE.FAILBACK:
// method = failback;
// break;
// case constants.FAIL_MODE.FAILFAST:
// method = failfast;
// break;
// case constants.FAIL_MODE.FAILSAFE:
// default:
// method = failfast;
// break;
// }
method.call(this, code, tracer, serverId, msg, opts, cb);
}
/**
* Failover rpc failure process. This will try other servers with option retries.
*
* @param code {Number} error code number.
* @param tracer {Object} current rpc tracer.
* @param serverId {String} rpc remote target server id.
* @param msg {Object} rpc message.
* @param opts {Object} rpc client options.
* @param cb {Function} user rpc callback.
*
* @api private
*/
let failover = function (this: any, code: number, tracer: {servers: object}, serverId: string, msg: {serverType: string}, opts: object, cb: Function) {
let servers;
let self = this;
let counter = 0;
let success = true;
let serverType = msg.serverType;
if (!tracer || !tracer.servers) {
servers = self.serversMap[serverType];
} else {
servers = tracer.servers;
}
let index = servers.indexOf(serverId);
if (index >= 0) {
servers.splice(index, 1);
}
tracer && (tracer.servers = servers);
if (!servers.length) {
logger.error('[omelox-rpc] rpc failed with all this type of servers, with serverType: %s', serverType);
cb(new Error('rpc failed with all this type of servers, with serverType: ' + serverType));
return;
}
self.dispatch.call(self, tracer, servers[0], msg, opts, cb);
};
/**
* Failsafe rpc failure process.
*
* @param code {Number} error code number.
* @param tracer {Object} current rpc tracer.
* @param serverId {String} rpc remote target server id.
* @param msg {Object} rpc message.
* @param opts {Object} rpc client options.
* @param cb {Function} user rpc callback.
*
* @api private
*/
let failsafe = function (this: any, code: number, tracer: {[key: string]: any}, serverId: string, msg: {serverType: string}, opts: {[key: string]: any}, cb: Function) {
let self = this;
let retryTimes = opts.retryTimes || constants.DEFAULT_PARAM.FAILSAFE_RETRIES;
let retryConnectTime = opts.retryConnectTime || constants.DEFAULT_PARAM.FAILSAFE_CONNECT_TIME;
if (!tracer.retryTimes) {
tracer.retryTimes = 1;
} else {
tracer.retryTimes += 1;
}
switch (code) {
case constants.RPC_ERROR.SERVER_NOT_STARTED:
case constants.RPC_ERROR.NO_TRAGET_SERVER:
cb(new Error('rpc client is not started or cannot find remote server.'));
break;
case constants.RPC_ERROR.FAIL_CONNECT_SERVER:
if (tracer.retryTimes <= retryTimes) {
setTimeout(function () {
self.connect(tracer, serverId, cb);
}, retryConnectTime * tracer.retryTimes);
} else {
cb(new Error('rpc client failed to connect to remote server: ' + serverId));
}
break;
case constants.RPC_ERROR.FAIL_FIND_MAILBOX:
case constants.RPC_ERROR.FAIL_SEND_MESSAGE:
if (tracer.retryTimes <= retryTimes) {
setTimeout(function () {
self.dispatch.call(self, tracer, serverId, msg, opts, cb);
}, retryConnectTime * tracer.retryTimes);
} else {
cb(new Error('rpc client failed to send message to remote server: ' + serverId));
}
break;
case constants.RPC_ERROR.FILTER_ERROR:
cb(new Error('rpc client filter encounters error.'));
break;
default:
cb(new Error('rpc client unknown error.'));
}
};
/**
* Failback rpc failure process. This will try the same server with sendInterval option and retries option.
*
* @param code {Number} error code number.
* @param tracer {Object} current rpc tracer.
* @param serverId {String} rpc remote target server id.
* @param msg {Object} rpc message.
* @param opts {Object} rpc client options.
* @param cb {Function} user rpc callback.
*
* @api private
*/
let failback = function (code: number, tracer: {[key: string]: any}, serverId: string, msg: {serverType: string}, opts: {[key: string]: any}, cb: Function) {
// todo record message in background and send the message at timing
};
/**
* Failfast rpc failure process. This will ignore error in rpc client.
*
* @param code {Number} error code number.
* @param tracer {Object} current rpc tracer.
* @param serverId {String} rpc remote target server id.
* @param msg {Object} rpc message.
* @param opts {Object} rpc client options.
* @param cb {Function} user rpc callback.
*
* @api private
*/
let failfast = function (code: number, tracer: {[key: string]: any}, serverId: string, msg: {serverType: string}, opts: {[key: string]: any}, cb: Function) {
logger.error('rpc failed with error, remote server: %s, msg: %j, error code: %s', serverId, msg, code);
cb && cb(new Error('rpc failed with error code: ' + code));
};