Улучшения SqliteConnectionPool
This commit is contained in:
@@ -4,8 +4,6 @@ const SqliteConnectionPool = require('./SqliteConnectionPool');
|
||||
const log = new (require('../core/AppLogger'))().log;//singleton
|
||||
|
||||
const migrations = {
|
||||
'app': require('./migrations/app'),
|
||||
'readerStorage': require('./migrations/readerStorage'),
|
||||
};
|
||||
|
||||
let instance = null;
|
||||
@@ -32,11 +30,11 @@ class ConnManager {
|
||||
const dbFileName = this.config.dataDir + '/' + poolConfig.fileName;
|
||||
|
||||
//бэкап
|
||||
if (await fs.pathExists(dbFileName))
|
||||
if (!poolConfig.noBak && await fs.pathExists(dbFileName))
|
||||
await fs.copy(dbFileName, `${dbFileName}.bak`);
|
||||
|
||||
const connPool = new SqliteConnectionPool();
|
||||
await connPool.open(poolConfig.connCount, dbFileName);
|
||||
await connPool.open(poolConfig, dbFileName);
|
||||
|
||||
log(`Opened database "${poolConfig.poolName}"`);
|
||||
//миграции
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
const sqlite = require('sqlite');
|
||||
const SQL = require('sql-template-strings');
|
||||
|
||||
const utils = require('../core/utils');
|
||||
|
||||
const waitingDelay = 100; //ms
|
||||
|
||||
class SqliteConnectionPool {
|
||||
constructor() {
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
async open(connCount, dbFileName) {
|
||||
if (!Number.isInteger(connCount) || connCount <= 0)
|
||||
return;
|
||||
async open(poolConfig, dbFileName) {
|
||||
const connCount = poolConfig.connCount || 1;
|
||||
const busyTimeout = poolConfig.busyTimeout || 60*1000;
|
||||
const cacheSize = poolConfig.cacheSize || 2000;
|
||||
|
||||
this.dbFileName = dbFileName;
|
||||
this.connections = [];
|
||||
this.freed = new Set();
|
||||
this.waitingQueue = [];
|
||||
|
||||
for (let i = 0; i < connCount; i++) {
|
||||
let client = await sqlite.open(dbFileName);
|
||||
client.configure('busyTimeout', 10000); //ms
|
||||
|
||||
client.configure('busyTimeout', busyTimeout); //ms
|
||||
await client.exec(`PRAGMA cache_size = ${cacheSize}`);
|
||||
|
||||
client.ret = () => {
|
||||
this.freed.add(i);
|
||||
if (this.waitingQueue.length) {
|
||||
this.waitingQueue.shift().onFreed(i);
|
||||
}
|
||||
};
|
||||
|
||||
this.freed.add(i);
|
||||
@@ -30,30 +35,27 @@ class SqliteConnectionPool {
|
||||
this.closed = false;
|
||||
}
|
||||
|
||||
_setImmediate() {
|
||||
get() {
|
||||
return new Promise((resolve) => {
|
||||
setImmediate(() => {
|
||||
return resolve();
|
||||
if (this.closed)
|
||||
throw new Error('Connection pool closed');
|
||||
|
||||
const freeConnIndex = this.freed.values().next().value;
|
||||
if (freeConnIndex !== undefined) {
|
||||
this.freed.delete(freeConnIndex);
|
||||
resolve(this.connections[freeConnIndex]);
|
||||
return;
|
||||
}
|
||||
|
||||
this.waitingQueue.push({
|
||||
onFreed: (connIndex) => {
|
||||
this.freed.delete(connIndex);
|
||||
resolve(this.connections[connIndex]);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async get() {
|
||||
if (this.closed)
|
||||
return;
|
||||
|
||||
let freeConnIndex = this.freed.values().next().value;
|
||||
if (freeConnIndex == null) {
|
||||
if (waitingDelay)
|
||||
await utils.sleep(waitingDelay);
|
||||
return await this._setImmediate().then(() => this.get());
|
||||
}
|
||||
|
||||
this.freed.delete(freeConnIndex);
|
||||
|
||||
return this.connections[freeConnIndex];
|
||||
}
|
||||
|
||||
async run(query) {
|
||||
const dbh = await this.get();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user