added panel mgmt

This commit is contained in:
2025-07-01 14:09:27 +02:00
parent 5aca14159b
commit 6bc2fc8bf3
2195 changed files with 146523 additions and 5 deletions

19
panel-mgmt/backend/node_modules/seq-queue/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"predef": [
"describe",
"it",
"before",
"after",
"window",
"__resources__"
],
"es5": true,
"node": true,
"eqeqeq": true,
"undef": true,
"curly": true,
"bitwise": true,
"immed": false,
"newcap": true,
"nonew": true
}

3
panel-mgmt/backend/node_modules/seq-queue/.npmignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
.project
node_modules/
lib/doc/

1
panel-mgmt/backend/node_modules/seq-queue/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1 @@
* Yongchang Zhou <changchang005@gmail.com>

22
panel-mgmt/backend/node_modules/seq-queue/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2012 Netease, Inc. and other pomelo contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

9
panel-mgmt/backend/node_modules/seq-queue/Makefile generated vendored Normal file
View File

@@ -0,0 +1,9 @@
TESTS = test/*.js
REPORTER = spec
TIMEOUT = 5000
test:
@./node_modules/.bin/mocha \
--reporter $(REPORTER) --timeout $(TIMEOUT) $(TESTS)
.PHONY: test

75
panel-mgmt/backend/node_modules/seq-queue/README.md generated vendored Normal file
View File

@@ -0,0 +1,75 @@
seq-queue - queue to keep request process in sequence
=====================================================
Seq-queue is simple tool to keep requests to be executed in order.
As we known, Node.js codes run in asynchronous mode and the callbacks are unordered. But sometimes we may need the requests to be processed in order. For example, in a game, a player would do some operations such as turn right and go ahead. And in the server side, we would like to process these requests one by one, not do them all at the same time.
Seq-queue takes the responsibility to make the asynchronous, unordered processing flow into serial and ordered. It's simple but not a repeated wheel.
Seq-queue is a FIFO task queue and we can push tasks as we wish, anytime(before the queue closed), anywhere(if we hold the queue instance). A task is known as a function and we can do anything in the function and just need to call `task.done()` to tell the queue current task has finished. It promises that a task in queue would not be executed util all tasks before it finished.
Seq-queue add timeout for each task execution. If a task throws an uncaught exception in its call back or a developer forgets to call `task.done()` callback, queue would be blocked and would not execute the left tasks. To avoid these situations, seq-queue set a timeout for each task. If a task timeout, queue would drop the task and notify develop by a 'timeout' event and then invoke the next task. Any `task.done()` invoked in a timeout task would be ignored.
* Tags: node.js
##Installation
```
npm install seq-queue
```
##Usage
``` javascript
var seqqueue = require('seq-queue');
var queue = seqqueue.createQueue(1000);
queue.push(
function(task) {
setTimeout(function() {
console.log('hello ');
task.done();
}, 500);
},
function() {
console.log('task timeout');
},
1000
);
queue.push(
function(task) {
setTimeout(function() {
console.log('world~');
task.done();
}, 500);
}
);
```
##API
###seqqueue.createQueue(timeout)
Create a new queue instance. A global timeout value in ms for the new instance can be set by `timeout` parameter or use the default timeout (3s) by no parameter.
###queue.push(fn, ontimeout, timeout)
Add a task into the queue instance.
####Arguments
+ fn(task) - The function that describes the content of task and would be invoke by queue. `fn` takes a arguemnt task and we *must* call task.done() to tell queue current task has finished.
+ ontimeout() - Callback for task timeout.
+ timeout - Timeout in ms for `fn`. If specified, it would overwrite the global timeout that set by `createQueue` for `fn`.
###queue.close(force)
Close the queue. A closed queue would stop receiving new task immediately. And the left tasks would be treated in different ways decided by `force`.
####Arguments
+ force - If true, queue would stop working immediately and ignore any tasks left in queue. Otherwise queue would execute the tasks in queue and then stop.
##Event
Seq-queue instances extend the EventEmitter and would emit events in their life cycles.
###'timeout'(totask)
If current task not invoke task.done() within the timeout ms, a timeout event would be emit. totask.fn and totask.timeout is the `fn` and `timeout` arguments that passed by `queue.push(2)`.
###'error'(err, task)
If the task function (not callbacks) throws an uncaught error, queue would emit an error event and passes the err and task informations by event callback arguments.
###'closed'
Emit when the close(false) is invoked.
###'drained'
Emit when close(true) is invoked or all tasks left have finished in closed status.

1
panel-mgmt/backend/node_modules/seq-queue/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./lib/seq-queue');

View File

View File

@@ -0,0 +1,199 @@
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var DEFAULT_TIMEOUT = 3000;
var INIT_ID = 0;
var EVENT_CLOSED = 'closed';
var EVENT_DRAINED = 'drained';
/**
* Instance a new queue
*
* @param {Number} timeout a global timeout for new queue
* @class
* @constructor
*/
var SeqQueue = function(timeout) {
EventEmitter.call(this);
if(timeout && timeout > 0) {
this.timeout = timeout;
} else {
this.timeout = DEFAULT_TIMEOUT;
}
this.status = SeqQueueManager.STATUS_IDLE;
this.curId = INIT_ID;
this.queue = [];
};
util.inherits(SeqQueue, EventEmitter);
/**
* Add a task into queue.
*
* @param fn new request
* @param ontimeout callback when task timeout
* @param timeout timeout for current request. take the global timeout if this is invalid
* @returns true or false
*/
SeqQueue.prototype.push = function(fn, ontimeout, timeout) {
if(this.status !== SeqQueueManager.STATUS_IDLE && this.status !== SeqQueueManager.STATUS_BUSY) {
//ignore invalid status
return false;
}
if(typeof fn !== 'function') {
throw new Error('fn should be a function.');
}
this.queue.push({fn: fn, ontimeout: ontimeout, timeout: timeout});
if(this.status === SeqQueueManager.STATUS_IDLE) {
this.status = SeqQueueManager.STATUS_BUSY;
var self = this;
process.nextTick(function() {
self._next(self.curId);
});
}
return true;
};
/**
* Close queue
*
* @param {Boolean} force if true will close the queue immediately else will execute the rest task in queue
*/
SeqQueue.prototype.close = function(force) {
if(this.status !== SeqQueueManager.STATUS_IDLE && this.status !== SeqQueueManager.STATUS_BUSY) {
//ignore invalid status
return;
}
if(force) {
this.status = SeqQueueManager.STATUS_DRAINED;
if(this.timerId) {
clearTimeout(this.timerId);
this.timerId = undefined;
}
this.emit(EVENT_DRAINED);
} else {
this.status = SeqQueueManager.STATUS_CLOSED;
this.emit(EVENT_CLOSED);
}
};
/**
* Invoke next task
*
* @param {String|Number} tid last executed task id
* @api private
*/
SeqQueue.prototype._next = function(tid) {
if(tid !== this.curId || this.status !== SeqQueueManager.STATUS_BUSY && this.status !== SeqQueueManager.STATUS_CLOSED) {
//ignore invalid next call
return;
}
if(this.timerId) {
clearTimeout(this.timerId);
this.timerId = undefined;
}
var task = this.queue.shift();
if(!task) {
if(this.status === SeqQueueManager.STATUS_BUSY) {
this.status = SeqQueueManager.STATUS_IDLE;
this.curId++; //modify curId to invalidate timeout task
} else {
this.status = SeqQueueManager.STATUS_DRAINED;
this.emit(EVENT_DRAINED);
}
return;
}
var self = this;
task.id = ++this.curId;
var timeout = task.timeout > 0 ? task.timeout : this.timeout;
timeout = timeout > 0 ? timeout : DEFAULT_TIMEOUT;
this.timerId = setTimeout(function() {
process.nextTick(function() {
self._next(task.id);
});
self.emit('timeout', task);
if(task.ontimeout) {
task.ontimeout();
}
}, timeout);
try {
task.fn({
done: function() {
var res = task.id === self.curId;
process.nextTick(function() {
self._next(task.id);
});
return res;
}
});
} catch(err) {
self.emit('error', err, task);
process.nextTick(function() {
self._next(task.id);
});
}
};
/**
* Queue manager.
*
* @module
*/
var SeqQueueManager = module.exports;
/**
* Queue status: idle, welcome new tasks
*
* @const
* @type {Number}
* @memberOf SeqQueueManager
*/
SeqQueueManager.STATUS_IDLE = 0;
/**
* Queue status: busy, queue is working for some tasks now
*
* @const
* @type {Number}
* @memberOf SeqQueueManager
*/
SeqQueueManager.STATUS_BUSY = 1;
/**
* Queue status: closed, queue has closed and would not receive task any more
* and is processing the remaining tasks now.
*
* @const
* @type {Number}
* @memberOf SeqQueueManager
*/
SeqQueueManager.STATUS_CLOSED = 2;
/**
* Queue status: drained, queue is ready to be destroy
*
* @const
* @type {Number}
* @memberOf SeqQueueManager
*/
SeqQueueManager.STATUS_DRAINED = 3;
/**
* Create Sequence queue
*
* @param {Number} timeout a global timeout for the new queue instance
* @return {Object} new queue instance
* @memberOf SeqQueueManager
*/
SeqQueueManager.createQueue = function(timeout) {
return new SeqQueue(timeout);
};

17
panel-mgmt/backend/node_modules/seq-queue/package.json generated vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "seq-queue",
"author": "changchang <changchang005@gmail.com>",
"version": "0.0.5",
"description": "A simple tool to keep requests to be executed in order.",
"homepage": "https://github.com/changchang/seq-queue",
"repository": {
"type": "git",
"url": "git@github.com:changchang/seq-queue.git"
},
"dependencies": {
},
"devDependencies": {
"mocha": ">=0.0.1",
"should": ">=0.0.1"
}
}

View File

@@ -0,0 +1,307 @@
var should = require('should');
var SeqQueue = require('../lib/seq-queue');
var timeout = 1000;
describe('seq-queue', function() {
describe('#createQueue', function() {
it('should return a seq-queue instance with init properties', function() {
var queue = SeqQueue.createQueue(timeout);
should.exist(queue);
queue.should.have.property('timeout', timeout);
queue.should.have.property('status', SeqQueue.IDLE);
});
});
describe('#push' , function() {
it('should change the queue status from idle to busy and invoke the task at once when task finish when queue idle', function(done) {
var queue = SeqQueue.createQueue(timeout);
queue.should.have.property('status', SeqQueue.IDLE);
queue.push(function(task) {
should.exist(task);
task.done();
queue.should.have.property('status', SeqQueue.IDLE);
done();
});
queue.should.have.property('status', SeqQueue.BUSY);
});
it('should keep the status busy and keep the new task wait until the former tasks finish when queue busy', function(done) {
var queue = SeqQueue.createQueue(timeout);
var formerTaskFinished = false;
//add first task
queue.push(function(task) {
formerTaskFinished = true;
task.done();
});
queue.should.have.property('status', SeqQueue.BUSY);
//add second task
queue.push(function(task) {
formerTaskFinished.should.be.true;
queue.should.have.property('status', SeqQueue.BUSY);
task.done();
queue.should.have.property('status', SeqQueue.IDLE);
done();
});
queue.should.have.property('status', SeqQueue.BUSY);
});
it('should ok if the task call done() directly', function(done) {
var queue = SeqQueue.createQueue();
var taskCount = 0;
queue.push(function(task) {
taskCount++;
task.done();
});
queue.push(function(task) {
taskCount++;
task.done();
});
setTimeout(function() {
taskCount.should.equal(2);
done();
}, 500);
});
});
describe('#close', function() {
it('should not accept new request but should execute the rest task in queue when close gracefully', function(done) {
var queue = SeqQueue.createQueue(timeout);
var closedEventCount = 0;
var drainedEventCount = 0;
queue.on('closed', function() {
closedEventCount++;
});
queue.on('drained', function() {
drainedEventCount++;
});
var executedTaskCount = 0;
queue.push(function(task) {
executedTaskCount++;
task.done();
}).should.be.true;
queue.close(false);
queue.should.have.property('status', SeqQueue.CLOSED);
queue.push(function(task) {
// never should be executed
executedTaskCount++;
task.done();
}).should.be.false;
// wait all task finished
setTimeout(function() {
executedTaskCount.should.equal(1);
closedEventCount.should.equal(1);
drainedEventCount.should.equal(1);
done();
}, 1000);
});
it('should not execute any task and emit a drained event when close forcefully', function(done) {
var queue = SeqQueue.createQueue(timeout);
var drainedEventCount = 0;
queue.on('drained', function() {
drainedEventCount++;
});
var executedTaskCount = 0;
queue.push(function(task) {
//never should be executed
executedTaskCount++;
task.done();
}).should.be.true;
queue.close(true);
queue.should.have.property('status', SeqQueue.DRAINED);
// wait all task finished
setTimeout(function() {
executedTaskCount.should.equal(0);
drainedEventCount.should.equal(1);
done();
}, 1000);
});
});
describe('#timeout', function() {
it('should emit timeout event and execute the next task when a task timeout by default', function(done) {
var queue = SeqQueue.createQueue();
var executedTaskCount = 0;
var timeoutCount = 0;
var onTimeoutCount = 0;
//add timeout listener
queue.on('timeout', function(task) {
task.should.be.a('object');
task.fn.should.be.a('function');
timeoutCount++;
});
queue.push(function(task) {
executedTaskCount++;
//no task.done() invoke to cause a timeout
}, function() {
onTimeoutCount++;
}).should.be.true;
queue.push(function(task) {
executedTaskCount++;
task.done();
}).should.be.true;
setTimeout(function() {
//wait all task finish
executedTaskCount.should.be.equal(2);
timeoutCount.should.be.equal(1);
onTimeoutCount.should.be.equal(1);
done();
}, 4000); //default timeout is 3s
});
it('should return false when invoke task.done() if task has already timeout', function(done) {
var queue = SeqQueue.createQueue();
var executedTaskCount = 0;
var timeoutCount = 0;
var timeout = 1000;
//add timeout listener
queue.on('timeout', function(task) {
task.should.be.a('object');
task.fn.should.be.a('function');
timeoutCount++;
});
queue.push(function(task) {
executedTaskCount++;
task.done().should.be.true;
}).should.be.true;
queue.push(function(task) {
//sleep to make a timeout
setTimeout(function() {
executedTaskCount++;
task.done().should.be.false;
}, timeout + 1000);
}, null, timeout).should.be.true;
setTimeout(function() {
//wait all task finish
executedTaskCount.should.be.equal(2);
timeoutCount.should.be.equal(1);
done();
}, 4000);
});
it('should never timeout after close forcefully', function(done) {
var queue = SeqQueue.createQueue(timeout);
var timeoutCount = 0;
//add timeout listener
queue.on('timeout', function(task) {
//should never enter here
timeoutCount++;
});
queue.push(function(task) {
//no task.done() invoke to cause a timeout
}).should.be.true;
queue.close(true);
setTimeout(function() {
//wait all task finish
timeoutCount.should.be.equal(0);
done();
}, timeout * 2);
});
it('should use the global timeout value by default', function(done) {
var globalTimeout = timeout + 100;
var queue = SeqQueue.createQueue(globalTimeout);
//add timeout listener
queue.on('timeout', function(task) {
(Date.now() - start).should.not.be.below(globalTimeout);
done();
});
queue.push(function(task) {
//no task.done() invoke to cause a timeout
}).should.be.true;
var start = Date.now();
});
it('should use the timeout value in #push if it was assigned', function(done) {
var localTimeout = timeout / 2;
var queue = SeqQueue.createQueue(timeout);
//add timeout listener
queue.on('timeout', function(task) {
var diff = Date.now() - start;
diff.should.not.be.below(localTimeout);
diff.should.not.be.above(timeout);
done();
});
queue.push(function(task) {
//no task.done() invoke to cause a timeout
}, null, localTimeout).should.be.true;
var start = Date.now();
});
});
describe('#error', function() {
it('should emit an error event and invoke next task when a task throws an event', function(done) {
var queue = SeqQueue.createQueue();
var errorCount = 0;
var taskCount = 0;
//add timeout listener
queue.on('error', function(err, task) {
errorCount++;
should.exist(err);
should.exist(task);
});
queue.push(function(task) {
taskCount++;
throw new Error('some error');
}).should.be.true;
queue.push(function(task) {
taskCount++;
task.done();
});
setTimeout(function() {
taskCount.should.equal(2);
errorCount.should.equal(1);
done();
}, 500);
});
it('should be ok when task throw a error after done was invoked', function(done) {
var queue = SeqQueue.createQueue();
var errorCount = 0;
var taskCount = 0;
//add timeout listener
queue.on('error', function(err, task) {
errorCount++;
should.exist(err);
should.exist(task);
});
queue.push(function(task) {
taskCount++;
task.done();
throw new Error('some error');
}).should.be.true;
queue.push(function(task) {
taskCount++;
task.done();
});
setTimeout(function() {
taskCount.should.equal(2);
errorCount.should.equal(1);
done();
}, 500);
});
});
});