diff --git a/src/index.ts b/src/index.ts index 0034fe5..44e7e59 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,14 @@ +// AI CORE + import * as WebSocket from 'ws'; import * as request from 'request-promise-native'; -const ReconnectingWebSocket = require('../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js'); - import serifs from './serifs'; import config from './config'; import IModule from './module'; import MessageLike from './message-like'; - import ReversiModule from './modules/reversi'; +import ServerModule from './modules/server'; +const ReconnectingWebSocket = require('../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js'); /** * 藍 @@ -45,6 +46,7 @@ export default class 藍 { } public install = (module: IModule) => { + module.install(this); this.modules.push(module); } @@ -120,6 +122,9 @@ export default class 藍 { const ai = new 藍(); +const serverModule = new ServerModule(); +ai.install(serverModule); + if (config.reversiEnabled) { const reversiModule = new ReversiModule(); ai.install(reversiModule); diff --git a/src/modules/reversi/index.ts b/src/modules/reversi/index.ts index aadf38a..4bf7821 100644 --- a/src/modules/reversi/index.ts +++ b/src/modules/reversi/index.ts @@ -1,12 +1,11 @@ import * as childProcess from 'child_process'; - const ReconnectingWebSocket = require('../../../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js'); - import 藍 from '../..'; import IModule from '../../module'; import serifs from '../../serifs'; import config from '../../config'; import MessageLike from '../../message-like'; +import * as WebSocket from 'ws'; export default class ReversiModule implements IModule { private ai: 藍; @@ -56,7 +55,6 @@ export default class ReversiModule implements IModule { } } - private onReversiConnectionMessage = (msg: any) => { switch (msg.type) { diff --git a/src/modules/server/index.ts b/src/modules/server/index.ts new file mode 100644 index 0000000..93ff02d --- /dev/null +++ b/src/modules/server/index.ts @@ -0,0 +1,81 @@ +import * as childProcess from 'child_process'; +import * as WebSocket from 'ws'; +import 藍 from '../..'; +import IModule from '../../module'; +import serifs from '../../serifs'; +import config from '../../config'; +const ReconnectingWebSocket = require('../../../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js'); + +export default class ServerModule implements IModule { + private ai: 藍; + private connection?: any; + private rebootScheduled = false; + private rebootTimer: any; + private rebootTimerSub: any; + + public install = (ai: 藍) => { + this.ai = ai; + + this.connection = new ReconnectingWebSocket(`${config.wsUrl}/server-stats`, [], { + WebSocket: WebSocket + }); + + this.connection.addEventListener('open', () => { + console.log('server-stats stream opened'); + }); + + this.connection.addEventListener('close', () => { + console.log('server-stats stream closed'); + }); + + this.connection.addEventListener('message', message => { + const msg = JSON.parse(message.data); + + this.onConnectionMessage(msg); + }); + } + + private onConnectionMessage = (msg: any) => { + switch (msg.type) { + + case 'stats': { + this.onStats(msg.body); + break; + } + + default: + break; + } + } + + private onStats = async (stats: any) => { + const memUsage = Math.round((stats.mem.used / stats.mem.total) * 100); + + console.log(`[SERVER] MEM: ${memUsage}%`); + + if (memUsage >= 90) { + this.scheduleReboot(); + } + } + + private scheduleReboot = () => { + if (this.rebootScheduled) return; + + this.rebootScheduled = true; + + this.ai.post({ + text: serifs.REBOOT_SCHEDULED + }); + + this.rebootTimer = setTimeout(() => { + childProcess.exec('forever restartall'); + }, 1000 * 60); + + this.rebootTimerSub = setTimeout(() => { + this.ai.post({ + cw: serifs.REBOOT, + text: serifs.REBOOT_DETAIL + }); + }, 1000 * 50); + } +} diff --git a/src/serifs.ts b/src/serifs.ts index fcb861d..d035b7b 100644 --- a/src/serifs.ts +++ b/src/serifs.ts @@ -7,5 +7,16 @@ export default { /** * リバーシへの誘いを断るとき */ - REVERSI_DECLINE: 'ごめんなさい、今リバーシはするなと言われてます...' + REVERSI_DECLINE: 'ごめんなさい、今リバーシはするなと言われてます...', + + /** + * (メモリが足りないので)再起動の予定が出来たとき + */ + REBOOT_SCHEDULED: 'サーバーの空きメモリが少なくなってきたので、1分後にサーバー再起動しますね!', + + /** + * まもなく再起動されるとき + */ + REBOOT: 'では、まもなくサーバーを再起動します!', + REBOOT_DETAIL: '(私も再起動に巻き込まれちゃうので、サーバーの再起動が完了したことのお知らせはできません...)' };