/*
* sers.ServiceStation.js
* Date : 2022-05-07
* Version: 2.1.18-preview9
* author : Lith
* email : serset@yeah.net
*/
; sers = { version: '2.1.18-preview9' };
/*
* vit.js 扩展
* author : Lith
* email : serset@yeah.net
*/
; (function (vit) {
// vit工具函数
; (function () {
vit.stringToBytes = function (str) {
if (!str) return [];
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
return bytes;
};
vit.bytesToString = function (bytes) {
if (!bytes) return null;
if (typeof bytes === 'string') {
return bytes;
}
var str = '',
_arr = bytes;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
};
vit.bytesToObject = function (bytes) {
return eval('(' + vit.bytesToString(bytes) + ')');
};
vit.objectSerializeToString = function (obj) {
if (obj == null || typeof (obj) == 'undefined') {
return null;
}
var str = obj;
if (typeof (str) != 'string') {
str = JSON.stringify(str);
}
return str;
};
vit.objectSerializeToBytes = function (obj) {
var str = vit.objectSerializeToString(obj);
return vit.stringToBytes(str);
};
//合并连个数组
vit.arrayConcat = function (a, b, count) {
//a.push.apply(a, b);
if (!count) count = b.length;
for (var t = 0; t < count; t++) {
a.push(b[t]);
}
return a;
};
vit.bytesToArrayBuffer = function (bytes) {
return new Uint8Array(bytes).buffer;
};
vit.bytesToDataView = function (bytes) {
return new DataView(vit.bytesToArrayBuffer(bytes));
};
vit.arrayBufferToBytes = function (arrayBuffer) {
return Array.from(new Uint8Array(arrayBuffer));
};
vit.dataViewToBytes = function (dataView) {
return vit.arrayBufferToBytes(dataView.buffer);
};
vit.bytesGetInt32 = function (bytes, index) {
return new DataView(new Uint8Array(bytes).buffer).getInt32(index || 0, true);
};
vit.int32ToBytes = function (int32) {
var buffer = new ArrayBuffer(4);
var view = new DataView(buffer);
view.setInt32(0, int32, true);
return vit.dataViewToBytes(view);
};
vit.bytesInsertInt32 = function (bytes, index, int32) {
var bytesInt32 = vit.int32ToBytes(int32);
bytes.splice(index, 0, bytesInt32[0], bytesInt32[1], bytesInt32[2], bytesInt32[3]);
return bytes;
};
// return '112233445566778899aabbccddee'
vit.guid = function guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4());
};
})();
//vit.logger
(function (logger) {
/*** 对Date的扩展,将 Date 转化为指定格式的String * 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q)
* 可以用 1-2 个占位符 * 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
* eg:
* (newDate()).pattern("yyyy-MM-dd hh:mm:ss.S")==> 2006-07-02 08:09:04.423
* (new Date()).pattern("yyyy-MM-dd E HH:mm:ss") ==> 2009-03-10 二 20:09:04
* (new Date()).pattern("yyyy-MM-dd EE hh:mm:ss") ==> 2009-03-10 周二 08:09:04
* (new Date()).pattern("yyyy-MM-dd EEE hh:mm:ss") ==> 2009-03-10 星期二 08:09:04
* (new Date()).pattern("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
*/
Date.prototype.pattern = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
var week = {
"0": "/u65e5",
"1": "/u4e00",
"2": "/u4e8c",
"3": "/u4e09",
"4": "/u56db",
"5": "/u4e94",
"6": "/u516d"
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
if (/(E+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[this.getDay() + ""]);
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
};
//type: info/error
//e: pass error when type is error
//function(message,type,e){ }
logger.onmessage;
logger.error = function (e, message) {
var msgBody = new Date().pattern("[mm:ss.S]") + '[error]' + (message || e.message || '');
//console.log(e);
//console.log(msgBody);
try {
if (logger.onmessage) logger.onmessage(msgBody, 'error', e);
} catch (e) {
}
};
logger.info = function (message) {
var msgBody = new Date().pattern("[mm:ss.S]") + '[info]' + message;
//console.log(msgBody);
try {
if (logger.onmessage) logger.onmessage(msgBody, 'info');
} catch (e) {
}
};
})(vit.logger = {});
})('undefined' === typeof (vit) ? vit = {} : vit);
/*
* sers.CL.js 扩展
* PipeFrame CL.DeliveryClient RequestAdaptor CL.OrganizeClient
* author : Lith
* email : serset@yeah.net
*/
; (function (CL) {
var logger = vit.logger;
function PipeFrame() {
this.write = function (arrayBuffer) {
queueBuff.push(new Uint8Array(arrayBuffer));
buffLen += arrayBuffer.byteLength;
};
//DataView list
var queueBuff = [];
var buffLen = 0;
var QueueBuff_dataLenOfRemoved = 0;
//return bytes
function read(lenToPop) {
if (buffLen < lenToPop) {
return;
}
buffLen -= lenToPop;
var dataToPop = [];
var copyedIndex = 0;
while (copyedIndex < lenToPop) {
var leftCount = lenToPop - copyedIndex;
var cur = queueBuff[0];
if (QueueBuff_dataLenOfRemoved != 0) {
cur = cur.subarray(QueueBuff_dataLenOfRemoved);
}
if (cur.length <= leftCount) {
//dataToPop 数据长
vit.arrayConcat(dataToPop, cur);
copyedIndex += cur.length;
QueueBuff_dataLenOfRemoved = 0;
queueBuff.shift();
}
else {
//queueBuff 数据长
vit.arrayConcat(dataToPop, cur, leftCount);
copyedIndex += leftCount;
QueueBuff_dataLenOfRemoved += leftCount;
}
}
return dataToPop;
};
var fileLen = -1;
//return bytes
this.readSersFile = function () {
if (fileLen < 0) {
var fileLen_bytes = read(4);
if (!fileLen_bytes) {
return null;
}
fileLen = vit.bytesGetInt32(fileLen_bytes, 0);
}
if (buffLen < fileLen) return null;
var data = read(fileLen);
fileLen = -1;
return data;
};
};
CL.DeliveryClient = function () {
var self = this;
self.host = "ws://127.0.0.1:4503";
//function (bytes) { }
self.event_onGetFrame;
// function () { }
self.event_onDisconnected;
self.sendFrame = function (bytes) {
if (!webSocket) throw new Error('连接尚未建立,无法发送数据,请先建立连接');
vit.bytesInsertInt32(bytes, 0, bytes.length);
var dataView = vit.bytesToDataView(bytes);
webSocket.send(dataView);
};
var pipe = new PipeFrame();
var webSocket = null;
//callback: function(success){ }
self.connect = function (callback) {
if (webSocket) throw new Error('连接尚未断开,不可再次连接');
webSocket = new WebSocket(self.host);
webSocket.binaryType = "arraybuffer";
webSocket.onerror = function (event) {
self.close();
};
webSocket.onclose = function () {
self.close();
};
//成功被调用 或者超时被调用
var isCalled = false;
var onCall = function (success) {
if (isCalled) return;
isCalled = true;
callback(success);
};
setTimeout(onCall, 10000);
webSocket.onopen = function (event) {
onCall(true);
};
webSocket.onmessage = function (event) {
var arrayBuffer = event.data;
pipe.write(arrayBuffer);
//bytes
var frame;
while (frame = pipe.readSersFile()) {
try {
self.event_onGetFrame(frame);
} catch (e) {
logger.error(e);
}
}
};
};
self.close = function () {
if (!webSocket) throw new Error('尚未建立连接,无需断开');
//(x.1) close socket
try {
webSocket.close();
} catch (e) {
logger.error(e);
}
webSocket = null;
logger.info('[sers.CL]DeliveryClient.event_onDisconnected');
//(x.2) event_onDisconnected
if (self.event_onDisconnected) {
try {
self.event_onDisconnected();
} catch (e) {
logger.error(e);
}
}
};
};
function RequestAdaptor() {
var EFrameType = { request: 1, reply: 2, message: 3 };
var ERequestType = { app: 0, heartBeat: 1 };
var organizeVersion = "Sers.Mq.Socket.v1";
var self = this;
// requestKey -> requestCallback
var organizeToDelivery_RequestMap = {};
var reqKeyIndex = 100;
//事件,向外部delivery发送字节流时被调用
//function (bytes) { }
self.event_onSendFrame;
//事件,delivery向Organize发送请求时被调用
//function (apiRequestMessage_bytes, callback) { }
// callback: function(apiReplyMessage_bytes){ }
self.event_onGetRequest;
//事件,delivery向Organize发送请求时被调用
//function (bytes) { }
self.event_onGetMessage;
//请求超时时间(单位ms,默认300000)
self.requestTimeoutMs = 300000;
//外部调用,当外部从delivery读取到数据时调用
self.deliveryToOrganize_onGetMessageFrame = function (bytes) {
//deliveryToOrganize_ProcessFrame
var msgType = bytes[0];
var msgData = bytes.slice(2);
switch (msgType) {
case EFrameType.reply:
var t = unpackReqRepFrame(msgData);
var reqKey = t.reqKey;
var replyData = t.oriData;
var reqCallback = organizeToDelivery_RequestMap[reqKey];
if (reqCallback) {
delete organizeToDelivery_RequestMap[reqKey];
reqCallback(replyData);
}
break;
case EFrameType.request:
var t = unpackReqRepFrame(msgData);
var reqKey_bytes = t.reqKey_bytes;
var requestData = t.oriData;
var requestType = bytes[1];
deliveryToOrganize_onGetRequest(requestType, reqKey_bytes, requestData);
break;
case EFrameType.message:
self.event_onGetMessage(msgData);
break;
}
};
function deliveryToOrganize_onGetRequest(requestType, reqKey_bytes, requestData) {
switch (requestType) {
case ERequestType.app:
self.event_onGetRequest(requestData, function (apiReplyMessage_bytes) {
deliveryToOrganize_sendReply(reqKey_bytes, apiReplyMessage_bytes);
});
return;
case ERequestType.heartBeat:
var version = vit.bytesToString(requestData);
if (version == organizeVersion) {
// send reply
deliveryToOrganize_sendReply(reqKey_bytes, requestData);
}
else {
// send reply
deliveryToOrganize_sendReply(reqKey_bytes, [0]);
}
return;
}
}
function deliveryToOrganize_sendReply(reqKey_bytes, replyData) {
var repFrame = packageReqRepFrame(reqKey_bytes, replyData);
delivery_sendFrame(EFrameType.reply, 0, repFrame);
}
//callback: ({success,replyData})=>{ }
self.sendRequest = function (requestType, requestData, callback) {
var reqKey = reqKeyIndex++;
//成功被调用 或者超时被调用
var isCalled = false;
var onRequestFinish = function (success, replyData) {
if (isCalled) return;
isCalled = true;
//if (!success)
delete organizeToDelivery_RequestMap[reqKey];
if (callback)
callback({ success: success, replyData: replyData });
};
setTimeout(onRequestFinish, self.requestTimeoutMs);
organizeToDelivery_RequestMap[reqKey] = function (replyData) { onRequestFinish(true, replyData); };
var reqKey_bytes = vit.int32ToBytes(reqKey);
reqKey_bytes.push(0, 0, 0, 0);
var reqRepFrame = packageReqRepFrame(reqKey_bytes, requestData);
delivery_sendFrame(EFrameType.request, requestType || ERequestType.app, reqRepFrame);
};
self.sendMessage = function (message_bytes) {
delivery_sendFrame(EFrameType.message, 0, message_bytes);
};
function delivery_sendFrame(msgType, requestType, bytes) {
bytes.splice(0, 0, msgType, requestType);
self.event_onSendFrame(bytes);
}
//reqKey_bytes 8字节
//返回 reqRepFrame[bytes]
function packageReqRepFrame(reqKey_bytes, oriData) {
return vit.arrayConcat(reqKey_bytes, oriData);
}
// 返回对象 {reqKey:reqKey,reqKey_bytes:reqKey_bytes, oriData:oriData}
function unpackReqRepFrame(reqRepFrame) {
var reqKey = vit.bytesGetInt32(reqRepFrame, 0);
return { reqKey: reqKey, reqKey_bytes: reqRepFrame.slice(0, 8), oriData: reqRepFrame.slice(8) };
}
}
//websocketHost demo: "ws://127.0.0.1:4503"
CL.OrganizeClient = function (websocketHost) {
var self = this;
var delivery = new CL.DeliveryClient();
//连接秘钥,用以验证连接安全性。服务端和客户端必须一致
self.secretKey = "SersCL";
//设置websocket host 地址 demo: "ws://127.0.0.1:4503"
self.setHost = function (websocketHost) {
delivery.host = websocketHost;
};
self.setHost(websocketHost);
var requestAdaptor = new RequestAdaptor();
//初始化requestAdaptor 和 delivery
(function () {
delivery.event_onGetFrame = function (bytes) {
requestAdaptor.deliveryToOrganize_onGetMessageFrame(bytes);
};
requestAdaptor.event_onGetRequest = function (apiRequestMessage_bytes, callback) {
self.event_onGetRequest(apiRequestMessage_bytes, callback);
};
requestAdaptor.event_onGetMessage = function (bytes) {
self.event_onGetMessage(bytes);
};
requestAdaptor.event_onSendFrame = function (bytes) {
delivery.sendFrame(bytes);
};
delivery.event_onDisconnected = function () {
if (self.event_onDisconnected)
self.event_onDisconnected.apply(self, arguments);
};
})();
//function (event) { }
self.event_onDisconnected = null;
//function (apiRequestMessage_bytes,callback) { }
// callback function(apiReplyMessage_bytes){}
self.event_onGetRequest = null;
//function (bytes) { }
self.event_onGetMessage = null;
//callback: ({success,replyData})=>{ }
self.sendRequest = function (requestData, callback) {
requestAdaptor.sendRequest(null, requestData, callback);
};
self.sendMessage = function (message_bytes) {
requestAdaptor.sendMessage(message_bytes);
};
//callback: function (success) { }
self.connect = function (callback) {
delivery.connect(function (success) {
//(x.1)连接不成功
if (!success)
callback(false);
//(x.2)进行权限校验
//setTimeout(function () {
self.sendRequest(vit.stringToBytes(self.secretKey), function (args) {
let success = args.success, replyData = args.replyData;
//(x.x.1)请求不成功
if (!success) {
callback(false);
return;
}
//(x.x.2)验证不成功
if (vit.bytesToString(replyData) != 'true') {
callback(false);
return;
}
//(x.x.3)验证成功
callback(true);
});
//}, 5000);
});
};
self.stop = function () {
delivery.close();
};
}
})(sers.CL || (sers.CL = {}));
/*
* sers.ServiceStation.js 扩展
* sers.ApiMessage sers.ApiClient sers.MessageClient sers.LocalApiService sers.ServiceStation
* author : Lith
* email : serset@yeah.net
*/
; (function (sers) {
var logger = vit.logger;
//ApiMessage
function ApiMessage() {
var self = this;
//bytes
var rpcContextData_OriData;
//bytes
var value_OriData;
//return object
self.getRpcData = function () {
var strRpc = vit.bytesToString(rpcContextData_OriData);
if (!strRpc) return {};
return eval('(' + strRpc + ')');
};
//return bytes
self.getValueBytes = function () {
return value_OriData;
};
//return string
self.getValueString = function () {
var strValue = vit.bytesToString(value_OriData);
return strValue;
};
//return object
self.getValueObject = function () {
return eval('(' + self.getValueString() + ')');
};
self.initAsApiRequestMessage = function (route, arg, httpMethod) {
var rpcData = {
"route": route,
"caller": {
"rid": vit.guid(),
"callStack": [], // parentRequestGuid array
"source": "Internal"
},
"http": {
"method": httpMethod || "GET"
}
};
rpcContextData_OriData = vit.objectSerializeToBytes(rpcData);
value_OriData = vit.objectSerializeToBytes(arg);
};
self.package = function () {
return ApiMessage.package(rpcContextData_OriData, value_OriData);
};
self.unpackage = function (oriData) {
var files = ApiMessage.unpackage(oriData);
rpcContextData_OriData = files[0];
value_OriData = files[1];
};
};
//arg files(bytes[])
//return bytes
ApiMessage.package = function () {
var files = arguments;
var oriData = [];
for (var t = 0; t < files.length; t++) {
var file = files[t];
vit.arrayConcat(oriData, vit.int32ToBytes(file.length));
vit.arrayConcat(oriData, file);
}
return oriData;
};
//arg oriData(bytes)
//return bytes[] file[]
ApiMessage.unpackage = function (oriData) {
var files = [];
var curIndex = 0;
while (curIndex < oriData.length) {
var fileLength = vit.bytesGetInt32(oriData, curIndex);
var fileContent = oriData.slice(curIndex + 4, curIndex + 4 + fileLength);
curIndex += 4 + fileLength;
files.push(fileContent);
}
return files;
};
sers.ApiMessage = ApiMessage;
//ApiClient
sers.ApiClient = function (organizeClient) {
//(string route, object arg, string httpMethod, function callback)
// callback: function({success,replyData_bytes,replyRpcData_object})
this.callApiAsync = function (route, arg, httpMethod, callback) {
var apiRequestMessage = new ApiMessage();
apiRequestMessage.initAsApiRequestMessage(route, arg, httpMethod);
organizeClient.sendRequest(apiRequestMessage.package(), function (args) {
let success = args.success, replyData = args.replyData;
if (!callback) return;
if (!success) {
callback({ success: false });
} else {
var apiMessage = new ApiMessage();
apiMessage.unpackage(replyData);
var value = apiMessage.getValueBytes();
var replyRpcData = apiMessage.getRpcData();
callback({ success: true, replyData_bytes: value, replyRpcData_object: replyRpcData });
}
});
};
};
//MessageClient
sers.MessageClient = function (organizeClient) {
let EFrameType = {
///
/// publish, msgTitle, msgData
///
publish : 0,
///
/// subscribe, msgTitle
///
subscribe : 1,
///
/// unSubscribe, msgTitle
///
unSubscribe : 2,
///
/// message, msgTitle, msgData
///
message : 3
};
function sendFrame(frame) {
organizeClient.sendMessage(frame);
}
this.onGetMessage = (messageData) => {
let frame = ApiMessage.unpackage(messageData);
let msgType = frame[0][0];
switch (msgType) {
case EFrameType.message:
let msgTitle = vit.bytesToString(frame[1]);
let msgData = frame[2];
this.message_Consumer(msgTitle, msgData);
break;
}
};
// (msgTitle,msgData)=>void
this.message_Consumer;
this.message_Publish = function (msgTitle, msgData) {
//EFrameType.publish, msgTitle, msgData
let frame = ApiMessage.package(
[EFrameType.publish],
vit.stringToBytes(msgTitle),
msgData);
sendFrame(frame);
};
this.message_Subscribe = function (msgTitle) {
//EFrameType.subscribe, msgTitle
let frame = ApiMessage.package(
[EFrameType.subscribe],
vit.stringToBytes(msgTitle)
);
sendFrame(frame);
};
this.message_UnSubscribe = function (msgTitle) {
//EFrameType.unSubscribe, msgTitle
let frame = ApiMessage.package(
[EFrameType.unSubscribe],
vit.stringToBytes(msgTitle)
);
sendFrame(frame);
};
};
//SubscriberManage
sers.SubscriberManage = function (messageClient) {
this.createSubscribe = (msgTitle, onGetMessage) => {
return new sers.MessageSubscriber(this, msgTitle, onGetMessage);
};
//消息订阅者 msgTitle -> Subscriber[]
let subscriberMap = {};
// subscriber:MessageSubscriber
this.message_Subscribe = function (subscriber) {
let subscriberList = subscriberMap[subscriber.msgTitle];
if (!subscriberList) {
subscriberList=subscriberMap[subscriber.msgTitle] = [];
messageClient.message_Subscribe(subscriber.msgTitle);
}
subscriberList.push(subscriber);
};
this.message_UnSubscribe = function (subscriber) {
let subscriberList = subscriberMap[subscriber.msgTitle];
if (!subscriberList) {
return false;
}
subscriberList = subscriberList.filter(m => m != subscriber);
if (subscriberList.length == 0) {
delete subscriberMap[subscriber.msgTitle];
messageClient.message_UnSubscribe(subscriber.msgTitle);
}
};
this.message_Consumer = function (msgTitle, msgData) {
let subscriberList = subscriberMap[msgTitle];
if (!subscriberList || !subscriberList.length) return;
for (let subscriber of subscriberList) {
try {
if (!subscriber || !subscriber.onGetMessage) continue;
subscriber.onGetMessage(msgData);
} catch (ex) {
logger.error(ex);
}
}
};
messageClient.message_Consumer = this.message_Consumer;
};
//MessageSubscriber
sers.MessageSubscriber = function (subscriberManage,msgTitle, onGetMessage) {
this.msgTitle = msgTitle;
// bytes=>void
this.onGetMessage = onGetMessage;
this.subscribe = function () {
subscriberManage.message_Subscribe(this);
return this;
};
this.unSubscribe = function () {
subscriberManage.message_UnSubscribe(this);
return this;
};
};
//LocalApiService
sers.LocalApiService = function () {
var self = this;
// route_httpMethod -> ApiNode
// ApiNode: { apiDesc,onInvoke,onInvokeAsync } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ }
// onInvokeFinish :(replyData_bytes)=>{ }
var apiNodeMap = {};
//return [ ApiNode ];
//ApiNode {apiDesc:apiDesc }
self.getApiNodes = function () {
var apiNodes = [];
for (var key in apiNodeMap) {
apiNodes.push({ apiDesc: apiNodeMap[key].apiDesc });
}
return apiNodes;
};
//清空已加载的apiNode
self.clearApiNodes = function () {
apiNodeMap = {};
};
// ApiNode: { apiDesc,onInvoke,onInvokeAsync } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ }
// onInvokeFinish :(replyData_bytes)=>{ }
self.addApiNode = function (apiNode) {
var apiKey = apiNode.apiDesc.route + '_' + apiNode.apiDesc.extendConfig.httpMethod;
apiNodeMap[apiKey] = apiNode;
};
// apiInvoke {route: '/JsStation/api', httpMethod: 'GET', name: 'call api in js server', description: 'js作为服务站点', onInvoke,onInvokeAsync}
// onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ }
// onInvokeFinish :(replyData_bytes)=>{ }
self.addApiInvoke = function (apiInvoke) {
var apiDesc = {
route: apiInvoke.route,
name: apiInvoke.name,
description: apiInvoke.description,
extendConfig: {
httpMethod: apiInvoke.httpMethod
}
};
self.addApiNode({ apiDesc: apiDesc, onInvoke: apiInvoke.onInvoke, onInvokeAsync: apiInvoke.onInvokeAsync });
};
// apiInvoke {route: '/JsStation/api', httpMethod: 'GET', name: 'call api in js server', description: 'js作为服务站点', onInvoke,onInvokeAsync}
// onInvoke: (requestData_bytes,rpcData_object,replyRpcData_object)=>{ return replyData_bytes; } //onInvoke 和 onInvokeAsync 指定其一即可
// onInvokeAsync: (requestData_bytes,rpcData_object,replyRpcData_object,onInvokeFinish)=>{ }
// onInvokeFinish :(replyData_bytes)=>{ }
self.addApiInvokeArray = function (apiInvokeArray) {
for (var apiInvoke of apiInvokeArray) {
self.addApiInvoke(apiInvoke);
}
};
//(Error e,requestData_bytes,rpcData_object,replyRpcData_object)
//localApiService.onError = (e,requestData_bytes,rpcData_object,replyRpcData_object)=>{ return {success:false}; }
self.onError = function (e, requestData_bytes, rpcData_object, replyRpcData_object) {
logger.error(e);
var reply = {
success: false,
error: {
errorMessage: e.message,
errorDetail: { name: e.name, stack: e.stack }
}
};
return reply;
};
//invoke local api
//callback: (apiReplyMessage_bytes)=>{ }
self.invokeApiAsync = (apiRequestMessage_bytes, callback) => {
//(x.1) 解析请求数据
var apiMessage = new ApiMessage();
apiMessage.unpackage(apiRequestMessage_bytes);
var rpcData_object = apiMessage.getRpcData();
var requestData_bytes = apiMessage.getValueBytes();
//(x.2)解析路由获得 处理函数
var route = rpcData_object.route;
var httpMethod = rpcData_object.http.method;
var apiKey = route + '_' + httpMethod;
var apiNode = apiNodeMap[apiKey];
//(x.3)进行处理获得结果数据
var replyRpcData_object = {}, replyData_bytes;
var onInvokeFinish = (replyData_bytes) => {
//返回结果数据
var apiReplyMessage_bytes = ApiMessage.package(
vit.objectSerializeToBytes(replyRpcData_object),
replyData_bytes
);
callback(apiReplyMessage_bytes);
};
if (apiNode) {
try {
if (apiNode.onInvoke) {
replyData_bytes = apiNode.onInvoke(requestData_bytes, rpcData_object, replyRpcData_object);
} else if (apiNode.onInvokeAsync) {
apiNode.onInvokeAsync(requestData_bytes, rpcData_object, replyRpcData_object, onInvokeFinish);
return;
}
} catch (e) {
var reply = self.onError(e, requestData_bytes, rpcData_object, replyRpcData_object);
replyData_bytes = vit.objectSerializeToBytes(reply);
}
} else {
var reply = {
success: false,
error: {
errorCode: 404,
errorMessage: "Api Not Found",
errorDetail: { source: 'from JsStation' }
}
};
replyData_bytes = vit.objectSerializeToBytes(reply);
}
onInvokeFinish(replyData_bytes);
};
};
//ServiceStation
// localApiService org apiClient serviceStationInfo
sers.ServiceStation = function () {
var self = this;
//(x.1) localApiService
(function () {
self.localApiService = new sers.LocalApiService();
})();
//(x.2) OrganizeClient self.org
(function () {
self.org = new sers.CL.OrganizeClient("ws://127.0.0.1:4503");
//self.org.event_onDisconnected = function () {
// logger.info('[sers.CL]org.event_onDisconnected');
//};
self.org.event_onGetRequest = self.localApiService.invokeApiAsync;
})();
//(x.3) apiClient
(function () {
self.apiClient = new sers.ApiClient(self.org);
})();
//(x.4) subscriberManage
(function () {
let messageClient = new sers.MessageClient(self.org);
self.subscriberManage = new sers.SubscriberManage(messageClient);
self.org.event_onGetMessage = messageClient.onGetMessage;
})();
//(x.5)
self.stop = function () {
logger.info('[sers.ServiceStation] try stop...');
self.org.stop();
logger.info('[sers.ServiceStation] stoped.');
};
//(x.6)
self.serviceStationInfo = {
serviceStationName: 'JsStation', serviceStationKey: '', stationVersion: '', info: {}
};
//(x.7)
var deviceInfo = { deviceKey: ('' + Math.random()).substr(2) };
//(x.8)
//callback: function(success){}
self.start = function (callback) {
logger.info('[sers.CL] try connect...');
self.org.connect(function (success) {
if (!success) {
logger.info('[sers.CL] org cannot connect to server!');
if (callback) callback(false);
return;
}
//向服务中心注册localApiService
logger.info('[ServiceStation] regist serviceStation to ServiceCenter...');
var apiNodes = self.localApiService.getApiNodes();
var serviceStationData = {
serviceStationInfo: self.serviceStationInfo,
deviceInfo: deviceInfo,
apiNodes: apiNodes
};
//(string route, object arg, string httpMethod, function callback)
// callback: function({success,replyData_bytes,replyRpcData_object})
self.apiClient.callApiAsync("/_sys_/serviceStation/regist", serviceStationData, 'POST', function (args) {
let success = args.success, replyData_bytes = args.replyData_bytes, replyRpcData_object = args.replyRpcData_object;
if (!success) {
logger.info("[ServiceStation] regist - failed");
if (callback) callback(false);
return;
}
var apiRet = vit.bytesToObject(replyData_bytes);
if (!apiRet.success) {
logger.info("[ServiceStation] regist - failed. reply:" + vit.bytesToString(replyData_bytes));
if (callback) callback(false);
return;
}
logger.info("[ServiceStation] regist - succeed");
if (callback) callback(true);
});
});
};
}
})(sers);