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