Add a Port pool manager to handle specific port atribution
This commit is contained in:
60
lib/PortManager.js
Normal file
60
lib/PortManager.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import Debug from 'debug';
|
||||
|
||||
class PortManager {
|
||||
constructor(opt) {
|
||||
this.debug = Debug('lt:PortManager');
|
||||
this.range = opt.range || null;
|
||||
this.first = null;
|
||||
this.last = null;
|
||||
this.pool = {};
|
||||
this.initializePool();
|
||||
}
|
||||
|
||||
initializePool() {
|
||||
if (this.range === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^[0-9]+:[0-9]+$/.test(this.range)) {
|
||||
throw new Error('Bad range expression: ' + this.range);
|
||||
}
|
||||
|
||||
[this.first, this.last] = this.range.split(':').map((port) => parseInt(port));
|
||||
|
||||
if (this.first > this.last) {
|
||||
throw new Error('Bad range expression min > max: ' + this.range);
|
||||
}
|
||||
|
||||
for (let port = this.first; port <= this.last; port++) {
|
||||
this.pool['_' + port] = null;
|
||||
}
|
||||
this.debug = Debug('lt:PortManager');
|
||||
this.debug('Pool initialized ' + JSON.stringify(this.pool));
|
||||
}
|
||||
|
||||
release(port) {
|
||||
if (this.range === null) {
|
||||
return;
|
||||
}
|
||||
this.debug('Release port ' + port);
|
||||
this.pool['_' + port] = null;
|
||||
}
|
||||
|
||||
getNextAvailable(clientId) {
|
||||
if (this.range === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let port = this.first; port <= this.last; port++) {
|
||||
if (this.pool['_' + port] === null) {
|
||||
this.pool['_' + port] = clientId;
|
||||
this.debug('Port found ' + port);
|
||||
return port;
|
||||
}
|
||||
}
|
||||
this.debug('No more ports available ');
|
||||
throw new Error('No more ports available in range ' + this.range);
|
||||
}
|
||||
}
|
||||
|
||||
export default PortManager;
|
||||
51
lib/PortManager.test.js
Normal file
51
lib/PortManager.test.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import assert from 'assert';
|
||||
|
||||
import PortManager from './PortManager';
|
||||
|
||||
describe('PortManager', () => {
|
||||
it('should construct with no range', () => {
|
||||
const portManager = new PortManager({});
|
||||
assert.equal(portManager.range, null);
|
||||
assert.equal(portManager.first, null);
|
||||
assert.equal(portManager.last, null);
|
||||
});
|
||||
|
||||
it('should construct with range', () => {
|
||||
const portManager = new PortManager({range: '10:20'});
|
||||
assert.equal(portManager.range, '10:20');
|
||||
assert.equal(portManager.first, 10);
|
||||
assert.equal(portManager.last, 20);
|
||||
});
|
||||
|
||||
it('should not construct with bad range expression', () => {
|
||||
assert.throws(()=>{
|
||||
new PortManager({range: 'a1020'});
|
||||
}, /Bad range expression: a1020/)
|
||||
});
|
||||
|
||||
it('should not construct with bad range max>min', () => {
|
||||
assert.throws(()=>{
|
||||
new PortManager({range: '20:10'});
|
||||
}, /Bad range expression min > max: 20:10/)
|
||||
});
|
||||
|
||||
it('should work has expected', async () => {
|
||||
const portManager = new PortManager({range: '10:12'});
|
||||
assert.equal(10,portManager.getNextAvailable('a'));
|
||||
assert.equal(11,portManager.getNextAvailable('b'));
|
||||
assert.equal(12,portManager.getNextAvailable('c'));
|
||||
|
||||
assert.throws(()=>{
|
||||
portManager.getNextAvailable();
|
||||
}, /No more ports available in range 10:12/)
|
||||
|
||||
portManager.release(11);
|
||||
assert.equal(11,portManager.getNextAvailable('bb'));
|
||||
|
||||
portManager.release(10);
|
||||
portManager.release(12);
|
||||
|
||||
assert.equal(10,portManager.getNextAvailable('cc'));
|
||||
assert.equal(12,portManager.getNextAvailable('dd'));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user