diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 5cafd99..c02b9ee 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -1,6 +1,8 @@ const WebSocket = require ('ws'); const _ = require('lodash'); +const WorkerState = require('../core/WorkerState');//singleton +const WebWorker = require('../core/WebWorker');//singleton const log = new (require('../core/AppLogger'))().log;//singleton //const utils = require('../core/utils'); @@ -12,6 +14,9 @@ class WebSocketController { this.config = config; this.isDevelopment = (config.branch == 'development'); + this.workerState = new WorkerState(); + this.webWorker = new WebWorker(config); + this.wss = wss; wss.on('connection', (ws) => { @@ -59,6 +64,8 @@ class WebSocketController { await this.test(req, ws); break; case 'get-config': await this.getConfig(req, ws); break; + case 'get-worker-state': + await this.getWorkerState(req, ws); break; default: throw new Error(`Action not found: ${req.action}`); @@ -100,6 +107,14 @@ class WebSocketController { } } + async getWorkerState(req, ws) { + if (!req.workerId) + throw new Error(`key 'workerId' is empty`); + + const state = this.workerState.getState(req.workerId); + this.send((state ? state : {}), req, ws); + } + } module.exports = WebSocketController; diff --git a/server/core/DbCreator.js b/server/core/DbCreator.js new file mode 100644 index 0000000..e69de29 diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js new file mode 100644 index 0000000..fd5b98c --- /dev/null +++ b/server/core/WebWorker.js @@ -0,0 +1,50 @@ +const WorkerState = require('./WorkerState'); + +//server states: +const ssNormal = 'normal'; +const ssDbLoading = 'db_loading'; + +//singleton +let instance = null; + +class WebWorker { + constructor(config) { + if (!instance) { + this.config = config; + this.workerState = new WorkerState(); + + this.wState = this.workerState.getControl('server_state'); + this.myState = ''; + + this.loadOrCreateDb();//no await + + instance = this; + } + + return instance; + } + + checkMyState() { + if (this.myState != ssNormal) + throw new Error('server_busy'); + } + + setMyState(newState) { + this.myState = newState; + this.wState.set({state: newState}); + } + + async loadOrCreateDb() { + this.setMyState(ssDbLoading); + + try { + // + } catch (e) { + // + } finally { + this.setMyState(ssNormal); + } + } +} + +module.exports = WebWorker; \ No newline at end of file diff --git a/server/core/WorkerState.js b/server/core/WorkerState.js new file mode 100644 index 0000000..3daf333 --- /dev/null +++ b/server/core/WorkerState.js @@ -0,0 +1,62 @@ +const utils = require('./utils'); + +const cleanInterval = 3600; //sec +const cleanAfterLastModified = cleanInterval - 60; //sec + +let instance = null; + +//singleton +class WorkerState { + constructor() { + if (!instance) { + this.states = {}; + this.cleanStates(); + instance = this; + } + + return instance; + } + + generateWorkerId() { + return utils.randomHexString(20); + } + + getControl(workerId) { + return { + set: state => this.setState(workerId, state), + finish: state => this.finishState(workerId, state), + get: () => this.getState(workerId), + }; + } + + setState(workerId, state) { + this.states[workerId] = Object.assign({}, this.states[workerId], state, { + workerId, + lastModified: Date.now() + }); + } + + finishState(workerId, state) { + this.states[workerId] = Object.assign({}, this.states[workerId], state, { + workerId, + state: 'finish', + lastModified: Date.now() + }); + } + + getState(workerId) { + return this.states[workerId]; + } + + cleanStates() { + const now = Date.now(); + for (let workerID in this.states) { + if ((now - this.states[workerID].lastModified) >= cleanAfterLastModified*1000) { + delete this.states[workerID]; + } + } + setTimeout(this.cleanStates.bind(this), cleanInterval*1000); + } +} + +module.exports = WorkerState; \ No newline at end of file