@bigtyphoon/melo 1.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +55 -0
- package/bin/commadtest.ts +10 -0
- package/bin/commands/add.ts +43 -0
- package/bin/commands/init.ts +292 -0
- package/bin/commands/kill.ts +21 -0
- package/bin/commands/list.ts +60 -0
- package/bin/commands/masterha.ts +40 -0
- package/bin/commands/restart.ts +48 -0
- package/bin/commands/start.ts +65 -0
- package/bin/commands/stop.ts +26 -0
- package/bin/melo.ts +30 -0
- package/bin/utils/constants.ts +27 -0
- package/bin/utils/utils.ts +130 -0
- package/dist/bin/commadtest.js +9 -0
- package/dist/bin/commands/add.js +40 -0
- package/dist/bin/commands/init.js +279 -0
- package/dist/bin/commands/kill.js +21 -0
- package/dist/bin/commands/list.js +65 -0
- package/dist/bin/commands/masterha.js +36 -0
- package/dist/bin/commands/restart.js +45 -0
- package/dist/bin/commands/start.js +58 -0
- package/dist/bin/commands/stop.js +20 -0
- package/dist/bin/melo.js +26 -0
- package/dist/bin/utils/constants.js +28 -0
- package/dist/bin/utils/utils.js +134 -0
- package/dist/lib/application.js +888 -0
- package/dist/lib/common/manager/appManager.js +112 -0
- package/dist/lib/common/manager/taskManager.js +39 -0
- package/dist/lib/common/remote/backend/msgRemote.js +63 -0
- package/dist/lib/common/remote/frontend/channelRemote.js +78 -0
- package/dist/lib/common/remote/frontend/sessionRemote.js +76 -0
- package/dist/lib/common/service/backendSessionService.js +337 -0
- package/dist/lib/common/service/channelService.js +514 -0
- package/dist/lib/common/service/connectionService.js +95 -0
- package/dist/lib/common/service/filterService.js +112 -0
- package/dist/lib/common/service/handlerService.js +187 -0
- package/dist/lib/common/service/sessionService.js +610 -0
- package/dist/lib/components/backendSession.js +14 -0
- package/dist/lib/components/channel.js +13 -0
- package/dist/lib/components/connection.js +12 -0
- package/dist/lib/components/connector.js +437 -0
- package/dist/lib/components/dictionary.js +93 -0
- package/dist/lib/components/master.js +39 -0
- package/dist/lib/components/monitor.js +25 -0
- package/dist/lib/components/protobuf.js +156 -0
- package/dist/lib/components/proxy.js +236 -0
- package/dist/lib/components/pushScheduler.js +62 -0
- package/dist/lib/components/remote.js +127 -0
- package/dist/lib/components/server.js +63 -0
- package/dist/lib/components/session.js +20 -0
- package/dist/lib/connectors/commands/handshake.js +119 -0
- package/dist/lib/connectors/commands/heartbeat.js +67 -0
- package/dist/lib/connectors/commands/kick.js +15 -0
- package/dist/lib/connectors/common/coder.js +90 -0
- package/dist/lib/connectors/common/handler.js +57 -0
- package/dist/lib/connectors/hybrid/IHybridSocket.js +3 -0
- package/dist/lib/connectors/hybrid/switcher.js +100 -0
- package/dist/lib/connectors/hybrid/tcpprocessor.js +40 -0
- package/dist/lib/connectors/hybrid/tcpsocket.js +171 -0
- package/dist/lib/connectors/hybrid/wsprocessor.js +49 -0
- package/dist/lib/connectors/hybridconnector.js +89 -0
- package/dist/lib/connectors/hybridsocket.js +139 -0
- package/dist/lib/connectors/mqtt/generate.js +113 -0
- package/dist/lib/connectors/mqtt/mqttadaptor.js +81 -0
- package/dist/lib/connectors/mqtt/protocol.js +48 -0
- package/dist/lib/connectors/mqttconnector.js +107 -0
- package/dist/lib/connectors/mqttsocket.js +59 -0
- package/dist/lib/connectors/sioconnector.js +135 -0
- package/dist/lib/connectors/siosocket.js +69 -0
- package/dist/lib/connectors/udpconnector.js +76 -0
- package/dist/lib/connectors/udpsocket.js +93 -0
- package/dist/lib/filters/handler/serial.js +44 -0
- package/dist/lib/filters/handler/time.js +32 -0
- package/dist/lib/filters/handler/timeout.js +45 -0
- package/dist/lib/filters/handler/toobusy.js +36 -0
- package/dist/lib/filters/rpc/rpcLog.js +43 -0
- package/dist/lib/filters/rpc/toobusy.js +41 -0
- package/dist/lib/index.js +81 -0
- package/dist/lib/interfaces/IComponent.js +3 -0
- package/dist/lib/interfaces/IConnector.js +3 -0
- package/dist/lib/interfaces/IHandlerFilter.js +3 -0
- package/dist/lib/interfaces/ILifeCycle.js +3 -0
- package/dist/lib/interfaces/IPlugin.js +3 -0
- package/dist/lib/interfaces/IPushScheduler.js +3 -0
- package/dist/lib/interfaces/ISocket.js +3 -0
- package/dist/lib/interfaces/IStore.js +3 -0
- package/dist/lib/interfaces/define.js +3 -0
- package/dist/lib/master/master.js +129 -0
- package/dist/lib/master/starter.js +236 -0
- package/dist/lib/master/watchdog.js +120 -0
- package/dist/lib/melo.js +125 -0
- package/dist/lib/modules/console.js +436 -0
- package/dist/lib/modules/masterwatcher.js +98 -0
- package/dist/lib/modules/monitorwatcher.js +124 -0
- package/dist/lib/modules/onlineUser.js +69 -0
- package/dist/lib/modules/restartNotifyModule.js +107 -0
- package/dist/lib/modules/watchServer.js +737 -0
- package/dist/lib/monitor/monitor.js +80 -0
- package/dist/lib/pushSchedulers/buffer.js +96 -0
- package/dist/lib/pushSchedulers/direct.js +58 -0
- package/dist/lib/pushSchedulers/multi.js +80 -0
- package/dist/lib/server/server.js +500 -0
- package/dist/lib/util/appUtil.js +306 -0
- package/dist/lib/util/constants.js +117 -0
- package/dist/lib/util/countDownLatch.js +51 -0
- package/dist/lib/util/events.js +20 -0
- package/dist/lib/util/handlerHelper.js +8 -0
- package/dist/lib/util/log.js +14 -0
- package/dist/lib/util/moduleUtil.js +101 -0
- package/dist/lib/util/pathUtil.js +134 -0
- package/dist/lib/util/remoterHelper.js +8 -0
- package/dist/lib/util/utils.js +358 -0
- package/dist/test/application.js +522 -0
- package/dist/test/config/log4js.json +28 -0
- package/dist/test/config/master.json +9 -0
- package/dist/test/config/servers.json +6 -0
- package/dist/test/filters/handler/serial.js +41 -0
- package/dist/test/filters/handler/time.js +41 -0
- package/dist/test/filters/handler/timeout.js +41 -0
- package/dist/test/filters/handler/toobusy.js +57 -0
- package/dist/test/filters/rpc/rpcLog.js +22 -0
- package/dist/test/filters/rpc/toobusy.js +39 -0
- package/dist/test/manager/mockChannelManager.js +77 -0
- package/dist/test/manager/taskManager.js +68 -0
- package/dist/test/mock-base/app/servers/other-file +0 -0
- package/dist/test/mock-plugin/components/mockPlugin.js +10 -0
- package/dist/test/mock-plugin/events/mockEvent.js +12 -0
- package/dist/test/modules/console.js +242 -0
- package/dist/test/pomelo.js +19 -0
- package/dist/test/remote/channelRemote.js +159 -0
- package/dist/test/service/channel.js +134 -0
- package/dist/test/service/channelService.js +216 -0
- package/dist/test/service/connectionService.js +114 -0
- package/dist/test/service/filterService.js +144 -0
- package/dist/test/service/handlerService.js +65 -0
- package/dist/test/service/sessionService.js +387 -0
- package/dist/test/util/countDownLatch.js +70 -0
- package/dist/test/util/pathUtil.js +108 -0
- package/dist/test/util/utils.js +140 -0
- package/lib/application.ts +1240 -0
- package/lib/common/manager/appManager.ts +118 -0
- package/lib/common/manager/taskManager.ts +50 -0
- package/lib/common/remote/backend/msgRemote.ts +134 -0
- package/lib/common/remote/frontend/channelRemote.ts +91 -0
- package/lib/common/remote/frontend/sessionRemote.ts +91 -0
- package/lib/common/service/backendSessionService.ts +388 -0
- package/lib/common/service/channelService.ts +609 -0
- package/lib/common/service/connectionService.ts +112 -0
- package/lib/common/service/filterService.ts +118 -0
- package/lib/common/service/handlerService.ts +224 -0
- package/lib/common/service/sessionService.ts +731 -0
- package/lib/components/backendSession.ts +14 -0
- package/lib/components/channel.ts +11 -0
- package/lib/components/connection.ts +13 -0
- package/lib/components/connector.ts +533 -0
- package/lib/components/dictionary.ts +121 -0
- package/lib/components/master.ts +41 -0
- package/lib/components/monitor.ts +30 -0
- package/lib/components/protobuf.ts +208 -0
- package/lib/components/proxy.ts +282 -0
- package/lib/components/pushScheduler.ts +70 -0
- package/lib/components/remote.ts +166 -0
- package/lib/components/server.ts +71 -0
- package/lib/components/session.ts +22 -0
- package/lib/connectors/commands/handshake.ts +155 -0
- package/lib/connectors/commands/heartbeat.ts +83 -0
- package/lib/connectors/commands/kick.ts +11 -0
- package/lib/connectors/common/coder.ts +93 -0
- package/lib/connectors/common/handler.ts +62 -0
- package/lib/connectors/hybrid/IHybridSocket.ts +9 -0
- package/lib/connectors/hybrid/switcher.ts +142 -0
- package/lib/connectors/hybrid/tcpprocessor.ts +43 -0
- package/lib/connectors/hybrid/tcpsocket.ts +223 -0
- package/lib/connectors/hybrid/wsprocessor.ts +57 -0
- package/lib/connectors/hybridconnector.ts +134 -0
- package/lib/connectors/hybridsocket.ts +168 -0
- package/lib/connectors/mqtt/generate.ts +103 -0
- package/lib/connectors/mqtt/mqttadaptor.ts +114 -0
- package/lib/connectors/mqtt/protocol.ts +49 -0
- package/lib/connectors/mqttconnector.ts +134 -0
- package/lib/connectors/mqttsocket.ts +79 -0
- package/lib/connectors/sioconnector.ts +161 -0
- package/lib/connectors/siosocket.ts +85 -0
- package/lib/connectors/udpconnector.ts +113 -0
- package/lib/connectors/udpsocket.ts +110 -0
- package/lib/filters/handler/serial.ts +46 -0
- package/lib/filters/handler/time.ts +35 -0
- package/lib/filters/handler/timeout.ts +50 -0
- package/lib/filters/handler/toobusy.ts +37 -0
- package/lib/filters/rpc/rpcLog.ts +42 -0
- package/lib/filters/rpc/toobusy.ts +41 -0
- package/lib/index.ts +74 -0
- package/lib/interfaces/IComponent.ts +47 -0
- package/lib/interfaces/IConnector.ts +20 -0
- package/lib/interfaces/IHandlerFilter.ts +15 -0
- package/lib/interfaces/ILifeCycle.ts +16 -0
- package/lib/interfaces/IPlugin.ts +65 -0
- package/lib/interfaces/IPushScheduler.ts +52 -0
- package/lib/interfaces/ISocket.ts +26 -0
- package/lib/interfaces/IStore.ts +10 -0
- package/lib/interfaces/define.ts +15 -0
- package/lib/master/master.ts +148 -0
- package/lib/master/starter.ts +234 -0
- package/lib/master/watchdog.ts +135 -0
- package/lib/melo.ts +152 -0
- package/lib/modules/console.ts +465 -0
- package/lib/modules/masterwatcher.ts +120 -0
- package/lib/modules/monitorwatcher.ts +151 -0
- package/lib/modules/onlineUser.ts +78 -0
- package/lib/modules/restartNotifyModule.ts +128 -0
- package/lib/modules/watchServer.ts +766 -0
- package/lib/monitor/monitor.ts +99 -0
- package/lib/pushSchedulers/buffer.ts +117 -0
- package/lib/pushSchedulers/direct.ts +65 -0
- package/lib/pushSchedulers/multi.ts +94 -0
- package/lib/server/server.ts +554 -0
- package/lib/util/appUtil.ts +313 -0
- package/lib/util/constants.ts +154 -0
- package/lib/util/countDownLatch.ts +72 -0
- package/lib/util/events.ts +15 -0
- package/lib/util/handlerHelper.ts +5 -0
- package/lib/util/log.ts +11 -0
- package/lib/util/moduleUtil.ts +110 -0
- package/lib/util/pathUtil.ts +132 -0
- package/lib/util/remoterHelper.ts +68 -0
- package/lib/util/utils.ts +365 -0
- package/package.json +93 -0
- package/template/game-server/.vscode/launch.json +27 -0
- package/template/game-server/app/servers/connector/handler/entryHandler.ts +50 -0
- package/template/game-server/app/servers/connector/remote/authRemoter.ts +36 -0
- package/template/game-server/app.ts +30 -0
- package/template/game-server/app.ts.mqtt +32 -0
- package/template/game-server/app.ts.sio +36 -0
- package/template/game-server/app.ts.sio.wss +34 -0
- package/template/game-server/app.ts.udp +31 -0
- package/template/game-server/app.ts.wss +40 -0
- package/template/game-server/config/adminServer.json +5 -0
- package/template/game-server/config/adminUser.json +22 -0
- package/template/game-server/config/clientProtos.json +1 -0
- package/template/game-server/config/dictionary.json +1 -0
- package/template/game-server/config/log4js.json +150 -0
- package/template/game-server/config/master.json +8 -0
- package/template/game-server/config/serverProtos.json +1 -0
- package/template/game-server/config/servers.json +12 -0
- package/template/game-server/copy.js +5 -0
- package/template/game-server/package.json +28 -0
- package/template/game-server/preload.ts +40 -0
- package/template/game-server/tsconfig.json +36 -0
- package/template/npm-install.bat +4 -0
- package/template/npm-install.sh +5 -0
- package/template/readme.md +31 -0
- package/template/shared/server.crt +15 -0
- package/template/shared/server.key +15 -0
- package/template/web-server/app.js +25 -0
- package/template/web-server/app.js.https +36 -0
- package/template/web-server/bin/component.bat +1 -0
- package/template/web-server/bin/component.sh +1 -0
- package/template/web-server/package.json +10 -0
- package/template/web-server/public/css/base.css +76 -0
- package/template/web-server/public/image/logo.png +0 -0
- package/template/web-server/public/image/sp.png +0 -0
- package/template/web-server/public/index.html +57 -0
- package/template/web-server/public/index.html.sio +58 -0
- package/template/web-server/public/js/lib/build/build.js +1730 -0
- package/template/web-server/public/js/lib/build/build.js.wss +1721 -0
- package/template/web-server/public/js/lib/component.json +6 -0
- package/template/web-server/public/js/lib/local/boot/component.json +11 -0
- package/template/web-server/public/js/lib/local/boot/index.js +11 -0
- package/template/web-server/public/js/lib/meloclient.js +456 -0
- package/template/web-server/public/js/lib/meloclient.js.wss +456 -0
- package/template/web-server/public/js/lib/socket.io.js +3 -0
- package/test/application.ts +607 -0
- package/test/filters/handler/serial.ts +47 -0
- package/test/filters/handler/time.ts +47 -0
- package/test/filters/handler/timeout.ts +46 -0
- package/test/filters/handler/toobusy.ts +59 -0
- package/test/filters/rpc/rpcLog.ts +20 -0
- package/test/filters/rpc/toobusy.ts +40 -0
- package/test/manager/mockChannelManager.ts +92 -0
- package/test/manager/taskManager.ts +78 -0
- package/test/mock-base/app/servers/other-file +0 -0
- package/test/mock-plugin/components/mockPlugin.ts +8 -0
- package/test/mock-plugin/events/mockEvent.ts +12 -0
- package/test/modules/console.ts +264 -0
- package/test/pomelo.ts +18 -0
- package/test/remote/channelRemote.ts +176 -0
- package/test/service/channel.ts +161 -0
- package/test/service/channelService.ts +243 -0
- package/test/service/connectionService.ts +142 -0
- package/test/service/filterService.ts +165 -0
- package/test/service/handlerService.ts +77 -0
- package/test/service/sessionService.ts +464 -0
- package/test/util/countDownLatch.ts +81 -0
- package/test/util/pathUtil.ts +122 -0
- package/test/util/utils.ts +165 -0
|
@@ -0,0 +1,888 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Melo -- proto
|
|
4
|
+
* Copyright(c) 2012 xiechengchao <xiecc@163.com>
|
|
5
|
+
* MIT Licensed
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.Application = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Module dependencies.
|
|
11
|
+
*/
|
|
12
|
+
const utils = require("./util/utils");
|
|
13
|
+
const melo_logger_1 = require("@bigtyphoon/melo-logger");
|
|
14
|
+
const events_1 = require("events");
|
|
15
|
+
const events_2 = require("./util/events");
|
|
16
|
+
const appUtil = require("./util/appUtil");
|
|
17
|
+
const Constants = require("./util/constants");
|
|
18
|
+
const appManager = require("./common/manager/appManager");
|
|
19
|
+
const fs = require("fs");
|
|
20
|
+
const path = require("path");
|
|
21
|
+
let logger = (0, melo_logger_1.getLogger)('melo', path.basename(__filename));
|
|
22
|
+
/**
|
|
23
|
+
* Application states
|
|
24
|
+
*/
|
|
25
|
+
let STATE_INITED = 1; // app has inited
|
|
26
|
+
let STATE_BEFORE_START = 2; // app before start
|
|
27
|
+
let STATE_START = 3; // app start
|
|
28
|
+
let STATE_STARTED = 4; // app has started
|
|
29
|
+
let STATE_STOPED = 5; // app has stoped
|
|
30
|
+
class Application {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.loaded = []; // loaded component list
|
|
33
|
+
this.components = {}; // name -> component map
|
|
34
|
+
this.settings = {}; // collection keep set/get
|
|
35
|
+
this.event = new events_1.EventEmitter(); // event object to sub/pub events
|
|
36
|
+
// global server infos
|
|
37
|
+
this.master = null; // master server info
|
|
38
|
+
this.servers = {}; // current global server info maps, id -> info
|
|
39
|
+
this.serverTypeMaps = {}; // current global type maps, type -> [info]
|
|
40
|
+
this.serverTypes = []; // current global server type list
|
|
41
|
+
this.usedPlugins = []; // current server custom lifecycle callbacks
|
|
42
|
+
this.clusterSeq = {}; // cluster id seqence
|
|
43
|
+
this.astart = utils.promisify(this.start);
|
|
44
|
+
this.aconfigure = utils.promisify(this.configure);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Initialize the server.
|
|
48
|
+
*
|
|
49
|
+
* - setup default configuration
|
|
50
|
+
*/
|
|
51
|
+
init(opts) {
|
|
52
|
+
opts = opts || {};
|
|
53
|
+
let base = opts.base || path.dirname(require.main.filename);
|
|
54
|
+
this.set(Constants.RESERVED.BASE, base);
|
|
55
|
+
this.base = base;
|
|
56
|
+
appUtil.defaultConfiguration(this);
|
|
57
|
+
this.state = STATE_INITED;
|
|
58
|
+
logger.info('application inited: %j', this.getServerId());
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get application base path
|
|
62
|
+
*
|
|
63
|
+
* // cwd: /home/game/
|
|
64
|
+
* melo start
|
|
65
|
+
* // app.getBase() -> /home/game
|
|
66
|
+
*
|
|
67
|
+
* @return {String} application base path
|
|
68
|
+
*
|
|
69
|
+
* @memberOf Application
|
|
70
|
+
*/
|
|
71
|
+
getBase() {
|
|
72
|
+
return this.get(Constants.RESERVED.BASE);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Override require method in application
|
|
76
|
+
*
|
|
77
|
+
* @param {String} relative path of file
|
|
78
|
+
*
|
|
79
|
+
* @memberOf Application
|
|
80
|
+
*/
|
|
81
|
+
require(ph) {
|
|
82
|
+
return require(path.join(this.getBase(), ph));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Configure logger with {$base}/config/log4js.json
|
|
86
|
+
*
|
|
87
|
+
* @param {Object} logger melo-logger instance without configuration
|
|
88
|
+
*
|
|
89
|
+
* @memberOf Application
|
|
90
|
+
*/
|
|
91
|
+
configureLogger(logger) {
|
|
92
|
+
if (process.env.POMELO_LOGGER !== 'off') {
|
|
93
|
+
let serverId = this.getServerId();
|
|
94
|
+
let base = this.getBase();
|
|
95
|
+
let env = this.get(Constants.RESERVED.ENV);
|
|
96
|
+
let originPath = path.join(base, Constants.FILEPATH.LOG);
|
|
97
|
+
let presentPath = path.join(base, Constants.FILEPATH.CONFIG_DIR, env, path.basename(Constants.FILEPATH.LOG));
|
|
98
|
+
if (this._checkCanRequire(originPath)) {
|
|
99
|
+
logger.configure(originPath, { serverId: serverId, base: base });
|
|
100
|
+
}
|
|
101
|
+
else if (this._checkCanRequire(presentPath)) {
|
|
102
|
+
logger.configure(presentPath, { serverId: serverId, base: base });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.error('logger file path configuration is error.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* add a filter to before and after filter
|
|
111
|
+
*
|
|
112
|
+
* @param {Object} filter provide before and after filter method.
|
|
113
|
+
* A filter should have two methods: before and after.
|
|
114
|
+
* @memberOf Application
|
|
115
|
+
*/
|
|
116
|
+
filter(filter) {
|
|
117
|
+
this.before(filter);
|
|
118
|
+
this.after(filter);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Add before filter.
|
|
122
|
+
*
|
|
123
|
+
* @param {Object|Function} bf before fileter, bf(msg, session, next)
|
|
124
|
+
* @memberOf Application
|
|
125
|
+
*/
|
|
126
|
+
before(bf) {
|
|
127
|
+
addFilter(this, Constants.KEYWORDS.BEFORE_FILTER, bf);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Add after filter.
|
|
131
|
+
*
|
|
132
|
+
* @param {Object|Function} af after filter, `af(err, msg, session, resp, next)`
|
|
133
|
+
* @memberOf Application
|
|
134
|
+
*/
|
|
135
|
+
after(af) {
|
|
136
|
+
addFilter(this, Constants.KEYWORDS.AFTER_FILTER, af);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* add a global filter to before and after global filter
|
|
140
|
+
*
|
|
141
|
+
* @param {Object} filter provide before and after filter method.
|
|
142
|
+
* A filter should have two methods: before and after.
|
|
143
|
+
* @memberOf Application
|
|
144
|
+
*/
|
|
145
|
+
globalFilter(filter) {
|
|
146
|
+
this.globalBefore(filter);
|
|
147
|
+
this.globalAfter(filter);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Add global before filter.
|
|
151
|
+
*
|
|
152
|
+
* @param {Object|Function} bf before fileter, bf(msg, session, next)
|
|
153
|
+
* @memberOf Application
|
|
154
|
+
*/
|
|
155
|
+
globalBefore(bf) {
|
|
156
|
+
addFilter(this, Constants.KEYWORDS.GLOBAL_BEFORE_FILTER, bf);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Add global after filter.
|
|
160
|
+
*
|
|
161
|
+
* @param {Object|Function} af after filter, `af(err, msg, session, resp, next)`
|
|
162
|
+
* @memberOf Application
|
|
163
|
+
*/
|
|
164
|
+
globalAfter(af) {
|
|
165
|
+
addFilter(this, Constants.KEYWORDS.GLOBAL_AFTER_FILTER, af);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Add rpc before filter.
|
|
169
|
+
*
|
|
170
|
+
* @param {Object|Function} bf before fileter, bf(serverId, msg, opts, next)
|
|
171
|
+
* @memberOf Application
|
|
172
|
+
*/
|
|
173
|
+
rpcBefore(bf) {
|
|
174
|
+
addFilter(this, Constants.KEYWORDS.RPC_BEFORE_FILTER, bf);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Add rpc after filter.
|
|
178
|
+
*
|
|
179
|
+
* @param {Object|Function} af after filter, `af(serverId, msg, opts, next)`
|
|
180
|
+
* @memberOf Application
|
|
181
|
+
*/
|
|
182
|
+
rpcAfter(af) {
|
|
183
|
+
addFilter(this, Constants.KEYWORDS.RPC_AFTER_FILTER, af);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* add a rpc filter to before and after rpc filter
|
|
187
|
+
*
|
|
188
|
+
* @param {Object} filter provide before and after filter method.
|
|
189
|
+
* A filter should have two methods: before and after.
|
|
190
|
+
* @memberOf Application
|
|
191
|
+
*/
|
|
192
|
+
rpcFilter(filter) {
|
|
193
|
+
this.rpcBefore(filter);
|
|
194
|
+
this.rpcAfter(filter);
|
|
195
|
+
}
|
|
196
|
+
load(name, component, opts) {
|
|
197
|
+
if (typeof name !== 'string') {
|
|
198
|
+
opts = component;
|
|
199
|
+
component = name;
|
|
200
|
+
name = null;
|
|
201
|
+
}
|
|
202
|
+
if (typeof component === 'function') {
|
|
203
|
+
component = new component(this, opts);
|
|
204
|
+
}
|
|
205
|
+
if (!name && typeof component.name === 'string') {
|
|
206
|
+
name = component.name;
|
|
207
|
+
}
|
|
208
|
+
if (name && this.components[name]) {
|
|
209
|
+
// ignore duplicat component
|
|
210
|
+
logger.warn('ignore duplicate component: %j', name);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
this.loaded.push(component);
|
|
214
|
+
if (name) {
|
|
215
|
+
// components with a name would get by name throught app.components later.
|
|
216
|
+
this.components[name] = component;
|
|
217
|
+
}
|
|
218
|
+
return component;
|
|
219
|
+
}
|
|
220
|
+
_checkCanRequire(path) {
|
|
221
|
+
try {
|
|
222
|
+
path = require.resolve(path);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
return path;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Load Configure json file to settings.(support different enviroment directory & compatible for old path)
|
|
231
|
+
*
|
|
232
|
+
* @param {String} key environment key
|
|
233
|
+
* @param {String} val environment value
|
|
234
|
+
* @param {Boolean} reload whether reload after change default false
|
|
235
|
+
* @return {Server|Mixed} for chaining, or the setting value
|
|
236
|
+
* @memberOf Application
|
|
237
|
+
*/
|
|
238
|
+
loadConfigBaseApp(key, val, reload = false) {
|
|
239
|
+
let self = this;
|
|
240
|
+
let env = this.get(Constants.RESERVED.ENV);
|
|
241
|
+
let originPath = path.join(this.getBase(), val);
|
|
242
|
+
let presentPath = path.join(this.getBase(), Constants.FILEPATH.CONFIG_DIR, env, path.basename(val));
|
|
243
|
+
let realPath;
|
|
244
|
+
let tmp;
|
|
245
|
+
if (self._checkCanRequire(originPath)) {
|
|
246
|
+
realPath = require.resolve(originPath);
|
|
247
|
+
let file = require(originPath);
|
|
248
|
+
if (file[env]) {
|
|
249
|
+
file = file[env];
|
|
250
|
+
}
|
|
251
|
+
this.set(key, file);
|
|
252
|
+
}
|
|
253
|
+
else if (self._checkCanRequire(presentPath)) {
|
|
254
|
+
realPath = require.resolve(presentPath);
|
|
255
|
+
let pfile = require(presentPath);
|
|
256
|
+
this.set(key, pfile);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
logger.error('invalid configuration with file path: %s', key);
|
|
260
|
+
}
|
|
261
|
+
if (!!realPath && !!reload) {
|
|
262
|
+
const watcher = fs.watch(realPath, function (event, filename) {
|
|
263
|
+
if (event === 'change') {
|
|
264
|
+
self.clearRequireCache(require.resolve(realPath));
|
|
265
|
+
watcher.close();
|
|
266
|
+
self.loadConfigBaseApp(key, val, reload);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
clearRequireCache(path) {
|
|
272
|
+
const moduleObj = require.cache[path];
|
|
273
|
+
if (!moduleObj) {
|
|
274
|
+
logger.warn('can not find module of truepath', path);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (moduleObj.parent) {
|
|
278
|
+
// console.log('has parent ',moduleObj.parent);
|
|
279
|
+
moduleObj.parent.children.splice(moduleObj.parent.children.indexOf(moduleObj), 1);
|
|
280
|
+
}
|
|
281
|
+
delete require.cache[path];
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Load Configure json file to settings.
|
|
285
|
+
*
|
|
286
|
+
* @param {String} key environment key
|
|
287
|
+
* @param {String} val environment value
|
|
288
|
+
* @return {Server|Mixed} for chaining, or the setting value
|
|
289
|
+
* @memberOf Application
|
|
290
|
+
*/
|
|
291
|
+
loadConfig(key, val) {
|
|
292
|
+
let env = this.get(Constants.RESERVED.ENV);
|
|
293
|
+
let cfg = require(val);
|
|
294
|
+
if (cfg[env]) {
|
|
295
|
+
cfg = cfg[env];
|
|
296
|
+
}
|
|
297
|
+
this.set(key, cfg);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Set the route function for the specified server type.
|
|
301
|
+
*
|
|
302
|
+
* Examples:
|
|
303
|
+
*
|
|
304
|
+
* app.route('area', routeFunc);
|
|
305
|
+
*
|
|
306
|
+
* let routeFunc = function(session, msg, app, cb) {
|
|
307
|
+
* // all request to area would be route to the first area server
|
|
308
|
+
* let areas = app.getServersByType('area');
|
|
309
|
+
* cb(null, areas[0].id);
|
|
310
|
+
* };
|
|
311
|
+
*
|
|
312
|
+
* @param {String} serverType server type string
|
|
313
|
+
* @param {Function} routeFunc route function. routeFunc(session, msg, app, cb)
|
|
314
|
+
* @return {Object} current application instance for chain invoking
|
|
315
|
+
* @memberOf Application
|
|
316
|
+
*/
|
|
317
|
+
route(serverType, routeFunc) {
|
|
318
|
+
let routes = this.get(Constants.KEYWORDS.ROUTE);
|
|
319
|
+
if (!routes) {
|
|
320
|
+
routes = {};
|
|
321
|
+
this.set(Constants.KEYWORDS.ROUTE, routes);
|
|
322
|
+
}
|
|
323
|
+
routes[serverType] = routeFunc;
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Set before stop function. It would perform before servers stop.
|
|
328
|
+
*
|
|
329
|
+
* @param {Function} fun before close function
|
|
330
|
+
* @return {Void}
|
|
331
|
+
* @memberOf Application
|
|
332
|
+
*/
|
|
333
|
+
beforeStopHook(fun) {
|
|
334
|
+
logger.warn('this method was deprecated in melo 0.8');
|
|
335
|
+
if (!!fun && typeof fun === 'function') {
|
|
336
|
+
this.set(Constants.KEYWORDS.BEFORE_STOP_HOOK, fun);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Start application. It would load the default components and start all the loaded components.
|
|
341
|
+
*
|
|
342
|
+
* @param {Function} cb callback function
|
|
343
|
+
* @memberOf Application
|
|
344
|
+
*/
|
|
345
|
+
start(cb) {
|
|
346
|
+
this.startTime = Date.now();
|
|
347
|
+
if (this.state > STATE_INITED) {
|
|
348
|
+
utils.invokeCallback(cb, new Error('application has already start.'));
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
let self = this;
|
|
352
|
+
appUtil.startByType(self, function () {
|
|
353
|
+
appUtil.loadDefaultComponents(self);
|
|
354
|
+
let startUp = function () {
|
|
355
|
+
self.state = STATE_BEFORE_START;
|
|
356
|
+
logger.info('%j enter before start...', self.getServerId());
|
|
357
|
+
appUtil.optComponents(self.loaded, Constants.RESERVED.BEFORE_START, function (err) {
|
|
358
|
+
if (err) {
|
|
359
|
+
utils.invokeCallback(cb, err);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
logger.info('%j enter start...', self.getServerId());
|
|
363
|
+
appUtil.optComponents(self.loaded, Constants.RESERVED.START, function (err) {
|
|
364
|
+
self.state = STATE_START;
|
|
365
|
+
if (err) {
|
|
366
|
+
utils.invokeCallback(cb, err);
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
logger.info('%j enter after start...', self.getServerId());
|
|
370
|
+
self.afterStart(cb);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
};
|
|
376
|
+
appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.BEFORE_STARTUP, self, function (err) {
|
|
377
|
+
if (err) {
|
|
378
|
+
utils.invokeCallback(cb, err);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
startUp();
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Lifecycle callback for after start.
|
|
388
|
+
*
|
|
389
|
+
* @param {Function} cb callback function
|
|
390
|
+
* @return {Void}
|
|
391
|
+
*/
|
|
392
|
+
afterStart(cb) {
|
|
393
|
+
if (this.state !== STATE_START) {
|
|
394
|
+
utils.invokeCallback(cb, new Error('application is not running now.'));
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
let self = this;
|
|
398
|
+
appUtil.optComponents(this.loaded, Constants.RESERVED.AFTER_START, function (err) {
|
|
399
|
+
self.state = STATE_STARTED;
|
|
400
|
+
let id = self.getServerId();
|
|
401
|
+
if (!err) {
|
|
402
|
+
logger.info('%j finish start', id);
|
|
403
|
+
}
|
|
404
|
+
appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.AFTER_STARTUP, self, function (err) {
|
|
405
|
+
let usedTime = Date.now() - self.startTime;
|
|
406
|
+
logger.info('%j startup in %s ms', id, usedTime);
|
|
407
|
+
self.event.emit(events_2.default.START_SERVER, id);
|
|
408
|
+
cb && cb(err);
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Stop components.
|
|
414
|
+
*
|
|
415
|
+
* @param {Boolean} force whether stop the app immediately
|
|
416
|
+
*/
|
|
417
|
+
stop(force) {
|
|
418
|
+
if (this.state > STATE_STARTED) {
|
|
419
|
+
logger.warn('[melo application] application is not running now.');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
this.state = STATE_STOPED;
|
|
423
|
+
let self = this;
|
|
424
|
+
this.stopTimer = setTimeout(function () {
|
|
425
|
+
process.exit(0);
|
|
426
|
+
}, Constants.TIME.TIME_WAIT_STOP);
|
|
427
|
+
let cancelShutDownTimer = function () {
|
|
428
|
+
if (!!self.stopTimer) {
|
|
429
|
+
clearTimeout(self.stopTimer);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
let shutDown = function () {
|
|
433
|
+
appUtil.stopComps(self.loaded, 0, force, function () {
|
|
434
|
+
cancelShutDownTimer();
|
|
435
|
+
if (force) {
|
|
436
|
+
process.exit(0);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
};
|
|
440
|
+
let fun = this.get(Constants.KEYWORDS.BEFORE_STOP_HOOK);
|
|
441
|
+
appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.BEFORE_SHUTDOWN, self, function (err) {
|
|
442
|
+
if (err) {
|
|
443
|
+
console.error(`throw err when beforeShutdown `, err.stack);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
if (!!fun) {
|
|
447
|
+
utils.invokeCallback(fun, self, shutDown, cancelShutDownTimer);
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
shutDown();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}, cancelShutDownTimer);
|
|
454
|
+
}
|
|
455
|
+
set(setting, val, attach) {
|
|
456
|
+
this.settings[setting] = val;
|
|
457
|
+
if (attach) {
|
|
458
|
+
this[setting] = val;
|
|
459
|
+
}
|
|
460
|
+
return this;
|
|
461
|
+
}
|
|
462
|
+
get(setting) {
|
|
463
|
+
return this.settings[setting];
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Check if `setting` is enabled.
|
|
467
|
+
*
|
|
468
|
+
* @param {String} setting application setting
|
|
469
|
+
* @return {Boolean}
|
|
470
|
+
* @memberOf Application
|
|
471
|
+
*/
|
|
472
|
+
enabled(setting) {
|
|
473
|
+
return !!this.get(setting);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Check if `setting` is disabled.
|
|
477
|
+
*
|
|
478
|
+
* @param {String} setting application setting
|
|
479
|
+
* @return {Boolean}
|
|
480
|
+
* @memberOf Application
|
|
481
|
+
*/
|
|
482
|
+
disabled(setting) {
|
|
483
|
+
return !this.get(setting);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Enable `setting`.
|
|
487
|
+
*
|
|
488
|
+
* @param {String} setting application setting
|
|
489
|
+
* @return {app} for chaining
|
|
490
|
+
* @memberOf Application
|
|
491
|
+
*/
|
|
492
|
+
enable(setting) {
|
|
493
|
+
return this.set(setting, true);
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Disable `setting`.
|
|
497
|
+
*
|
|
498
|
+
* @param {String} setting application setting
|
|
499
|
+
* @return {app} for chaining
|
|
500
|
+
* @memberOf Application
|
|
501
|
+
*/
|
|
502
|
+
disable(setting) {
|
|
503
|
+
return this.set(setting, false);
|
|
504
|
+
}
|
|
505
|
+
configure(env, type, fn) {
|
|
506
|
+
let args = [].slice.call(arguments);
|
|
507
|
+
fn = args.pop();
|
|
508
|
+
env = type = Constants.RESERVED.ALL;
|
|
509
|
+
if (args.length > 0) {
|
|
510
|
+
env = args[0];
|
|
511
|
+
}
|
|
512
|
+
if (args.length > 1) {
|
|
513
|
+
type = args[1];
|
|
514
|
+
}
|
|
515
|
+
if (env === Constants.RESERVED.ALL || contains(this.settings.env, env)) {
|
|
516
|
+
if (type === Constants.RESERVED.ALL || contains(this.settings.serverType, type)) {
|
|
517
|
+
fn.call(this);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return this;
|
|
521
|
+
}
|
|
522
|
+
registerAdmin(moduleId, module, opts) {
|
|
523
|
+
let modules = this.get(Constants.KEYWORDS.MODULE);
|
|
524
|
+
if (!modules) {
|
|
525
|
+
modules = {};
|
|
526
|
+
this.set(Constants.KEYWORDS.MODULE, modules);
|
|
527
|
+
}
|
|
528
|
+
if (typeof moduleId !== 'string') {
|
|
529
|
+
opts = module;
|
|
530
|
+
module = moduleId;
|
|
531
|
+
if (module) {
|
|
532
|
+
moduleId = (module.moduleId);
|
|
533
|
+
if (!moduleId)
|
|
534
|
+
moduleId = module.constructor.name;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (!moduleId) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
modules[moduleId] = {
|
|
541
|
+
moduleId: moduleId,
|
|
542
|
+
module: module,
|
|
543
|
+
opts: opts
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Use plugin.
|
|
548
|
+
*
|
|
549
|
+
* @param {Object} plugin plugin instance
|
|
550
|
+
* @param {[type]} opts (optional) construct parameters for the factory function
|
|
551
|
+
* @memberOf Application
|
|
552
|
+
*/
|
|
553
|
+
use(plugin, opts) {
|
|
554
|
+
opts = opts || {};
|
|
555
|
+
if (!plugin) {
|
|
556
|
+
throw new Error(`pluin is null!]`);
|
|
557
|
+
}
|
|
558
|
+
if (this.usedPlugins.indexOf(plugin) >= 0) {
|
|
559
|
+
throw new Error(`pluin[${plugin.name} was used already!]`);
|
|
560
|
+
}
|
|
561
|
+
if (plugin.components) {
|
|
562
|
+
for (let componentCtor of plugin.components) {
|
|
563
|
+
this.load(componentCtor, opts);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (plugin.events) {
|
|
567
|
+
for (let eventCtor of plugin.events) {
|
|
568
|
+
this.loadEvent(eventCtor, opts);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
this.usedPlugins.push(plugin);
|
|
572
|
+
console.warn(`used Plugin : ${plugin.name}`);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Application transaction. Transcation includes conditions and handlers, if conditions are satisfied, handlers would be executed.
|
|
576
|
+
* And you can set retry times to execute handlers. The transaction log is in file logs/transaction.log.
|
|
577
|
+
*
|
|
578
|
+
* @param {String} name transaction name
|
|
579
|
+
* @param {Object} conditions functions which are called before transaction
|
|
580
|
+
* @param {Object} handlers functions which are called during transaction
|
|
581
|
+
* @param {Number} retry retry times to execute handlers if conditions are successfully executed
|
|
582
|
+
* @memberOf Application
|
|
583
|
+
*/
|
|
584
|
+
transaction(name, conditions, handlers, retry) {
|
|
585
|
+
appManager.transaction(name, conditions, handlers, retry);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Get master server info.
|
|
589
|
+
*
|
|
590
|
+
* @return {Object} master server info, {id, host, port}
|
|
591
|
+
* @memberOf Application
|
|
592
|
+
*/
|
|
593
|
+
getMaster() {
|
|
594
|
+
return this.master;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Get current server info.
|
|
598
|
+
*
|
|
599
|
+
* @return {Object} current server info, {id, serverType, host, port}
|
|
600
|
+
* @memberOf Application
|
|
601
|
+
*/
|
|
602
|
+
getCurServer() {
|
|
603
|
+
return this.curServer;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Get current server id.
|
|
607
|
+
*
|
|
608
|
+
* @return {String|Number} current server id from servers.json
|
|
609
|
+
* @memberOf Application
|
|
610
|
+
*/
|
|
611
|
+
getServerId() {
|
|
612
|
+
return this.serverId;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Get current server
|
|
616
|
+
* @returns ServerInfo
|
|
617
|
+
*/
|
|
618
|
+
getCurrentServer() {
|
|
619
|
+
return this.curServer;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Get current server type.
|
|
623
|
+
*
|
|
624
|
+
* @return {String|Number} current server type from servers.json
|
|
625
|
+
* @memberOf Application
|
|
626
|
+
*/
|
|
627
|
+
getServerType() {
|
|
628
|
+
return this.serverType;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Get all the current server infos.
|
|
632
|
+
*
|
|
633
|
+
* @return {Object} server info map, key: server id, value: server info
|
|
634
|
+
* @memberOf Application
|
|
635
|
+
*/
|
|
636
|
+
getServers() {
|
|
637
|
+
return this.servers;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Get all server infos from servers.json.
|
|
641
|
+
*
|
|
642
|
+
* @return {Object} server info map, key: server id, value: server info
|
|
643
|
+
* @memberOf Application
|
|
644
|
+
*/
|
|
645
|
+
getServersFromConfig() {
|
|
646
|
+
return this.get(Constants.KEYWORDS.SERVER_MAP);
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Get all the server type.
|
|
650
|
+
*
|
|
651
|
+
* @return {Array} server type list
|
|
652
|
+
* @memberOf Application
|
|
653
|
+
*/
|
|
654
|
+
getServerTypes() {
|
|
655
|
+
return this.serverTypes;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Get server info by server id from current server cluster.
|
|
659
|
+
*
|
|
660
|
+
* @param {String} serverId server id
|
|
661
|
+
* @return {Object} server info or undefined
|
|
662
|
+
* @memberOf Application
|
|
663
|
+
*/
|
|
664
|
+
getServerById(serverId) {
|
|
665
|
+
return this.servers[serverId];
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Get server info by server id from servers.json.
|
|
669
|
+
*
|
|
670
|
+
* @param {String} serverId server id
|
|
671
|
+
* @return {Object} server info or undefined
|
|
672
|
+
* @memberOf Application
|
|
673
|
+
*/
|
|
674
|
+
getServerFromConfig(serverId) {
|
|
675
|
+
return this.get(Constants.KEYWORDS.SERVER_MAP)[serverId];
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Get server infos by server type.
|
|
679
|
+
*
|
|
680
|
+
* @param {String} serverType server type
|
|
681
|
+
* @return {Array} server info list
|
|
682
|
+
* @memberOf Application
|
|
683
|
+
*/
|
|
684
|
+
getServersByType(serverType) {
|
|
685
|
+
return this.serverTypeMaps[serverType];
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Check the server whether is a frontend server
|
|
689
|
+
*
|
|
690
|
+
* @param {server} server server info. it would check current server
|
|
691
|
+
* if server not specified
|
|
692
|
+
* @return {Boolean}
|
|
693
|
+
*
|
|
694
|
+
* @memberOf Application
|
|
695
|
+
*/
|
|
696
|
+
isFrontend(server) {
|
|
697
|
+
server = server || this.getCurServer();
|
|
698
|
+
return !!server && server.frontend === 'true';
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Check the server whether is a backend server
|
|
702
|
+
*
|
|
703
|
+
* @param {server} server server info. it would check current server
|
|
704
|
+
* if server not specified
|
|
705
|
+
* @return {Boolean}
|
|
706
|
+
* @memberOf Application
|
|
707
|
+
*/
|
|
708
|
+
isBackend(server) {
|
|
709
|
+
server = server || this.getCurServer();
|
|
710
|
+
return !!server && !server.frontend;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Check whether current server is a master server
|
|
714
|
+
*
|
|
715
|
+
* @return {Boolean}
|
|
716
|
+
* @memberOf Application
|
|
717
|
+
*/
|
|
718
|
+
isMaster() {
|
|
719
|
+
return this.serverType === Constants.RESERVED.MASTER;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Add new server info to current application in runtime.
|
|
723
|
+
*
|
|
724
|
+
* @param {Array} servers new server info list
|
|
725
|
+
* @memberOf Application
|
|
726
|
+
*/
|
|
727
|
+
addServers(servers) {
|
|
728
|
+
if (!servers || !servers.length) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
let item, slist;
|
|
732
|
+
for (let i = 0, l = servers.length; i < l; i++) {
|
|
733
|
+
item = servers[i];
|
|
734
|
+
// update global server map
|
|
735
|
+
this.servers[item.id] = item;
|
|
736
|
+
// update global server type map
|
|
737
|
+
slist = this.serverTypeMaps[item.serverType];
|
|
738
|
+
if (!slist) {
|
|
739
|
+
this.serverTypeMaps[item.serverType] = slist = [];
|
|
740
|
+
}
|
|
741
|
+
replaceServer(slist, item);
|
|
742
|
+
// update global server type list
|
|
743
|
+
if (this.serverTypes.indexOf(item.serverType) < 0) {
|
|
744
|
+
this.serverTypes.push(item.serverType);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
this.event.emit(events_2.default.ADD_SERVERS, servers);
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Remove server info from current application at runtime.
|
|
751
|
+
*
|
|
752
|
+
* @param {Array} ids server id list
|
|
753
|
+
* @memberOf Application
|
|
754
|
+
*/
|
|
755
|
+
removeServers(ids) {
|
|
756
|
+
if (!ids || !ids.length) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
let id, item, slist;
|
|
760
|
+
for (let i = 0, l = ids.length; i < l; i++) {
|
|
761
|
+
id = ids[i];
|
|
762
|
+
item = this.servers[id];
|
|
763
|
+
if (!item) {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
// clean global server map
|
|
767
|
+
delete this.servers[id];
|
|
768
|
+
// clean global server type map
|
|
769
|
+
slist = this.serverTypeMaps[item.serverType];
|
|
770
|
+
removeServer(slist, id);
|
|
771
|
+
// TODO: should remove the server type if the slist is empty?
|
|
772
|
+
}
|
|
773
|
+
this.event.emit(events_2.default.REMOVE_SERVERS, ids);
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Replace server info from current application at runtime.
|
|
777
|
+
*
|
|
778
|
+
* @param {Object} server id map
|
|
779
|
+
* @memberOf Application
|
|
780
|
+
*/
|
|
781
|
+
replaceServers(servers) {
|
|
782
|
+
if (!servers) {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
this.servers = servers;
|
|
786
|
+
this.serverTypeMaps = {};
|
|
787
|
+
this.serverTypes = [];
|
|
788
|
+
let serverArray = [];
|
|
789
|
+
for (let id in servers) {
|
|
790
|
+
let server = servers[id];
|
|
791
|
+
let serverType = server[Constants.RESERVED.SERVER_TYPE];
|
|
792
|
+
let slist = this.serverTypeMaps[serverType];
|
|
793
|
+
if (!slist) {
|
|
794
|
+
this.serverTypeMaps[serverType] = slist = [];
|
|
795
|
+
}
|
|
796
|
+
this.serverTypeMaps[serverType].push(server);
|
|
797
|
+
// update global server type list
|
|
798
|
+
if (this.serverTypes.indexOf(serverType) < 0) {
|
|
799
|
+
this.serverTypes.push(serverType);
|
|
800
|
+
}
|
|
801
|
+
serverArray.push(server);
|
|
802
|
+
}
|
|
803
|
+
this.event.emit(events_2.default.REPLACE_SERVERS, serverArray);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Add crons from current application at runtime.
|
|
807
|
+
*
|
|
808
|
+
* @param {Array} crons new crons would be added in application
|
|
809
|
+
* @memberOf Application
|
|
810
|
+
*/
|
|
811
|
+
addCrons(crons) {
|
|
812
|
+
if (!crons || !crons.length) {
|
|
813
|
+
logger.warn('crons is not defined.');
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
this.event.emit(events_2.default.ADD_CRONS, crons);
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Remove crons from current application at runtime.
|
|
820
|
+
*
|
|
821
|
+
* @param {Array} crons old crons would be removed in application
|
|
822
|
+
* @memberOf Application
|
|
823
|
+
*/
|
|
824
|
+
removeCrons(crons) {
|
|
825
|
+
if (!crons || !crons.length) {
|
|
826
|
+
logger.warn('ids is not defined.');
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
this.event.emit(events_2.default.REMOVE_CRONS, crons);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* 加载一个事件侦听
|
|
833
|
+
* @param Event
|
|
834
|
+
* @param opts
|
|
835
|
+
*/
|
|
836
|
+
loadEvent(Event, opts) {
|
|
837
|
+
let eventInstance = new Event(opts);
|
|
838
|
+
for (let evt in events_2.AppEvents) {
|
|
839
|
+
let name = events_2.AppEvents[evt];
|
|
840
|
+
let method = eventInstance[name];
|
|
841
|
+
if (method) {
|
|
842
|
+
this.event.on(name, method.bind(eventInstance));
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
exports.Application = Application;
|
|
848
|
+
let replaceServer = function (slist, serverInfo) {
|
|
849
|
+
for (let i = 0, l = slist.length; i < l; i++) {
|
|
850
|
+
if (slist[i].id === serverInfo.id) {
|
|
851
|
+
slist[i] = serverInfo;
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
slist.push(serverInfo);
|
|
856
|
+
};
|
|
857
|
+
let removeServer = function (slist, id) {
|
|
858
|
+
if (!slist || !slist.length) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
for (let i = 0, l = slist.length; i < l; i++) {
|
|
862
|
+
if (slist[i].id === id) {
|
|
863
|
+
slist.splice(i, 1);
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
let contains = function (str, settings) {
|
|
869
|
+
if (!settings) {
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
let ts = settings.split('|');
|
|
873
|
+
for (let i = 0, l = ts.length; i < l; i++) {
|
|
874
|
+
if (str === ts[i]) {
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return false;
|
|
879
|
+
};
|
|
880
|
+
let addFilter = function (app, type, filter) {
|
|
881
|
+
let filters = app.get(type);
|
|
882
|
+
if (!filters) {
|
|
883
|
+
filters = [];
|
|
884
|
+
app.set(type, filters);
|
|
885
|
+
}
|
|
886
|
+
filters.push(filter);
|
|
887
|
+
};
|
|
888
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvYXBwbGljYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQUVIOztHQUVHO0FBQ0gsc0NBQXNDO0FBQ3RDLHlEQUE2RDtBQUM3RCxtQ0FBc0M7QUFDdEMsMENBQTZEO0FBQzdELDBDQUEwQztBQUUxQyw4Q0FBOEM7QUFFOUMsMERBQTBEO0FBRTFELHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUE0QjdCLElBQUksTUFBTSxHQUFHLElBQUEsdUJBQVMsRUFBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0FBa0UxRDs7R0FFRztBQUNILElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQyxDQUFFLGlCQUFpQjtBQUN4QyxJQUFJLGtCQUFrQixHQUFHLENBQUMsQ0FBQyxDQUFFLG1CQUFtQjtBQUNoRCxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FBRSxZQUFZO0FBQ2xDLElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQyxDQUFFLGtCQUFrQjtBQUMxQyxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBRSxpQkFBaUI7QUFFeEMsTUFBYSxXQUFXO0lBQXhCO1FBRUksV0FBTSxHQUFpQixFQUFFLENBQUMsQ0FBTyx3QkFBd0I7UUFDekQsZUFBVSxHQWVOLEVBQUUsQ0FBQyxDQUFHLHdCQUF3QjtRQU1sQyxhQUFRLEdBQTJCLEVBQUUsQ0FBQyxDQUFLLDBCQUEwQjtRQUNyRSxVQUFLLEdBQUcsSUFBSSxxQkFBWSxFQUFFLENBQUMsQ0FBRSxpQ0FBaUM7UUFROUQsc0JBQXNCO1FBQ3RCLFdBQU0sR0FBb0IsSUFBSSxDQUFDLENBQVMscUJBQXFCO1FBQzdELFlBQU8sR0FBaUMsRUFBRSxDQUFDLENBQVUsOENBQThDO1FBQ25HLG1CQUFjLEdBQXFDLEVBQUUsQ0FBQyxDQUFHLDJDQUEyQztRQUNwRyxnQkFB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
|