diff --git a/server/db/ConnManager.js b/server/db/ConnManager.js index 5576fa47..14098a6a 100644 --- a/server/db/ConnManager.js +++ b/server/db/ConnManager.js @@ -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}"`); //миграции diff --git a/server/db/SqliteConnectionPool.js b/server/db/SqliteConnectionPool.js index a5189a9b..01b8f991 100644 --- a/server/db/SqliteConnectionPool.js +++ b/server/db/SqliteConnectionPool.js @@ -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 {