@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.
Files changed (296) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +55 -0
  3. package/bin/commadtest.ts +10 -0
  4. package/bin/commands/add.ts +43 -0
  5. package/bin/commands/init.ts +292 -0
  6. package/bin/commands/kill.ts +21 -0
  7. package/bin/commands/list.ts +60 -0
  8. package/bin/commands/masterha.ts +40 -0
  9. package/bin/commands/restart.ts +48 -0
  10. package/bin/commands/start.ts +65 -0
  11. package/bin/commands/stop.ts +26 -0
  12. package/bin/melo.ts +30 -0
  13. package/bin/utils/constants.ts +27 -0
  14. package/bin/utils/utils.ts +130 -0
  15. package/dist/bin/commadtest.js +9 -0
  16. package/dist/bin/commands/add.js +40 -0
  17. package/dist/bin/commands/init.js +279 -0
  18. package/dist/bin/commands/kill.js +21 -0
  19. package/dist/bin/commands/list.js +65 -0
  20. package/dist/bin/commands/masterha.js +36 -0
  21. package/dist/bin/commands/restart.js +45 -0
  22. package/dist/bin/commands/start.js +58 -0
  23. package/dist/bin/commands/stop.js +20 -0
  24. package/dist/bin/melo.js +26 -0
  25. package/dist/bin/utils/constants.js +28 -0
  26. package/dist/bin/utils/utils.js +134 -0
  27. package/dist/lib/application.js +888 -0
  28. package/dist/lib/common/manager/appManager.js +112 -0
  29. package/dist/lib/common/manager/taskManager.js +39 -0
  30. package/dist/lib/common/remote/backend/msgRemote.js +63 -0
  31. package/dist/lib/common/remote/frontend/channelRemote.js +78 -0
  32. package/dist/lib/common/remote/frontend/sessionRemote.js +76 -0
  33. package/dist/lib/common/service/backendSessionService.js +337 -0
  34. package/dist/lib/common/service/channelService.js +514 -0
  35. package/dist/lib/common/service/connectionService.js +95 -0
  36. package/dist/lib/common/service/filterService.js +112 -0
  37. package/dist/lib/common/service/handlerService.js +187 -0
  38. package/dist/lib/common/service/sessionService.js +610 -0
  39. package/dist/lib/components/backendSession.js +14 -0
  40. package/dist/lib/components/channel.js +13 -0
  41. package/dist/lib/components/connection.js +12 -0
  42. package/dist/lib/components/connector.js +437 -0
  43. package/dist/lib/components/dictionary.js +93 -0
  44. package/dist/lib/components/master.js +39 -0
  45. package/dist/lib/components/monitor.js +25 -0
  46. package/dist/lib/components/protobuf.js +156 -0
  47. package/dist/lib/components/proxy.js +236 -0
  48. package/dist/lib/components/pushScheduler.js +62 -0
  49. package/dist/lib/components/remote.js +127 -0
  50. package/dist/lib/components/server.js +63 -0
  51. package/dist/lib/components/session.js +20 -0
  52. package/dist/lib/connectors/commands/handshake.js +119 -0
  53. package/dist/lib/connectors/commands/heartbeat.js +67 -0
  54. package/dist/lib/connectors/commands/kick.js +15 -0
  55. package/dist/lib/connectors/common/coder.js +90 -0
  56. package/dist/lib/connectors/common/handler.js +57 -0
  57. package/dist/lib/connectors/hybrid/IHybridSocket.js +3 -0
  58. package/dist/lib/connectors/hybrid/switcher.js +100 -0
  59. package/dist/lib/connectors/hybrid/tcpprocessor.js +40 -0
  60. package/dist/lib/connectors/hybrid/tcpsocket.js +171 -0
  61. package/dist/lib/connectors/hybrid/wsprocessor.js +49 -0
  62. package/dist/lib/connectors/hybridconnector.js +89 -0
  63. package/dist/lib/connectors/hybridsocket.js +139 -0
  64. package/dist/lib/connectors/mqtt/generate.js +113 -0
  65. package/dist/lib/connectors/mqtt/mqttadaptor.js +81 -0
  66. package/dist/lib/connectors/mqtt/protocol.js +48 -0
  67. package/dist/lib/connectors/mqttconnector.js +107 -0
  68. package/dist/lib/connectors/mqttsocket.js +59 -0
  69. package/dist/lib/connectors/sioconnector.js +135 -0
  70. package/dist/lib/connectors/siosocket.js +69 -0
  71. package/dist/lib/connectors/udpconnector.js +76 -0
  72. package/dist/lib/connectors/udpsocket.js +93 -0
  73. package/dist/lib/filters/handler/serial.js +44 -0
  74. package/dist/lib/filters/handler/time.js +32 -0
  75. package/dist/lib/filters/handler/timeout.js +45 -0
  76. package/dist/lib/filters/handler/toobusy.js +36 -0
  77. package/dist/lib/filters/rpc/rpcLog.js +43 -0
  78. package/dist/lib/filters/rpc/toobusy.js +41 -0
  79. package/dist/lib/index.js +81 -0
  80. package/dist/lib/interfaces/IComponent.js +3 -0
  81. package/dist/lib/interfaces/IConnector.js +3 -0
  82. package/dist/lib/interfaces/IHandlerFilter.js +3 -0
  83. package/dist/lib/interfaces/ILifeCycle.js +3 -0
  84. package/dist/lib/interfaces/IPlugin.js +3 -0
  85. package/dist/lib/interfaces/IPushScheduler.js +3 -0
  86. package/dist/lib/interfaces/ISocket.js +3 -0
  87. package/dist/lib/interfaces/IStore.js +3 -0
  88. package/dist/lib/interfaces/define.js +3 -0
  89. package/dist/lib/master/master.js +129 -0
  90. package/dist/lib/master/starter.js +236 -0
  91. package/dist/lib/master/watchdog.js +120 -0
  92. package/dist/lib/melo.js +125 -0
  93. package/dist/lib/modules/console.js +436 -0
  94. package/dist/lib/modules/masterwatcher.js +98 -0
  95. package/dist/lib/modules/monitorwatcher.js +124 -0
  96. package/dist/lib/modules/onlineUser.js +69 -0
  97. package/dist/lib/modules/restartNotifyModule.js +107 -0
  98. package/dist/lib/modules/watchServer.js +737 -0
  99. package/dist/lib/monitor/monitor.js +80 -0
  100. package/dist/lib/pushSchedulers/buffer.js +96 -0
  101. package/dist/lib/pushSchedulers/direct.js +58 -0
  102. package/dist/lib/pushSchedulers/multi.js +80 -0
  103. package/dist/lib/server/server.js +500 -0
  104. package/dist/lib/util/appUtil.js +306 -0
  105. package/dist/lib/util/constants.js +117 -0
  106. package/dist/lib/util/countDownLatch.js +51 -0
  107. package/dist/lib/util/events.js +20 -0
  108. package/dist/lib/util/handlerHelper.js +8 -0
  109. package/dist/lib/util/log.js +14 -0
  110. package/dist/lib/util/moduleUtil.js +101 -0
  111. package/dist/lib/util/pathUtil.js +134 -0
  112. package/dist/lib/util/remoterHelper.js +8 -0
  113. package/dist/lib/util/utils.js +358 -0
  114. package/dist/test/application.js +522 -0
  115. package/dist/test/config/log4js.json +28 -0
  116. package/dist/test/config/master.json +9 -0
  117. package/dist/test/config/servers.json +6 -0
  118. package/dist/test/filters/handler/serial.js +41 -0
  119. package/dist/test/filters/handler/time.js +41 -0
  120. package/dist/test/filters/handler/timeout.js +41 -0
  121. package/dist/test/filters/handler/toobusy.js +57 -0
  122. package/dist/test/filters/rpc/rpcLog.js +22 -0
  123. package/dist/test/filters/rpc/toobusy.js +39 -0
  124. package/dist/test/manager/mockChannelManager.js +77 -0
  125. package/dist/test/manager/taskManager.js +68 -0
  126. package/dist/test/mock-base/app/servers/other-file +0 -0
  127. package/dist/test/mock-plugin/components/mockPlugin.js +10 -0
  128. package/dist/test/mock-plugin/events/mockEvent.js +12 -0
  129. package/dist/test/modules/console.js +242 -0
  130. package/dist/test/pomelo.js +19 -0
  131. package/dist/test/remote/channelRemote.js +159 -0
  132. package/dist/test/service/channel.js +134 -0
  133. package/dist/test/service/channelService.js +216 -0
  134. package/dist/test/service/connectionService.js +114 -0
  135. package/dist/test/service/filterService.js +144 -0
  136. package/dist/test/service/handlerService.js +65 -0
  137. package/dist/test/service/sessionService.js +387 -0
  138. package/dist/test/util/countDownLatch.js +70 -0
  139. package/dist/test/util/pathUtil.js +108 -0
  140. package/dist/test/util/utils.js +140 -0
  141. package/lib/application.ts +1240 -0
  142. package/lib/common/manager/appManager.ts +118 -0
  143. package/lib/common/manager/taskManager.ts +50 -0
  144. package/lib/common/remote/backend/msgRemote.ts +134 -0
  145. package/lib/common/remote/frontend/channelRemote.ts +91 -0
  146. package/lib/common/remote/frontend/sessionRemote.ts +91 -0
  147. package/lib/common/service/backendSessionService.ts +388 -0
  148. package/lib/common/service/channelService.ts +609 -0
  149. package/lib/common/service/connectionService.ts +112 -0
  150. package/lib/common/service/filterService.ts +118 -0
  151. package/lib/common/service/handlerService.ts +224 -0
  152. package/lib/common/service/sessionService.ts +731 -0
  153. package/lib/components/backendSession.ts +14 -0
  154. package/lib/components/channel.ts +11 -0
  155. package/lib/components/connection.ts +13 -0
  156. package/lib/components/connector.ts +533 -0
  157. package/lib/components/dictionary.ts +121 -0
  158. package/lib/components/master.ts +41 -0
  159. package/lib/components/monitor.ts +30 -0
  160. package/lib/components/protobuf.ts +208 -0
  161. package/lib/components/proxy.ts +282 -0
  162. package/lib/components/pushScheduler.ts +70 -0
  163. package/lib/components/remote.ts +166 -0
  164. package/lib/components/server.ts +71 -0
  165. package/lib/components/session.ts +22 -0
  166. package/lib/connectors/commands/handshake.ts +155 -0
  167. package/lib/connectors/commands/heartbeat.ts +83 -0
  168. package/lib/connectors/commands/kick.ts +11 -0
  169. package/lib/connectors/common/coder.ts +93 -0
  170. package/lib/connectors/common/handler.ts +62 -0
  171. package/lib/connectors/hybrid/IHybridSocket.ts +9 -0
  172. package/lib/connectors/hybrid/switcher.ts +142 -0
  173. package/lib/connectors/hybrid/tcpprocessor.ts +43 -0
  174. package/lib/connectors/hybrid/tcpsocket.ts +223 -0
  175. package/lib/connectors/hybrid/wsprocessor.ts +57 -0
  176. package/lib/connectors/hybridconnector.ts +134 -0
  177. package/lib/connectors/hybridsocket.ts +168 -0
  178. package/lib/connectors/mqtt/generate.ts +103 -0
  179. package/lib/connectors/mqtt/mqttadaptor.ts +114 -0
  180. package/lib/connectors/mqtt/protocol.ts +49 -0
  181. package/lib/connectors/mqttconnector.ts +134 -0
  182. package/lib/connectors/mqttsocket.ts +79 -0
  183. package/lib/connectors/sioconnector.ts +161 -0
  184. package/lib/connectors/siosocket.ts +85 -0
  185. package/lib/connectors/udpconnector.ts +113 -0
  186. package/lib/connectors/udpsocket.ts +110 -0
  187. package/lib/filters/handler/serial.ts +46 -0
  188. package/lib/filters/handler/time.ts +35 -0
  189. package/lib/filters/handler/timeout.ts +50 -0
  190. package/lib/filters/handler/toobusy.ts +37 -0
  191. package/lib/filters/rpc/rpcLog.ts +42 -0
  192. package/lib/filters/rpc/toobusy.ts +41 -0
  193. package/lib/index.ts +74 -0
  194. package/lib/interfaces/IComponent.ts +47 -0
  195. package/lib/interfaces/IConnector.ts +20 -0
  196. package/lib/interfaces/IHandlerFilter.ts +15 -0
  197. package/lib/interfaces/ILifeCycle.ts +16 -0
  198. package/lib/interfaces/IPlugin.ts +65 -0
  199. package/lib/interfaces/IPushScheduler.ts +52 -0
  200. package/lib/interfaces/ISocket.ts +26 -0
  201. package/lib/interfaces/IStore.ts +10 -0
  202. package/lib/interfaces/define.ts +15 -0
  203. package/lib/master/master.ts +148 -0
  204. package/lib/master/starter.ts +234 -0
  205. package/lib/master/watchdog.ts +135 -0
  206. package/lib/melo.ts +152 -0
  207. package/lib/modules/console.ts +465 -0
  208. package/lib/modules/masterwatcher.ts +120 -0
  209. package/lib/modules/monitorwatcher.ts +151 -0
  210. package/lib/modules/onlineUser.ts +78 -0
  211. package/lib/modules/restartNotifyModule.ts +128 -0
  212. package/lib/modules/watchServer.ts +766 -0
  213. package/lib/monitor/monitor.ts +99 -0
  214. package/lib/pushSchedulers/buffer.ts +117 -0
  215. package/lib/pushSchedulers/direct.ts +65 -0
  216. package/lib/pushSchedulers/multi.ts +94 -0
  217. package/lib/server/server.ts +554 -0
  218. package/lib/util/appUtil.ts +313 -0
  219. package/lib/util/constants.ts +154 -0
  220. package/lib/util/countDownLatch.ts +72 -0
  221. package/lib/util/events.ts +15 -0
  222. package/lib/util/handlerHelper.ts +5 -0
  223. package/lib/util/log.ts +11 -0
  224. package/lib/util/moduleUtil.ts +110 -0
  225. package/lib/util/pathUtil.ts +132 -0
  226. package/lib/util/remoterHelper.ts +68 -0
  227. package/lib/util/utils.ts +365 -0
  228. package/package.json +93 -0
  229. package/template/game-server/.vscode/launch.json +27 -0
  230. package/template/game-server/app/servers/connector/handler/entryHandler.ts +50 -0
  231. package/template/game-server/app/servers/connector/remote/authRemoter.ts +36 -0
  232. package/template/game-server/app.ts +30 -0
  233. package/template/game-server/app.ts.mqtt +32 -0
  234. package/template/game-server/app.ts.sio +36 -0
  235. package/template/game-server/app.ts.sio.wss +34 -0
  236. package/template/game-server/app.ts.udp +31 -0
  237. package/template/game-server/app.ts.wss +40 -0
  238. package/template/game-server/config/adminServer.json +5 -0
  239. package/template/game-server/config/adminUser.json +22 -0
  240. package/template/game-server/config/clientProtos.json +1 -0
  241. package/template/game-server/config/dictionary.json +1 -0
  242. package/template/game-server/config/log4js.json +150 -0
  243. package/template/game-server/config/master.json +8 -0
  244. package/template/game-server/config/serverProtos.json +1 -0
  245. package/template/game-server/config/servers.json +12 -0
  246. package/template/game-server/copy.js +5 -0
  247. package/template/game-server/package.json +28 -0
  248. package/template/game-server/preload.ts +40 -0
  249. package/template/game-server/tsconfig.json +36 -0
  250. package/template/npm-install.bat +4 -0
  251. package/template/npm-install.sh +5 -0
  252. package/template/readme.md +31 -0
  253. package/template/shared/server.crt +15 -0
  254. package/template/shared/server.key +15 -0
  255. package/template/web-server/app.js +25 -0
  256. package/template/web-server/app.js.https +36 -0
  257. package/template/web-server/bin/component.bat +1 -0
  258. package/template/web-server/bin/component.sh +1 -0
  259. package/template/web-server/package.json +10 -0
  260. package/template/web-server/public/css/base.css +76 -0
  261. package/template/web-server/public/image/logo.png +0 -0
  262. package/template/web-server/public/image/sp.png +0 -0
  263. package/template/web-server/public/index.html +57 -0
  264. package/template/web-server/public/index.html.sio +58 -0
  265. package/template/web-server/public/js/lib/build/build.js +1730 -0
  266. package/template/web-server/public/js/lib/build/build.js.wss +1721 -0
  267. package/template/web-server/public/js/lib/component.json +6 -0
  268. package/template/web-server/public/js/lib/local/boot/component.json +11 -0
  269. package/template/web-server/public/js/lib/local/boot/index.js +11 -0
  270. package/template/web-server/public/js/lib/meloclient.js +456 -0
  271. package/template/web-server/public/js/lib/meloclient.js.wss +456 -0
  272. package/template/web-server/public/js/lib/socket.io.js +3 -0
  273. package/test/application.ts +607 -0
  274. package/test/filters/handler/serial.ts +47 -0
  275. package/test/filters/handler/time.ts +47 -0
  276. package/test/filters/handler/timeout.ts +46 -0
  277. package/test/filters/handler/toobusy.ts +59 -0
  278. package/test/filters/rpc/rpcLog.ts +20 -0
  279. package/test/filters/rpc/toobusy.ts +40 -0
  280. package/test/manager/mockChannelManager.ts +92 -0
  281. package/test/manager/taskManager.ts +78 -0
  282. package/test/mock-base/app/servers/other-file +0 -0
  283. package/test/mock-plugin/components/mockPlugin.ts +8 -0
  284. package/test/mock-plugin/events/mockEvent.ts +12 -0
  285. package/test/modules/console.ts +264 -0
  286. package/test/pomelo.ts +18 -0
  287. package/test/remote/channelRemote.ts +176 -0
  288. package/test/service/channel.ts +161 -0
  289. package/test/service/channelService.ts +243 -0
  290. package/test/service/connectionService.ts +142 -0
  291. package/test/service/filterService.ts +165 -0
  292. package/test/service/handlerService.ts +77 -0
  293. package/test/service/sessionService.ts +464 -0
  294. package/test/util/countDownLatch.ts +81 -0
  295. package/test/util/pathUtil.ts +122 -0
  296. package/test/util/utils.ts +165 -0
@@ -0,0 +1,1240 @@
1
+ /*!
2
+ * Melo -- proto
3
+ * Copyright(c) 2012 xiechengchao <xiecc@163.com>
4
+ * MIT Licensed
5
+ */
6
+
7
+ /**
8
+ * Module dependencies.
9
+ */
10
+ import * as utils from './util/utils';
11
+ import { getLogger, ILogger } from '@bigtyphoon/melo-logger';
12
+ import { EventEmitter } from 'events';
13
+ import { AppEvents, default as events } from './util/events';
14
+ import * as appUtil from './util/appUtil';
15
+ import { ServerStartArgs } from './util/appUtil';
16
+ import * as Constants from './util/constants';
17
+ import { FRONTENDID, ServerInfo } from './util/constants';
18
+ import * as appManager from './common/manager/appManager';
19
+ import { TransactionCondictionFunction, TransactionHandlerFunction } from './common/manager/appManager';
20
+ import * as fs from 'fs';
21
+ import * as path from 'path';
22
+ import { IComponent } from './interfaces/IComponent';
23
+ import { DictionaryComponent } from './components/dictionary';
24
+ import { PushSchedulerComponent } from './components/pushScheduler';
25
+ import { BackendSessionService } from './common/service/backendSessionService';
26
+ import { ChannelService, ChannelServiceOptions } from './common/service/channelService';
27
+ import { SessionComponent } from './components/session';
28
+ import { ServerComponent } from './components/server';
29
+ import { RemoteComponent, RemoteComponentOptions } from './components/remote';
30
+ import { ProxyComponent, ProxyComponentOptions, RouteFunction, RouteMaps } from './components/proxy';
31
+ import { ProtobufComponent, ProtobufComponentOptions } from './components/protobuf';
32
+ import { MonitorComponent } from './components/monitor';
33
+ import { MasterComponent } from './components/master';
34
+ import { ConnectorComponent, ConnectorComponentOptions } from './components/connector';
35
+ import { ConnectionComponent } from './components/connection';
36
+ import { SessionService } from './common/service/sessionService';
37
+ import { ObjectType } from './interfaces/define';
38
+ import { IModule, IModuleFactory } from '@bigtyphoon/melo-admin';
39
+ import { ChannelComponent } from './components/channel';
40
+ import { BackendSessionComponent } from './components/backendSession';
41
+ import { AfterHandlerFilter, BeforeHandlerFilter, IHandlerFilter } from './interfaces/IHandlerFilter';
42
+ import { MailStationErrorHandler, RpcFilter, RpcMsg } from '@bigtyphoon/melo-rpc';
43
+ import { ModuleRecord } from './util/moduleUtil';
44
+ import { ApplicationEventContructor, IPlugin } from './interfaces/IPlugin';
45
+ import { Cron, ResponseErrorHandler } from './server/server';
46
+ import { RemoterProxy } from './util/remoterHelper';
47
+ import { FrontendOrBackendSession, ISession, MonitorOptions, ScheduleOptions, SID, UID } from './index';
48
+
49
+ let logger = getLogger('melo', path.basename(__filename));
50
+
51
+
52
+ export type ConfigureCallback = () => void;
53
+ export type AConfigureFunc1 = () => Promise<void> ;
54
+ export type AConfigureFunc2 = (env: string) => Promise<void> ;
55
+ export type AConfigureFunc3 = (env: string, type: string) => Promise<void>;
56
+
57
+ export interface ApplicationOptions {
58
+ base?: string;
59
+ }
60
+
61
+ export type BeforeStopHookFunction = (app: Application, shutDown: () => void, cancelShutDownTimer: () => void) => void;
62
+
63
+ declare global {
64
+ // 定义用户Rpc基础类
65
+ interface UserRpc {
66
+ test(): void;
67
+ }
68
+
69
+ // channelRemote functions
70
+ type pushMessageFunction = (route: string, msg: any, uids: UID[], opts: ScheduleOptions) => Promise<UID[]>;
71
+ type broadcastFunction = (route: string, msg: any, opts: ScheduleOptions) => Promise<UID[]>;
72
+ // sessionRemote functions
73
+ type bindFunction = (sid: SID, uid: UID) => Promise<void>;
74
+ type unbindFunction = (sid: SID, uid: UID) => Promise<void>;
75
+ type pushFunction = (sid: SID, key: string, value: any) => Promise<void>;
76
+ type pushAllFunction = (sid: SID, settings: { [key: string]: any }) => Promise<void>;
77
+ type getBackendSessionBySidFunction = (sid: SID) => Promise<ISession>;
78
+ type getBackendSessionsByUidFunction = (uid: UID) => Promise<ISession[]>;
79
+ type kickBySidFunction = (sid: SID, reason: string) => Promise<void>;
80
+ type kickByUidFunction = (uid: UID, reason: string) => Promise<void>;
81
+
82
+ interface SysRpc {
83
+ [serverType: string]: {
84
+ /**
85
+ * 用来把客户端发到前端的handler信息转发到后端服务器
86
+ */
87
+ msgRemote: {
88
+ forwardMessage: (routeParam: FrontendOrBackendSession, msg: any, session: ISession) => Promise<void>;
89
+ },
90
+
91
+ /**
92
+ * 用来通知前端服务器往客户端发信息
93
+ */
94
+ channelRemote: {
95
+ pushMessage: RemoterProxy<pushMessageFunction>;
96
+ broadcast: RemoterProxy<broadcastFunction>;
97
+ }
98
+
99
+ /**
100
+ * 用来从前端服务器获取或设置Session相关的服务
101
+ */
102
+ sessionRemote: {
103
+ bind: RemoterProxy<bindFunction>;
104
+ unbind: RemoterProxy<unbindFunction>;
105
+ push: RemoterProxy<pushFunction>;
106
+ pushAll: RemoterProxy<pushAllFunction>;
107
+ getBackendSessionBySid: RemoterProxy<getBackendSessionBySidFunction>;
108
+ getBackendSessionsByUid: RemoterProxy<getBackendSessionsByUidFunction>;
109
+ kickBySid: RemoterProxy<kickBySidFunction>;
110
+ kickByUid: RemoterProxy<kickByUidFunction>;
111
+ }
112
+ };
113
+ }
114
+ }
115
+ /**
116
+ * Application states
117
+ */
118
+ let STATE_INITED = 1; // app has inited
119
+ let STATE_BEFORE_START = 2; // app before start
120
+ let STATE_START = 3; // app start
121
+ let STATE_STARTED = 4; // app has started
122
+ let STATE_STOPED = 5; // app has stoped
123
+
124
+ export class Application {
125
+
126
+ loaded: IComponent[] = []; // loaded component list
127
+ components: {
128
+ __backendSession__?: BackendSessionComponent,
129
+ __channel__?: ChannelComponent,
130
+ __connection__?: ConnectionComponent,
131
+ __connector__?: ConnectorComponent,
132
+ __dictionary__?: DictionaryComponent,
133
+ __master__?: MasterComponent,
134
+ __monitor__?: MonitorComponent,
135
+ __protobuf__?: ProtobufComponent,
136
+ __proxy__?: ProxyComponent,
137
+ __remote__?: RemoteComponent,
138
+ __server__?: ServerComponent,
139
+ __session__?: SessionComponent,
140
+ __pushScheduler__?: PushSchedulerComponent,
141
+ [key: string]: IComponent
142
+ } = {}; // name -> component map
143
+
144
+ sessionService ?: SessionService;
145
+ backendSessionService ?: BackendSessionService;
146
+ channelService ?: ChannelService;
147
+
148
+ settings: { [key: string]: any } = {}; // collection keep set/get
149
+ event = new EventEmitter(); // event object to sub/pub events
150
+
151
+ // current server info
152
+ serverId: string; // current server id
153
+ serverType: string; // current server type
154
+ curServer: ServerInfo; // current server info
155
+ startTime: number; // current server start time
156
+
157
+ // global server infos
158
+ master: ServerStartArgs = null; // master server info
159
+ servers: { [id: string]: ServerInfo } = {}; // current global server info maps, id -> info
160
+ serverTypeMaps: { [type: string]: ServerInfo[] } = {}; // current global type maps, type -> [info]
161
+ serverTypes: string[] = []; // current global server type list
162
+ usedPlugins: IPlugin[] = []; // current server custom lifecycle callbacks
163
+ clusterSeq: { [serverType: string]: number } = {}; // cluster id seqence
164
+ state: number;
165
+ base: string;
166
+
167
+ startId: string;
168
+ type: string;
169
+ stopTimer: any;
170
+
171
+ /**
172
+ * Initialize the server.
173
+ *
174
+ * - setup default configuration
175
+ */
176
+ init(opts ?: ApplicationOptions) {
177
+ opts = opts || {};
178
+ let base = opts.base || path.dirname(require.main.filename);
179
+ this.set(Constants.RESERVED.BASE, base);
180
+ this.base = base;
181
+
182
+ appUtil.defaultConfiguration(this);
183
+
184
+ this.state = STATE_INITED;
185
+ logger.info('application inited: %j', this.getServerId());
186
+ }
187
+
188
+ /**
189
+ * Get application base path
190
+ *
191
+ * // cwd: /home/game/
192
+ * melo start
193
+ * // app.getBase() -> /home/game
194
+ *
195
+ * @return {String} application base path
196
+ *
197
+ * @memberOf Application
198
+ */
199
+ getBase() {
200
+ return this.get(Constants.RESERVED.BASE);
201
+ }
202
+
203
+ /**
204
+ * Override require method in application
205
+ *
206
+ * @param {String} relative path of file
207
+ *
208
+ * @memberOf Application
209
+ */
210
+ require(ph: string) {
211
+ return require(path.join(this.getBase(), ph));
212
+ }
213
+
214
+ /**
215
+ * Configure logger with {$base}/config/log4js.json
216
+ *
217
+ * @param {Object} logger melo-logger instance without configuration
218
+ *
219
+ * @memberOf Application
220
+ */
221
+ configureLogger(logger: ILogger) {
222
+ if (process.env.POMELO_LOGGER !== 'off') {
223
+ let serverId = this.getServerId();
224
+ let base = this.getBase();
225
+ let env = this.get(Constants.RESERVED.ENV);
226
+ let originPath = path.join(base, Constants.FILEPATH.LOG);
227
+ let presentPath = path.join(base, Constants.FILEPATH.CONFIG_DIR, env, path.basename(Constants.FILEPATH.LOG));
228
+ if (this._checkCanRequire(originPath)) {
229
+ logger.configure(originPath, { serverId: serverId, base: base });
230
+ } else if (this._checkCanRequire(presentPath)) {
231
+ logger.configure(presentPath, { serverId: serverId, base: base });
232
+ } else {
233
+ console.error('logger file path configuration is error.');
234
+ }
235
+ }
236
+ }
237
+
238
+ /**
239
+ * add a filter to before and after filter
240
+ *
241
+ * @param {Object} filter provide before and after filter method.
242
+ * A filter should have two methods: before and after.
243
+ * @memberOf Application
244
+ */
245
+ filter(filter: IHandlerFilter): void {
246
+ this.before(filter);
247
+ this.after(filter);
248
+ }
249
+
250
+ /**
251
+ * Add before filter.
252
+ *
253
+ * @param {Object|Function} bf before fileter, bf(msg, session, next)
254
+ * @memberOf Application
255
+ */
256
+ before(bf: BeforeHandlerFilter): void {
257
+ addFilter(this, Constants.KEYWORDS.BEFORE_FILTER, bf);
258
+ }
259
+
260
+ /**
261
+ * Add after filter.
262
+ *
263
+ * @param {Object|Function} af after filter, `af(err, msg, session, resp, next)`
264
+ * @memberOf Application
265
+ */
266
+ after(af: AfterHandlerFilter): void {
267
+ addFilter(this, Constants.KEYWORDS.AFTER_FILTER, af);
268
+ }
269
+
270
+ /**
271
+ * add a global filter to before and after global filter
272
+ *
273
+ * @param {Object} filter provide before and after filter method.
274
+ * A filter should have two methods: before and after.
275
+ * @memberOf Application
276
+ */
277
+ globalFilter(filter: IHandlerFilter) {
278
+ this.globalBefore(filter);
279
+ this.globalAfter(filter);
280
+ }
281
+
282
+ /**
283
+ * Add global before filter.
284
+ *
285
+ * @param {Object|Function} bf before fileter, bf(msg, session, next)
286
+ * @memberOf Application
287
+ */
288
+ globalBefore(bf: BeforeHandlerFilter) {
289
+ addFilter(this, Constants.KEYWORDS.GLOBAL_BEFORE_FILTER, bf);
290
+ }
291
+
292
+ /**
293
+ * Add global after filter.
294
+ *
295
+ * @param {Object|Function} af after filter, `af(err, msg, session, resp, next)`
296
+ * @memberOf Application
297
+ */
298
+ globalAfter(af: AfterHandlerFilter) {
299
+ addFilter(this, Constants.KEYWORDS.GLOBAL_AFTER_FILTER, af);
300
+ }
301
+
302
+ /**
303
+ * Add rpc before filter.
304
+ *
305
+ * @param {Object|Function} bf before fileter, bf(serverId, msg, opts, next)
306
+ * @memberOf Application
307
+ */
308
+ rpcBefore(bf: RpcFilter | RpcFilter[]) {
309
+ addFilter(this, Constants.KEYWORDS.RPC_BEFORE_FILTER, bf);
310
+ }
311
+
312
+ /**
313
+ * Add rpc after filter.
314
+ *
315
+ * @param {Object|Function} af after filter, `af(serverId, msg, opts, next)`
316
+ * @memberOf Application
317
+ */
318
+ rpcAfter(af: RpcFilter | RpcFilter[]) {
319
+ addFilter(this, Constants.KEYWORDS.RPC_AFTER_FILTER, af);
320
+ }
321
+
322
+ /**
323
+ * add a rpc filter to before and after rpc filter
324
+ *
325
+ * @param {Object} filter provide before and after filter method.
326
+ * A filter should have two methods: before and after.
327
+ * @memberOf Application
328
+ */
329
+ rpcFilter(filter: RpcFilter) {
330
+ this.rpcBefore(filter);
331
+ this.rpcAfter(filter);
332
+ }
333
+
334
+ /**
335
+ * Load component
336
+ *
337
+ * @param {String} name (optional) name of the component
338
+ * @param {Object} component component instance or factory function of the component
339
+ * @param {[type]} opts (optional) construct parameters for the factory function
340
+ * @return {Object} app instance for chain invoke
341
+ * @memberOf Application
342
+ */
343
+ load<T extends IComponent>(component: ObjectType<T>, opts ?: any): T;
344
+ load<T extends IComponent>(name: string, component: ObjectType<T>, opts ?: any): T;
345
+
346
+ load<T extends IComponent>(component: T, opts ?: any): T;
347
+ load<T extends IComponent>(name: string, component: T, opts ?: any): T;
348
+
349
+ load<T extends IComponent>(name: string | ObjectType<T>, component ?: ObjectType<T> | any | T, opts ?: any): T {
350
+ if (typeof name !== 'string') {
351
+ opts = component;
352
+ component = name;
353
+ name = null;
354
+ }
355
+
356
+ if (typeof component === 'function') {
357
+ component = new component(this, opts);
358
+ }
359
+
360
+ if (!name && typeof component.name === 'string') {
361
+ name = component.name;
362
+ }
363
+
364
+ if (name && this.components[name as string]) {
365
+ // ignore duplicat component
366
+ logger.warn('ignore duplicate component: %j', name);
367
+ return;
368
+ }
369
+
370
+ this.loaded.push(component);
371
+ if (name) {
372
+ // components with a name would get by name throught app.components later.
373
+ this.components[name as string] = component;
374
+ }
375
+
376
+ return component;
377
+ }
378
+
379
+ _checkCanRequire(path: string) {
380
+ try {
381
+ path = require.resolve(path);
382
+ } catch (err) {
383
+ return null;
384
+ }
385
+ return path;
386
+ }
387
+
388
+ /**
389
+ * Load Configure json file to settings.(support different enviroment directory & compatible for old path)
390
+ *
391
+ * @param {String} key environment key
392
+ * @param {String} val environment value
393
+ * @param {Boolean} reload whether reload after change default false
394
+ * @return {Server|Mixed} for chaining, or the setting value
395
+ * @memberOf Application
396
+ */
397
+ loadConfigBaseApp(key: string, val: string, reload = false) {
398
+ let self = this;
399
+ let env = this.get(Constants.RESERVED.ENV);
400
+ let originPath = path.join(this.getBase(), val);
401
+ let presentPath = path.join(this.getBase(), Constants.FILEPATH.CONFIG_DIR, env, path.basename(val));
402
+ let realPath: string;
403
+ let tmp: string;
404
+ if (self._checkCanRequire(originPath)) {
405
+ realPath = require.resolve(originPath);
406
+ let file = require(originPath);
407
+ if (file[env]) {
408
+ file = file[env];
409
+ }
410
+ this.set(key, file);
411
+ } else if (self._checkCanRequire(presentPath)) {
412
+ realPath = require.resolve(presentPath);
413
+ let pfile = require(presentPath);
414
+ this.set(key, pfile);
415
+ } else {
416
+ logger.error('invalid configuration with file path: %s', key);
417
+ }
418
+
419
+ if (!!realPath && !!reload) {
420
+ const watcher = fs.watch(realPath, function (event, filename) {
421
+ if (event === 'change') {
422
+ self.clearRequireCache(require.resolve(realPath));
423
+ watcher.close();
424
+ self.loadConfigBaseApp(key, val, reload);
425
+
426
+ }
427
+ });
428
+ }
429
+ }
430
+
431
+ clearRequireCache(path: string) {
432
+ const moduleObj = require.cache[path];
433
+ if (!moduleObj) {
434
+ logger.warn('can not find module of truepath', path);
435
+ return;
436
+ }
437
+ if (moduleObj.parent) {
438
+ // console.log('has parent ',moduleObj.parent);
439
+ moduleObj.parent.children.splice(moduleObj.parent.children.indexOf(moduleObj), 1);
440
+ }
441
+ delete require.cache[path];
442
+ }
443
+
444
+ /**
445
+ * Load Configure json file to settings.
446
+ *
447
+ * @param {String} key environment key
448
+ * @param {String} val environment value
449
+ * @return {Server|Mixed} for chaining, or the setting value
450
+ * @memberOf Application
451
+ */
452
+ loadConfig(key: string, val: string) {
453
+ let env = this.get(Constants.RESERVED.ENV);
454
+ let cfg = require(val);
455
+ if (cfg[env]) {
456
+ cfg = cfg[env];
457
+ }
458
+ this.set(key, cfg);
459
+ }
460
+
461
+ /**
462
+ * Set the route function for the specified server type.
463
+ *
464
+ * Examples:
465
+ *
466
+ * app.route('area', routeFunc);
467
+ *
468
+ * let routeFunc = function(session, msg, app, cb) {
469
+ * // all request to area would be route to the first area server
470
+ * let areas = app.getServersByType('area');
471
+ * cb(null, areas[0].id);
472
+ * };
473
+ *
474
+ * @param {String} serverType server type string
475
+ * @param {Function} routeFunc route function. routeFunc(session, msg, app, cb)
476
+ * @return {Object} current application instance for chain invoking
477
+ * @memberOf Application
478
+ */
479
+ route(serverType: string, routeFunc: RouteFunction) {
480
+ let routes = this.get(Constants.KEYWORDS.ROUTE);
481
+ if (!routes) {
482
+ routes = {};
483
+ this.set(Constants.KEYWORDS.ROUTE, routes);
484
+ }
485
+ routes[serverType] = routeFunc;
486
+ return this;
487
+ }
488
+
489
+ /**
490
+ * Set before stop function. It would perform before servers stop.
491
+ *
492
+ * @param {Function} fun before close function
493
+ * @return {Void}
494
+ * @memberOf Application
495
+ */
496
+ beforeStopHook(fun: BeforeStopHookFunction) {
497
+ logger.warn('this method was deprecated in melo 0.8');
498
+ if (!!fun && typeof fun === 'function') {
499
+ this.set(Constants.KEYWORDS.BEFORE_STOP_HOOK, fun);
500
+ }
501
+ }
502
+
503
+ /**
504
+ * Start application. It would load the default components and start all the loaded components.
505
+ *
506
+ * @param {Function} cb callback function
507
+ * @memberOf Application
508
+ */
509
+ start(cb ?: (err ?: Error, result ?: void) => void) {
510
+ this.startTime = Date.now();
511
+ if (this.state > STATE_INITED) {
512
+ utils.invokeCallback(cb, new Error('application has already start.'));
513
+ return;
514
+ }
515
+
516
+ let self = this;
517
+ appUtil.startByType(self, function () {
518
+ appUtil.loadDefaultComponents(self);
519
+ let startUp = function () {
520
+ self.state = STATE_BEFORE_START;
521
+ logger.info('%j enter before start...', self.getServerId());
522
+
523
+ appUtil.optComponents(self.loaded, Constants.RESERVED.BEFORE_START, function (err) {
524
+ if (err) {
525
+ utils.invokeCallback(cb, err);
526
+ } else {
527
+ logger.info('%j enter start...', self.getServerId());
528
+
529
+ appUtil.optComponents(self.loaded, Constants.RESERVED.START, function (err) {
530
+ self.state = STATE_START;
531
+ if (err) {
532
+ utils.invokeCallback(cb, err);
533
+ } else {
534
+ logger.info('%j enter after start...', self.getServerId());
535
+ self.afterStart(cb);
536
+ }
537
+ });
538
+ }
539
+ });
540
+
541
+ };
542
+
543
+ appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.BEFORE_STARTUP, self, function (err) {
544
+ if (err) {
545
+ utils.invokeCallback(cb, err);
546
+ } else {
547
+ startUp();
548
+ }
549
+ });
550
+ });
551
+ }
552
+
553
+ /**
554
+ * Lifecycle callback for after start.
555
+ *
556
+ * @param {Function} cb callback function
557
+ * @return {Void}
558
+ */
559
+ afterStart(cb ?: (err?: Error) => void) {
560
+ if (this.state !== STATE_START) {
561
+ utils.invokeCallback(cb, new Error('application is not running now.'));
562
+ return;
563
+ }
564
+
565
+ let self = this;
566
+ appUtil.optComponents(this.loaded, Constants.RESERVED.AFTER_START, function (err) {
567
+ self.state = STATE_STARTED;
568
+ let id = self.getServerId();
569
+ if (!err) {
570
+ logger.info('%j finish start', id);
571
+ }
572
+ appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.AFTER_STARTUP, self, function (err?: Error) {
573
+ let usedTime = Date.now() - self.startTime;
574
+ logger.info('%j startup in %s ms', id, usedTime);
575
+ self.event.emit(events.START_SERVER, id);
576
+ cb && cb(err);
577
+ });
578
+ });
579
+ }
580
+
581
+ /**
582
+ * Stop components.
583
+ *
584
+ * @param {Boolean} force whether stop the app immediately
585
+ */
586
+ stop(force: boolean) {
587
+ if (this.state > STATE_STARTED) {
588
+ logger.warn('[melo application] application is not running now.');
589
+ return;
590
+ }
591
+ this.state = STATE_STOPED;
592
+ let self = this;
593
+
594
+ this.stopTimer = setTimeout(function () {
595
+ process.exit(0);
596
+ }, Constants.TIME.TIME_WAIT_STOP);
597
+
598
+ let cancelShutDownTimer = function () {
599
+ if (!!self.stopTimer) {
600
+ clearTimeout(self.stopTimer);
601
+ }
602
+ };
603
+ let shutDown = function () {
604
+ appUtil.stopComps(self.loaded, 0, force, function () {
605
+ cancelShutDownTimer();
606
+ if (force) {
607
+ process.exit(0);
608
+ }
609
+ });
610
+ };
611
+ let fun = this.get(Constants.KEYWORDS.BEFORE_STOP_HOOK);
612
+
613
+ appUtil.optLifecycles(self.usedPlugins, Constants.LIFECYCLE.BEFORE_SHUTDOWN, self, function (err) {
614
+ if (err) {
615
+ console.error(`throw err when beforeShutdown `, err.stack);
616
+ } else {
617
+ if (!!fun) {
618
+ utils.invokeCallback(fun, self, shutDown, cancelShutDownTimer);
619
+ } else {
620
+ shutDown();
621
+ }
622
+ }
623
+ }, cancelShutDownTimer);
624
+ }
625
+
626
+ /**
627
+ * Assign `setting` to `val`, or return `setting`'s value.
628
+ *
629
+ * Example:
630
+ *
631
+ * app.set('key1', 'value1');
632
+ * app.get('key1'); // 'value1'
633
+ * app.key1; // undefined
634
+ *
635
+ * app.set('key2', 'value2', true);
636
+ * app.get('key2'); // 'value2'
637
+ * app.key2; // 'value2'
638
+ *
639
+ * @param {String} setting the setting of application
640
+ * @param {String} val the setting's value
641
+ * @param {Boolean} attach whether attach the settings to application
642
+ * @return {Server|Mixed} for chaining, or the setting value
643
+ * @memberOf Application
644
+ */
645
+ set(setting: 'channelService', val: ChannelService, attach?: boolean): Application;
646
+ set(setting: 'sessionService', val: SessionService, attach?: boolean): Application;
647
+ set(setting: 'channelConfig', val: ChannelServiceOptions, attach?: boolean): Application;
648
+ set(setting: 'backendSessionService', val: BackendSessionComponent, attach?: boolean): Application;
649
+ set(setting: 'protobufConfig', val: ProtobufComponentOptions, attach?: boolean): Application;
650
+ set(setting: 'connectorConfig', val: ConnectorComponentOptions, attach?: boolean): Application;
651
+ set(setting: 'remoteConfig', val: RemoteComponentOptions, attach?: boolean): Application;
652
+ set(setting: 'monitorConfig', val: MonitorOptions, attach?: boolean): Application;
653
+ set(setting: 'proxyConfig', val: ProxyComponentOptions, attach?: boolean): Application;
654
+ set(setting: Constants.KEYWORDS.BEFORE_FILTER, val: BeforeHandlerFilter[], attach?: boolean): Application;
655
+ set(setting: Constants.KEYWORDS.AFTER_FILTER, val: AfterHandlerFilter[], attach?: boolean): Application;
656
+ set(setting: Constants.KEYWORDS.GLOBAL_BEFORE_FILTER, val: BeforeHandlerFilter[], attach?: boolean): Application;
657
+ set(setting: Constants.KEYWORDS.GLOBAL_AFTER_FILTER, val: AfterHandlerFilter[], attach?: boolean): Application;
658
+ set(setting: Constants.KEYWORDS.RPC_BEFORE_FILTER, val: RpcFilter | RpcFilter[], attach?: boolean): Application;
659
+ set(setting: Constants.KEYWORDS.RPC_AFTER_FILTER, val: RpcFilter | RpcFilter[], attach?: boolean): Application;
660
+ set(setting: Constants.RESERVED.RPC_ERROR_HANDLER, val: MailStationErrorHandler, attach?: boolean): Application;
661
+ set(setting: Constants.KEYWORDS.ROUTE, val: RouteMaps, attach?: boolean): Application;
662
+ set(setting: Constants.KEYWORDS.BEFORE_STOP_HOOK, val: BeforeStopHookFunction, attach?: boolean): Application;
663
+ set(setting: Constants.RESERVED.BASE, val: string, attach?: boolean): Application;
664
+ set(setting: Constants.RESERVED.ENV, val: string, attach?: boolean): Application;
665
+ set(setting: Constants.RESERVED.GLOBAL_ERROR_HANDLER, val: ResponseErrorHandler, attach?: boolean): Application;
666
+ set(setting: Constants.RESERVED.ERROR_HANDLER, val: ResponseErrorHandler, attach?: boolean): Application;
667
+ set(setting: Constants.KEYWORDS.MODULE, val: { [key: string]: ModuleRecord }, attach?: boolean): Application;
668
+ set(setting: string, val: string | any, attach?: boolean): Application;
669
+ set(setting: string, val: string | any, attach?: boolean): Application {
670
+ this.settings[setting] = val;
671
+ if (attach) {
672
+ (this as any)[setting] = val;
673
+ }
674
+ return this;
675
+ }
676
+
677
+ /**
678
+ * Get property from setting
679
+ *
680
+ * @param {String} setting application setting
681
+ * @return {String} val
682
+ * @memberOf Application
683
+ */
684
+ get(setting: 'channelService'): ChannelService;
685
+ get(setting: 'sessionService'): SessionService;
686
+ get(setting: 'channelConfig'): ChannelServiceOptions;
687
+ get(setting: 'remoteConfig'): RemoteComponentOptions;
688
+ get(setting: 'backendSessionService'): BackendSessionComponent;
689
+ get(setting: Constants.KEYWORDS.BEFORE_FILTER): BeforeHandlerFilter[];
690
+ get(setting: Constants.KEYWORDS.AFTER_FILTER): AfterHandlerFilter[];
691
+ get(setting: Constants.KEYWORDS.GLOBAL_BEFORE_FILTER): BeforeHandlerFilter[];
692
+ get(setting: Constants.KEYWORDS.GLOBAL_AFTER_FILTER): AfterHandlerFilter[];
693
+ get(setting: Constants.KEYWORDS.RPC_BEFORE_FILTER): RpcFilter | RpcFilter[];
694
+ get(setting: Constants.KEYWORDS.RPC_AFTER_FILTER): RpcFilter | RpcFilter[];
695
+ get(setting: Constants.RESERVED.RPC_ERROR_HANDLER): MailStationErrorHandler;
696
+ get(setting: Constants.KEYWORDS.ROUTE): RouteMaps;
697
+ get(setting: Constants.KEYWORDS.BEFORE_STOP_HOOK): BeforeStopHookFunction;
698
+ get(setting: Constants.RESERVED.BASE): string;
699
+ get(setting: Constants.RESERVED.ENV): string;
700
+ get(setting: Constants.RESERVED.GLOBAL_ERROR_HANDLER): ResponseErrorHandler;
701
+ get(setting: Constants.RESERVED.ERROR_HANDLER): ResponseErrorHandler;
702
+ get(setting: Constants.KEYWORDS.MODULE): { [key: string]: ModuleRecord };
703
+ get(setting: string): string | any;
704
+ get(setting: string): string | any {
705
+ return this.settings[setting];
706
+ }
707
+
708
+ /**
709
+ * Check if `setting` is enabled.
710
+ *
711
+ * @param {String} setting application setting
712
+ * @return {Boolean}
713
+ * @memberOf Application
714
+ */
715
+ enabled(setting: string) {
716
+ return !!this.get(setting);
717
+ }
718
+
719
+ /**
720
+ * Check if `setting` is disabled.
721
+ *
722
+ * @param {String} setting application setting
723
+ * @return {Boolean}
724
+ * @memberOf Application
725
+ */
726
+ disabled(setting: string) {
727
+ return !this.get(setting);
728
+ }
729
+
730
+ /**
731
+ * Enable `setting`.
732
+ *
733
+ * @param {String} setting application setting
734
+ * @return {app} for chaining
735
+ * @memberOf Application
736
+ */
737
+ enable(setting: string) {
738
+ return this.set(setting, true);
739
+ }
740
+
741
+ /**
742
+ * Disable `setting`.
743
+ *
744
+ * @param {String} setting application setting
745
+ * @return {app} for chaining
746
+ * @memberOf Application
747
+ */
748
+ disable(setting: string) {
749
+ return this.set(setting, false);
750
+ }
751
+
752
+ /**
753
+ * Configure callback for the specified env and server type.
754
+ * When no env is specified that callback will
755
+ * be invoked for all environments and when no type is specified
756
+ * that callback will be invoked for all server types.
757
+ *
758
+ * Examples:
759
+ *
760
+ * app.configure(function(){
761
+ * // executed for all envs and server types
762
+ * });
763
+ *
764
+ * app.configure('development', function(){
765
+ * // executed development env
766
+ * });
767
+ *
768
+ * app.configure('development', 'connector', function(){
769
+ * // executed for development env and connector server type
770
+ * });
771
+ *
772
+ * @param {String} env application environment
773
+ * @param {Function} fn callback function
774
+ * @param {String} type server type
775
+ * @return {Application} for chaining
776
+ * @memberOf Application
777
+ */
778
+
779
+ configure(fn: ConfigureCallback): Application;
780
+ configure(env: string, fn: ConfigureCallback): Application;
781
+ configure(env: string, type: string, fn: ConfigureCallback): Application;
782
+ configure(env: string | ConfigureCallback, type ?: string | ConfigureCallback, fn ?: ConfigureCallback): Application {
783
+ let args = [].slice.call(arguments);
784
+ fn = args.pop();
785
+ env = type = Constants.RESERVED.ALL;
786
+
787
+ if (args.length > 0) {
788
+ env = args[0];
789
+ }
790
+ if (args.length > 1) {
791
+ type = args[1];
792
+ }
793
+
794
+ if (env === Constants.RESERVED.ALL || contains(this.settings.env, env as string)) {
795
+ if (type === Constants.RESERVED.ALL || contains(this.settings.serverType, type as string)) {
796
+ fn.call(this);
797
+ }
798
+ }
799
+ return this;
800
+ }
801
+
802
+ /**
803
+ * Register admin modules. Admin modules is the extends point of the monitor system.
804
+ *
805
+ * @param {String} module (optional) module id or provoided by module.moduleId
806
+ * @param {Object} module module object or factory function for module
807
+ * @param {Object} opts construct parameter for module
808
+ * @memberOf Application
809
+ */
810
+ registerAdmin(module: IModule, opts ?: any): void;
811
+ registerAdmin(moduleId: string, module ?: IModule, opts ?: any): void;
812
+
813
+
814
+ registerAdmin(module: IModuleFactory, opts ?: any): void;
815
+ registerAdmin(moduleId: string, module ?: IModuleFactory, opts ?: any): void;
816
+
817
+ registerAdmin(moduleId: string | IModule | IModuleFactory, module ?: IModule | IModuleFactory, opts ?: any) {
818
+ let modules = this.get(Constants.KEYWORDS.MODULE);
819
+ if (!modules) {
820
+ modules = {};
821
+ this.set(Constants.KEYWORDS.MODULE, modules);
822
+ }
823
+
824
+ if (typeof moduleId !== 'string') {
825
+ opts = module;
826
+ module = moduleId;
827
+ if (module) {
828
+ moduleId = ((module as IModuleFactory).moduleId);
829
+ if (!moduleId)
830
+ moduleId = (module as IModule).constructor.name;
831
+ }
832
+ }
833
+
834
+ if (!moduleId) {
835
+ return;
836
+ }
837
+
838
+ modules[moduleId as string] = {
839
+ moduleId: moduleId as string,
840
+ module: module,
841
+ opts: opts
842
+ };
843
+ }
844
+
845
+ /**
846
+ * Use plugin.
847
+ *
848
+ * @param {Object} plugin plugin instance
849
+ * @param {[type]} opts (optional) construct parameters for the factory function
850
+ * @memberOf Application
851
+ */
852
+ use(plugin: IPlugin, opts ?: any) {
853
+ opts = opts || {};
854
+ if (!plugin) {
855
+ throw new Error(`pluin is null!]`);
856
+ }
857
+ if (this.usedPlugins.indexOf(plugin) >= 0) {
858
+ throw new Error(`pluin[${ plugin.name } was used already!]`);
859
+ }
860
+
861
+ if (plugin.components) {
862
+ for (let componentCtor of plugin.components) {
863
+ this.load(componentCtor, opts);
864
+ }
865
+ }
866
+ if (plugin.events) {
867
+ for (let eventCtor of plugin.events) {
868
+ this.loadEvent(eventCtor, opts);
869
+ }
870
+ }
871
+
872
+ this.usedPlugins.push(plugin);
873
+
874
+ console.warn(`used Plugin : ${ plugin.name }`);
875
+ }
876
+
877
+ /**
878
+ * Application transaction. Transcation includes conditions and handlers, if conditions are satisfied, handlers would be executed.
879
+ * And you can set retry times to execute handlers. The transaction log is in file logs/transaction.log.
880
+ *
881
+ * @param {String} name transaction name
882
+ * @param {Object} conditions functions which are called before transaction
883
+ * @param {Object} handlers functions which are called during transaction
884
+ * @param {Number} retry retry times to execute handlers if conditions are successfully executed
885
+ * @memberOf Application
886
+ */
887
+ transaction(name: string, conditions: { [key: string]: TransactionCondictionFunction }, handlers: { [key: string]: TransactionHandlerFunction }, retry?: number) {
888
+ appManager.transaction(name, conditions, handlers, retry);
889
+ }
890
+
891
+ /**
892
+ * Get master server info.
893
+ *
894
+ * @return {Object} master server info, {id, host, port}
895
+ * @memberOf Application
896
+ */
897
+ getMaster() {
898
+ return this.master;
899
+ }
900
+
901
+ /**
902
+ * Get current server info.
903
+ *
904
+ * @return {Object} current server info, {id, serverType, host, port}
905
+ * @memberOf Application
906
+ */
907
+ getCurServer() {
908
+ return this.curServer;
909
+ }
910
+
911
+ /**
912
+ * Get current server id.
913
+ *
914
+ * @return {String|Number} current server id from servers.json
915
+ * @memberOf Application
916
+ */
917
+ getServerId() {
918
+ return this.serverId;
919
+ }
920
+
921
+ /**
922
+ * Get current server
923
+ * @returns ServerInfo
924
+ */
925
+ getCurrentServer() {
926
+ return this.curServer;
927
+ }
928
+
929
+ /**
930
+ * Get current server type.
931
+ *
932
+ * @return {String|Number} current server type from servers.json
933
+ * @memberOf Application
934
+ */
935
+ getServerType() {
936
+ return this.serverType;
937
+ }
938
+
939
+ /**
940
+ * Get all the current server infos.
941
+ *
942
+ * @return {Object} server info map, key: server id, value: server info
943
+ * @memberOf Application
944
+ */
945
+ getServers() {
946
+ return this.servers;
947
+ }
948
+
949
+ /**
950
+ * Get all server infos from servers.json.
951
+ *
952
+ * @return {Object} server info map, key: server id, value: server info
953
+ * @memberOf Application
954
+ */
955
+ getServersFromConfig() {
956
+ return this.get(Constants.KEYWORDS.SERVER_MAP);
957
+ }
958
+
959
+ /**
960
+ * Get all the server type.
961
+ *
962
+ * @return {Array} server type list
963
+ * @memberOf Application
964
+ */
965
+ getServerTypes() {
966
+ return this.serverTypes;
967
+ }
968
+
969
+ /**
970
+ * Get server info by server id from current server cluster.
971
+ *
972
+ * @param {String} serverId server id
973
+ * @return {Object} server info or undefined
974
+ * @memberOf Application
975
+ */
976
+ getServerById(serverId: string) {
977
+ return this.servers[serverId];
978
+ }
979
+
980
+ /**
981
+ * Get server info by server id from servers.json.
982
+ *
983
+ * @param {String} serverId server id
984
+ * @return {Object} server info or undefined
985
+ * @memberOf Application
986
+ */
987
+
988
+ getServerFromConfig(serverId: string) {
989
+ return this.get(Constants.KEYWORDS.SERVER_MAP)[serverId];
990
+ }
991
+
992
+ /**
993
+ * Get server infos by server type.
994
+ *
995
+ * @param {String} serverType server type
996
+ * @return {Array} server info list
997
+ * @memberOf Application
998
+ */
999
+ getServersByType(serverType: string) {
1000
+ return this.serverTypeMaps[serverType];
1001
+ }
1002
+
1003
+ /**
1004
+ * Check the server whether is a frontend server
1005
+ *
1006
+ * @param {server} server server info. it would check current server
1007
+ * if server not specified
1008
+ * @return {Boolean}
1009
+ *
1010
+ * @memberOf Application
1011
+ */
1012
+ isFrontend(server ?: any) {
1013
+ server = server || this.getCurServer();
1014
+ return !!server && server.frontend === 'true';
1015
+ }
1016
+
1017
+ /**
1018
+ * Check the server whether is a backend server
1019
+ *
1020
+ * @param {server} server server info. it would check current server
1021
+ * if server not specified
1022
+ * @return {Boolean}
1023
+ * @memberOf Application
1024
+ */
1025
+ isBackend(server: ServerInfo) {
1026
+ server = server || this.getCurServer();
1027
+ return !!server && !server.frontend;
1028
+ }
1029
+
1030
+ /**
1031
+ * Check whether current server is a master server
1032
+ *
1033
+ * @return {Boolean}
1034
+ * @memberOf Application
1035
+ */
1036
+ isMaster() {
1037
+ return this.serverType === Constants.RESERVED.MASTER;
1038
+ }
1039
+
1040
+ /**
1041
+ * Add new server info to current application in runtime.
1042
+ *
1043
+ * @param {Array} servers new server info list
1044
+ * @memberOf Application
1045
+ */
1046
+ addServers(servers: ServerInfo[]) {
1047
+ if (!servers || !servers.length) {
1048
+ return;
1049
+ }
1050
+
1051
+ let item: ServerInfo, slist: ServerInfo[];
1052
+ for (let i = 0, l = servers.length; i < l; i++) {
1053
+ item = servers[i];
1054
+ // update global server map
1055
+ this.servers[item.id] = item;
1056
+
1057
+ // update global server type map
1058
+ slist = this.serverTypeMaps[item.serverType];
1059
+ if (!slist) {
1060
+ this.serverTypeMaps[item.serverType] = slist = [];
1061
+ }
1062
+ replaceServer(slist, item);
1063
+
1064
+ // update global server type list
1065
+ if (this.serverTypes.indexOf(item.serverType) < 0) {
1066
+ this.serverTypes.push(item.serverType);
1067
+ }
1068
+ }
1069
+ this.event.emit(events.ADD_SERVERS, servers);
1070
+ }
1071
+
1072
+ /**
1073
+ * Remove server info from current application at runtime.
1074
+ *
1075
+ * @param {Array} ids server id list
1076
+ * @memberOf Application
1077
+ */
1078
+ removeServers(ids: string[]) {
1079
+ if (!ids || !ids.length) {
1080
+ return;
1081
+ }
1082
+
1083
+ let id, item, slist;
1084
+ for (let i = 0, l = ids.length; i < l; i++) {
1085
+ id = ids[i];
1086
+ item = this.servers[id];
1087
+ if (!item) {
1088
+ continue;
1089
+ }
1090
+ // clean global server map
1091
+ delete this.servers[id];
1092
+
1093
+ // clean global server type map
1094
+ slist = this.serverTypeMaps[item.serverType];
1095
+ removeServer(slist, id);
1096
+ // TODO: should remove the server type if the slist is empty?
1097
+ }
1098
+ this.event.emit(events.REMOVE_SERVERS, ids);
1099
+ }
1100
+
1101
+ /**
1102
+ * Replace server info from current application at runtime.
1103
+ *
1104
+ * @param {Object} server id map
1105
+ * @memberOf Application
1106
+ */
1107
+ replaceServers(servers: { [serverId: string]: ServerInfo }) {
1108
+ if (!servers) {
1109
+ return;
1110
+ }
1111
+
1112
+ this.servers = servers;
1113
+ this.serverTypeMaps = {};
1114
+ this.serverTypes = [];
1115
+ let serverArray = [];
1116
+ for (let id in servers) {
1117
+ let server = servers[id];
1118
+ let serverType = server[Constants.RESERVED.SERVER_TYPE];
1119
+ let slist = this.serverTypeMaps[serverType];
1120
+ if (!slist) {
1121
+ this.serverTypeMaps[serverType] = slist = [];
1122
+ }
1123
+ this.serverTypeMaps[serverType].push(server);
1124
+ // update global server type list
1125
+ if (this.serverTypes.indexOf(serverType) < 0) {
1126
+ this.serverTypes.push(serverType);
1127
+ }
1128
+ serverArray.push(server);
1129
+ }
1130
+ this.event.emit(events.REPLACE_SERVERS, serverArray);
1131
+ }
1132
+
1133
+ /**
1134
+ * Add crons from current application at runtime.
1135
+ *
1136
+ * @param {Array} crons new crons would be added in application
1137
+ * @memberOf Application
1138
+ */
1139
+ addCrons(crons: Cron[]) {
1140
+ if (!crons || !crons.length) {
1141
+ logger.warn('crons is not defined.');
1142
+ return;
1143
+ }
1144
+ this.event.emit(events.ADD_CRONS, crons);
1145
+ }
1146
+
1147
+ /**
1148
+ * Remove crons from current application at runtime.
1149
+ *
1150
+ * @param {Array} crons old crons would be removed in application
1151
+ * @memberOf Application
1152
+ */
1153
+ removeCrons(crons: Cron[]) {
1154
+ if (!crons || !crons.length) {
1155
+ logger.warn('ids is not defined.');
1156
+ return;
1157
+ }
1158
+ this.event.emit(events.REMOVE_CRONS, crons);
1159
+ }
1160
+
1161
+ astart = utils.promisify(this.start);
1162
+ aconfigure: AConfigureFunc1 | AConfigureFunc2 | AConfigureFunc3 = utils.promisify(this.configure) as any;
1163
+
1164
+ rpc ?: UserRpc;
1165
+ sysrpc ?: SysRpc;
1166
+
1167
+ /**
1168
+ * Proxy for rpc client rpcInvoke.
1169
+ *
1170
+ * @param {String} serverId remote server id
1171
+ * @param {Object} msg rpc message: {serverType: serverType, service: serviceName, method: methodName, args: arguments}
1172
+ * @param {Function} cb callback function
1173
+ */
1174
+ rpcInvoke ?: (serverId: FRONTENDID, msg: RpcMsg, cb: Function) => void;
1175
+
1176
+
1177
+ /**
1178
+ * 加载一个事件侦听
1179
+ * @param Event
1180
+ * @param opts
1181
+ */
1182
+ loadEvent(Event: ApplicationEventContructor, opts: any) {
1183
+ let eventInstance = new Event(opts);
1184
+
1185
+ for (let evt in AppEvents) {
1186
+ let name = (AppEvents as any)[evt];
1187
+ let method = (eventInstance as any)[name];
1188
+ if (method) {
1189
+ this.event.on(name, method.bind(eventInstance));
1190
+ }
1191
+ }
1192
+ }
1193
+
1194
+ }
1195
+
1196
+ let replaceServer = function (slist: ServerInfo[], serverInfo: ServerInfo) {
1197
+ for (let i = 0, l = slist.length; i < l; i++) {
1198
+ if (slist[i].id === serverInfo.id) {
1199
+ slist[i] = serverInfo;
1200
+ return;
1201
+ }
1202
+ }
1203
+ slist.push(serverInfo);
1204
+ };
1205
+
1206
+ let removeServer = function (slist: ServerInfo[], id: string) {
1207
+ if (!slist || !slist.length) {
1208
+ return;
1209
+ }
1210
+
1211
+ for (let i = 0, l = slist.length; i < l; i++) {
1212
+ if (slist[i].id === id) {
1213
+ slist.splice(i, 1);
1214
+ return;
1215
+ }
1216
+ }
1217
+ };
1218
+
1219
+ let contains = function (str: string, settings: string) {
1220
+ if (!settings) {
1221
+ return false;
1222
+ }
1223
+
1224
+ let ts = settings.split('|');
1225
+ for (let i = 0, l = ts.length; i < l; i++) {
1226
+ if (str === ts[i]) {
1227
+ return true;
1228
+ }
1229
+ }
1230
+ return false;
1231
+ };
1232
+
1233
+ let addFilter = function <T>(app: Application, type: string, filter: T) {
1234
+ let filters = app.get(type);
1235
+ if (!filters) {
1236
+ filters = [];
1237
+ app.set(type, filters);
1238
+ }
1239
+ filters.push(filter);
1240
+ };