@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,41 @@
1
+ /**
2
+ * Component for master.
3
+ */
4
+ import { MasterServer, MasterServerOptions } from '../master/master';
5
+ import { IComponent } from '../interfaces/IComponent';
6
+ import { Application } from '../application';
7
+
8
+ /**
9
+ * Master component class
10
+ *
11
+ * @param {Object} app current application context
12
+ */
13
+ export class MasterComponent implements IComponent {
14
+ name = '__master__';
15
+ master: MasterServer;
16
+ constructor(app: Application, opts: MasterServerOptions) {
17
+ this.master = new MasterServer(app, opts);
18
+ }
19
+
20
+ /**
21
+ * Component lifecycle function
22
+ *
23
+ * @param {Function} cb
24
+ * @return {Void}
25
+ */
26
+ start(cb: (err?: Error) => void) {
27
+ this.master.start(cb);
28
+ }
29
+
30
+ /**
31
+ * Component lifecycle function
32
+ *
33
+ * @param {Boolean} force whether stop the component immediately
34
+ * @param {Function} cb
35
+ * @return {Void}
36
+ */
37
+ stop(force: boolean, cb: (err?: Error) => void) {
38
+ this.master.stop(cb);
39
+ }
40
+
41
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Component for monitor.
3
+ * Load and start monitor client.
4
+ */
5
+ import { Monitor, MonitorOptions } from '../monitor/monitor';
6
+ import { IComponent } from '../interfaces/IComponent';
7
+ import { Application } from '../application';
8
+ import { MasterInfo } from '../index';
9
+
10
+
11
+
12
+ export class MonitorComponent implements IComponent {
13
+ monitor: Monitor;
14
+ constructor(app: Application, opts ?: MonitorOptions) {
15
+ this.monitor = new Monitor(app, opts);
16
+ }
17
+
18
+ name = '__monitor__';
19
+ start(cb: () => void) {
20
+ this.monitor.start(cb);
21
+ }
22
+
23
+ stop(force: boolean, cb: () => void) {
24
+ this.monitor.stop(cb);
25
+ }
26
+
27
+ reconnect(masterInfo: MasterInfo) {
28
+ this.monitor.reconnect(masterInfo);
29
+ }
30
+ }
@@ -0,0 +1,208 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { Protobuf } from '@bigtyphoon/melo-protobuf';
4
+ import * as Constants from '../util/constants';
5
+ import * as crypto from 'crypto';
6
+ import { getLogger } from '@bigtyphoon/melo-logger';
7
+ import { Application } from '../application';
8
+ import { IComponent } from '../interfaces/IComponent';
9
+ import AppEvents from '../util/events';
10
+
11
+ let logger = getLogger('melo', path.basename(__filename));
12
+
13
+ export interface ProtobufComponentOptions {
14
+ serverProtos?: string;
15
+ clientProtos?: string;
16
+ /**
17
+ 指定 melo-protobuf encode使用 buffer缓存大小
18
+ 使用方法 在 connector配置参数
19
+ app.set('protobufConfig', {
20
+ // protobuf Encoder 使用 5m 的缓存 需要保证每个消息不会超过指定的缓存大小,超过了就会抛出异常
21
+ encoderCacheSize: 5 * 1024 * 1024
22
+ });
23
+ 如果缓存大小不够就会有错误日志
24
+ 缓存大小不够 日志示例
25
+ [2020-03-27T10:44:48.752] [ERROR] melo - [chat-server-1 channelService.js] [pushMessage] fail to dispatch msg to serverId: connector-server-1, err:RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 0. Received 1
26
+ at boundsError (internal/buffer.js:53:9)
27
+ at writeU_Int8 (internal/buffer.js:562:5)
28
+ at Buffer.writeUInt8 (internal/buffer.js:569:10)
29
+ at Encoder.writeBytes (F:\develop\gong4-server\logicServer\melo\packages\melo-protobuf\lib\encoder.ts:195:20)
30
+ */
31
+ encoderCacheSize?: number;
32
+ // decode 客户端请求消息时校验消息
33
+ decodeCheckMsg?: boolean;
34
+ }
35
+
36
+
37
+ export class ProtobufComponent implements IComponent {
38
+ app: Application;
39
+
40
+ watchers: { [key: string]: fs.FSWatcher } = {};
41
+ serverProtos: {
42
+ [key: string]: any;
43
+ } = {};
44
+ clientProtos: {
45
+ [key: string]: any;
46
+ } = {};
47
+ version = '';
48
+ serverProtosPath: string;
49
+ clientProtosPath: string;
50
+
51
+ protobuf: Protobuf;
52
+ name = '__protobuf__';
53
+
54
+ _canRequire(path: string): boolean {
55
+ try {
56
+ require.resolve(path);
57
+ } catch (err) {
58
+ return false;
59
+ }
60
+ return true;
61
+ }
62
+
63
+ constructor(app: Application, opts ?: ProtobufComponentOptions) {
64
+ this.app = app;
65
+ opts = opts || {};
66
+ logger.debug('ProtobufComponent options:', opts)
67
+ let env = app.get(Constants.RESERVED.ENV);
68
+ let originServerPath = path.join(app.getBase(), Constants.FILEPATH.SERVER_PROTOS);
69
+ let presentServerPath = path.join(Constants.FILEPATH.CONFIG_DIR, env, path.basename(Constants.FILEPATH.SERVER_PROTOS));
70
+ let originClientPath = path.join(app.getBase(), Constants.FILEPATH.CLIENT_PROTOS);
71
+ let presentClientPath = path.join(Constants.FILEPATH.CONFIG_DIR, env, path.basename(Constants.FILEPATH.CLIENT_PROTOS));
72
+
73
+ this.serverProtosPath = opts.serverProtos || (this._canRequire(originServerPath) ? Constants.FILEPATH.SERVER_PROTOS : presentServerPath);
74
+ this.clientProtosPath = opts.clientProtos || (this._canRequire(originClientPath) ? Constants.FILEPATH.CLIENT_PROTOS : presentClientPath);
75
+
76
+ this.setProtos(Constants.RESERVED.SERVER, path.join(app.getBase(), this.serverProtosPath));
77
+ this.setProtos(Constants.RESERVED.CLIENT, path.join(app.getBase(), this.clientProtosPath));
78
+
79
+ this.protobuf = new Protobuf({
80
+ encoderProtos: this.serverProtos,
81
+ decoderProtos: this.clientProtos,
82
+ encoderCacheSize: opts.encoderCacheSize,
83
+ decodeCheckMsg: opts.decodeCheckMsg,
84
+ });
85
+ }
86
+
87
+
88
+ encode(key: string, msg: any) {
89
+ return this.protobuf.encode(key, msg);
90
+ }
91
+
92
+ encode2Bytes(key: string, msg: any) {
93
+ return this.protobuf.encode2Bytes(key, msg);
94
+ }
95
+
96
+ decode(key: string, msg: any) {
97
+ return this.protobuf.decode(key, msg);
98
+ }
99
+
100
+ getProtos() {
101
+ return {
102
+ server: this.serverProtos,
103
+ client: this.clientProtos,
104
+ version: this.version
105
+ };
106
+ }
107
+
108
+ getVersion() {
109
+ return this.version;
110
+ }
111
+
112
+ // 手动重新加载协议文件。
113
+ public manualReloadProtos() {
114
+ let truePath = path.join(this.app.getBase(), this.serverProtosPath);
115
+ truePath = require.resolve(truePath);
116
+ this.onUpdate(Constants.RESERVED.SERVER, truePath, 'change');
117
+ truePath = path.join(this.app.getBase(), this.clientProtosPath);
118
+ truePath = require.resolve(truePath);
119
+ this.onUpdate(Constants.RESERVED.CLIENT, truePath, 'change');
120
+ }
121
+
122
+ setProtos(type: string, path: string) {
123
+ if (!this._canRequire(path)) {
124
+ return;
125
+ }
126
+ if (type === Constants.RESERVED.SERVER) {
127
+ this.serverProtos = Protobuf.parse(require(path));
128
+ }
129
+
130
+ if (type === Constants.RESERVED.CLIENT) {
131
+ this.clientProtos = Protobuf.parse(require(path));
132
+ }
133
+
134
+ let protoStr = JSON.stringify(this.clientProtos) + JSON.stringify(this.serverProtos);
135
+ this.version = crypto.createHash('md5').update(protoStr).digest('base64');
136
+
137
+ // Watch file
138
+ const truePath = require.resolve(path);
139
+ let watcher = fs.watch(truePath, this.onUpdate.bind(this, type, truePath));
140
+ if (this.watchers[type]) {
141
+ this.watchers[type].close();
142
+ }
143
+ this.watchers[type] = watcher;
144
+ }
145
+
146
+ clearRequireCache(path: string) {
147
+ const moduleObj = require.cache[path];
148
+ if (!moduleObj) {
149
+ logger.warn('can not find module of truepath', path);
150
+ return;
151
+ }
152
+ if (moduleObj.parent) {
153
+ // console.log('has parent ',moduleObj.parent);
154
+ moduleObj.parent.children.splice(moduleObj.parent.children.indexOf(moduleObj), 1);
155
+ }
156
+ delete require.cache[path];
157
+ }
158
+
159
+ onUpdate(type: string, path: string, event: string, filename?: string, errTry?: boolean) {
160
+ if (event !== 'change') {
161
+ return;
162
+ }
163
+
164
+ let self = this;
165
+ this.clearRequireCache(path);
166
+ try {
167
+ let protos = Protobuf.parse(require(path));
168
+ // 预防 git checkout这样的操作导致获得的数据为空的情况
169
+ if (!protos || !Object.keys(protos).length) {
170
+ // retry.
171
+ throw new Error('protos error');
172
+ }
173
+ if (type === Constants.RESERVED.SERVER) {
174
+ this.protobuf.setEncoderProtos(protos);
175
+ self.serverProtos = protos;
176
+ } else {
177
+ this.protobuf.setDecoderProtos(protos);
178
+ self.clientProtos = protos;
179
+ }
180
+
181
+ let protoStr = JSON.stringify(self.clientProtos) + JSON.stringify(self.serverProtos);
182
+ self.version = crypto.createHash('md5').update(protoStr).digest('base64');
183
+ logger.info('change proto file , type : %j, path : %j, version : %j', type, path, self.version);
184
+ // 抛出 proto 变化事件。
185
+ self.app.event.emit(AppEvents.PROTO_CHANGED, type);
186
+ } catch (e) {
187
+ logger.error('change proto file error! path : %j', path, filename, errTry, e);
188
+ if (!errTry) {
189
+ logger.warn('setTimeout,try update proto');
190
+ setTimeout(() => {
191
+ logger.warn('try update proto again');
192
+ this.onUpdate(type, path, event, filename, true);
193
+ }, 3000);
194
+ }
195
+
196
+ }
197
+ this.watchers[type].close();
198
+ this.watchers[type] = fs.watch(path, this.onUpdate.bind(this, type, path));
199
+ }
200
+
201
+ stop(force: boolean, cb: () => void) {
202
+ for (let type in this.watchers) {
203
+ this.watchers[type].close();
204
+ }
205
+ this.watchers = {};
206
+ process.nextTick(cb);
207
+ }
208
+ }
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Component for proxy.
3
+ * Generate proxies for rpc client.
4
+ */
5
+ import * as crc from 'crc';
6
+ import * as utils from '../util/utils';
7
+ import { default as events } from '../util/events';
8
+ import { RpcClient, createClient } from '@bigtyphoon/melo-rpc';
9
+ import * as pathUtil from '../util/pathUtil';
10
+ import * as Constants from '../util/constants';
11
+ import { getLogger } from '@bigtyphoon/melo-logger';
12
+ import { Application } from '../application';
13
+ import { IComponent } from '../interfaces/IComponent';
14
+ import { RpcClientOpts } from '@bigtyphoon/melo-rpc';
15
+ import { ServerInfo } from '../util/constants';
16
+ import { Session } from '../index';
17
+ import * as path from 'path';
18
+
19
+ let logger = getLogger('melo', path.basename(__filename));
20
+
21
+ export interface ProxyComponentOptions extends RpcClientOpts {
22
+ rpcClient?: {
23
+ create: (opts: RpcClientOpts) => RpcClient;
24
+ };
25
+ bufferMsg?: boolean;
26
+ cacheMsg?: boolean;
27
+ interval?: number;
28
+
29
+ enableRpcLog?: boolean;
30
+ }
31
+
32
+ /**
33
+ * Proxy component class
34
+ *
35
+ * @param {Object} app current application context
36
+ * @param {Object} opts construct parameters
37
+ */
38
+ export class ProxyComponent implements IComponent {
39
+ app: Application;
40
+ opts: ProxyComponentOptions;
41
+ client: RpcClient;
42
+
43
+ constructor(app: Application, opts: ProxyComponentOptions) {
44
+ opts = opts || {};
45
+ // proxy default config
46
+ // cacheMsg is deprecated, just for compatibility here.
47
+ opts.bufferMsg = opts.bufferMsg || opts.cacheMsg || false;
48
+ opts.interval = opts.interval || 30;
49
+ opts.router = genRouteFun();
50
+ opts.context = opts.context ?? app;
51
+ opts.routeContext = opts.routeContext ?? app;
52
+ if (app.enabled('rpcDebugLog')) {
53
+ opts.rpcDebugLog = true;
54
+ opts.rpcLogger = getLogger('rpc-debug', path.basename(__filename));
55
+ }
56
+
57
+ this.app = app;
58
+ this.opts = opts;
59
+ this.client = genRpcClient(this.app, opts);
60
+ this.app.event.on(events.ADD_SERVERS, this.addServers.bind(this));
61
+ this.app.event.on(events.REMOVE_SERVERS, this.removeServers.bind(this));
62
+ this.app.event.on(events.REPLACE_SERVERS, this.replaceServers.bind(this));
63
+ }
64
+
65
+ name = '__proxy__';
66
+
67
+ /**
68
+ * Proxy component lifecycle function
69
+ *
70
+ * @param {Function} cb
71
+ * @return {Void}
72
+ */
73
+ start(cb: (err?: Error) => void) {
74
+ if (this.opts.enableRpcLog) {
75
+ logger.warn('enableRpcLog is deprecated in 0.8.0, please use app.rpcFilter(melo.rpcFilters.rpcLog())');
76
+ }
77
+ let rpcBefores = this.app.get(Constants.KEYWORDS.RPC_BEFORE_FILTER);
78
+ let rpcAfters = this.app.get(Constants.KEYWORDS.RPC_AFTER_FILTER);
79
+ let rpcErrorHandler = this.app.get(Constants.RESERVED.RPC_ERROR_HANDLER);
80
+
81
+ if (!!rpcBefores) {
82
+ this.client.before(rpcBefores);
83
+ }
84
+ if (!!rpcAfters) {
85
+ this.client.after(rpcAfters);
86
+ }
87
+ if (!!rpcErrorHandler) {
88
+ this.client.setErrorHandler(rpcErrorHandler);
89
+ }
90
+ process.nextTick(cb);
91
+ }
92
+
93
+ /**
94
+ * Component lifecycle callback
95
+ *
96
+ * @param {Function} cb
97
+ * @return {Void}
98
+ */
99
+ afterStart(cb: (err?: Error) => void) {
100
+ let self = this;
101
+
102
+ Object.defineProperty(this.app, 'rpc', {
103
+ get: function () {
104
+ return self.client.proxies.user;
105
+ }
106
+ });
107
+
108
+ Object.defineProperty(this.app, 'sysrpc', {
109
+ get: function () {
110
+ return self.client.proxies.sys;
111
+ }
112
+ });
113
+ this.app.rpcInvoke = this.client.rpcInvoke.bind(this.client);
114
+
115
+ this.client.start(cb);
116
+ }
117
+
118
+ /**
119
+ * Add remote server to the rpc client.
120
+ *
121
+ * @param {Array} servers server info list, {id, serverType, host, port}
122
+ */
123
+ addServers(servers: ServerInfo[]) {
124
+ if (!servers || !servers.length) {
125
+ return;
126
+ }
127
+
128
+ genProxies(this.client, this.app, servers);
129
+ this.client.addServers(servers);
130
+ }
131
+
132
+ manualReloadProxies() {
133
+ let servers = [];
134
+ for (let k in this.client._station.servers) {
135
+ servers.push(this.client._station.servers[k])
136
+ }
137
+ logger.warn('manualReloadProxies servers:', servers);
138
+ genProxies(this.client, this.app, servers);
139
+ }
140
+
141
+ /**
142
+ * Remove remote server from the rpc client.
143
+ *
144
+ * @param {Array} ids server id list
145
+ */
146
+ removeServers(ids: string[]) {
147
+ this.client.removeServers(ids);
148
+ }
149
+
150
+ /**
151
+ * Replace remote servers from the rpc client.
152
+ *
153
+ * @param {Array} ids server id list
154
+ */
155
+ replaceServers(servers: ServerInfo[]) {
156
+ if (!servers || !servers.length) {
157
+ return;
158
+ }
159
+
160
+ // update proxies
161
+ this.client.proxies = {};
162
+ genProxies(this.client, this.app, servers);
163
+
164
+ this.client.replaceServers(servers);
165
+ }
166
+
167
+ /**
168
+ * Proxy for rpc client rpcInvoke.
169
+ *
170
+ * @param {String} serverId remote server id
171
+ * @param {Object} msg rpc message: {serverType: serverType, service: serviceName, method: methodName, args: arguments}
172
+ * @param {Function} cb callback function
173
+ */
174
+ rpcInvoke(serverId: string, msg: any, cb: (err: Error, ...args: any[]) => void) {
175
+ this.client.rpcInvoke(serverId, msg, cb);
176
+ }
177
+ }
178
+
179
+ export function manualReloadProxies(app: Application) {
180
+ if (!app.components.__proxy__) {
181
+ return;
182
+ }
183
+ if (app.components.__proxy__.manualReloadProxies) {
184
+ app.components.__proxy__.manualReloadProxies();
185
+ } else {
186
+ logger.warn('manualReloadProxies not method');
187
+ }
188
+
189
+ }
190
+
191
+ /**
192
+ * Generate rpc client
193
+ *
194
+ * @param {Object} app current application context
195
+ * @param {Object} opts contructor parameters for rpc client
196
+ * @return {Object} rpc client
197
+ */
198
+ let genRpcClient = function (app: Application, opts: RpcClientOpts & { rpcClient?: { create: (opts: RpcClientOpts) => RpcClient; } }) {
199
+ opts.context = opts.context ?? app;
200
+ opts.routeContext = opts.routeContext ?? app;
201
+ if (!!opts.rpcClient) {
202
+ return opts.rpcClient.create(opts);
203
+ } else {
204
+ return createClient(opts);
205
+ }
206
+ };
207
+
208
+ /**
209
+ * Generate proxy for the server infos.
210
+ *
211
+ * @param {Object} client rpc client instance
212
+ * @param {Object} app application context
213
+ * @param {Array} sinfos server info list
214
+ */
215
+ let genProxies = function (client: RpcClient, app: Application, sinfos: ServerInfo[]) {
216
+ let item;
217
+ for (let i = 0, l = sinfos.length; i < l; i++) {
218
+ item = sinfos[i];
219
+ client.addProxies(getProxyRecords(app, item));
220
+ }
221
+ };
222
+
223
+ /**
224
+ * Check a server whether has generated proxy before
225
+ *
226
+ * @param {Object} client rpc client instance
227
+ * @param {Object} sinfo server info
228
+ * @return {Boolean} true or false
229
+ */
230
+ let hasProxy = function (client: RpcClient, sinfo: ServerInfo) {
231
+ let proxy = client.proxies;
232
+ return !!proxy.sys && !!proxy.sys[sinfo.serverType];
233
+ };
234
+
235
+ /**
236
+ * Get proxy path for rpc client.
237
+ * Iterate all the remote service path and create remote path record.
238
+ *
239
+ * @param {Object} app current application context
240
+ * @param {Object} sinfo server info, format: {id, serverType, host, port}
241
+ * @return {Array} remote path record array
242
+ */
243
+ let getProxyRecords = function (app: Application, sinfo: ServerInfo) {
244
+ return sinfo.remoterPaths;
245
+ };
246
+
247
+ let genRouteFun = function () {
248
+ return function (session: Session, msg: any, app: Application, cb: RouteCallback) {
249
+ let routes = app.get(Constants.KEYWORDS.ROUTE);
250
+
251
+ if (!routes) {
252
+ defaultRoute(session, msg, app, cb);
253
+ return;
254
+ }
255
+
256
+ let type = msg.serverType,
257
+ route = routes[type] || routes['default'];
258
+
259
+ if (route) {
260
+ route(session, msg, app, cb);
261
+ } else {
262
+ defaultRoute(session, msg, app, cb);
263
+ }
264
+ };
265
+ };
266
+
267
+ export type RouteCallback = (err: Error, routeToServerId ?: string) => void;
268
+
269
+ let defaultRoute = function (session: Session, msg: any, app: Application, cb: RouteCallback) {
270
+ let list = app.getServersByType(msg.serverType);
271
+ if (!list || !list.length) {
272
+ cb(new Error('can not find server info for type:' + msg.serverType));
273
+ return;
274
+ }
275
+
276
+ let uid = session ? (session.uid || '') : '';
277
+ let index = Math.abs(crc.crc32(uid.toString())) % list.length;
278
+ utils.invokeCallback(cb, null, list[index].id);
279
+ };
280
+
281
+ export type RouteFunction = (routeFrom: any, msg: any, app: Application, cb: RouteCallback) => void;
282
+ export type RouteMaps = { [key: string]: RouteFunction };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Scheduler component to schedule message sending.
3
+ */
4
+
5
+ import {DirectPushScheduler as DefaultScheduler} from '../pushSchedulers/direct';
6
+ import { getLogger } from '@bigtyphoon/melo-logger';
7
+ import { Application } from '../application';
8
+ import { IComponent } from '../interfaces/IComponent';
9
+ import { IPushScheduler, ScheduleOptions, IPushSchedulerOrCtor, IPushSchedulerOptions, MultiPushSchedulerOptions } from '../interfaces/IPushScheduler';
10
+ import { MultiPushScheduler } from '../pushSchedulers/multi';
11
+ import { SID } from '../util/constants';
12
+ import * as path from 'path';
13
+ let logger = getLogger('melo', path.basename(__filename));
14
+
15
+
16
+ export class PushSchedulerComponent implements IComponent {
17
+ scheduler: IPushScheduler;
18
+ constructor(private app: Application, opts ?: IPushSchedulerOptions) {
19
+ opts = opts || {};
20
+ this.scheduler = getScheduler(this, app, opts);
21
+ }
22
+
23
+ name = '__pushScheduler__';
24
+
25
+ /**
26
+ * Component lifecycle callback
27
+ *
28
+ * @param {Function} cb
29
+ * @return {Void}
30
+ */
31
+ afterStart(cb: () => void) {
32
+ this.scheduler.start().then(cb);
33
+ }
34
+
35
+ /**
36
+ * Component lifecycle callback
37
+ *
38
+ * @param {Function} cb
39
+ * @return {Void}
40
+ */
41
+ stop(force: boolean, cb: () => void) {
42
+ this.scheduler.stop().then(cb);
43
+ }
44
+
45
+ /**
46
+ * Schedule how the message to send.
47
+ *
48
+ * @param {Number} reqId request id
49
+ * @param {String} route route string of the message
50
+ * @param {Object} msg message content after encoded
51
+ * @param {Array} recvs array of receiver's session id
52
+ * @param {Object} opts options
53
+ * @param {Function} cb
54
+ */
55
+ schedule(reqId: number, route: string, msg: any, recvs: SID[], opts: ScheduleOptions, cb: (err?: Error) => void) {
56
+ this.scheduler.schedule(reqId, route, msg, recvs, opts, cb);
57
+ }
58
+ }
59
+ let getScheduler = function (pushSchedulerComp: PushSchedulerComponent, app: Application, opts: IPushSchedulerOptions): IPushScheduler {
60
+ let scheduler = opts.scheduler || DefaultScheduler;
61
+ if (typeof scheduler === 'function') {
62
+ return new scheduler(app, opts);
63
+ }
64
+
65
+ if (Array.isArray(scheduler)) {
66
+ return new MultiPushScheduler(app , opts as MultiPushSchedulerOptions);
67
+ }
68
+
69
+ return scheduler as IPushScheduler;
70
+ };