소스 검색

Улучшения SqliteConnectionPool

Book Pauk 4 년 전
부모
커밋
6c20b0b83e
2개의 변경된 파일31개의 추가작업 그리고 31개의 파일을 삭제
  1. 2 4
      server/db/ConnManager.js
  2. 29 27
      server/db/SqliteConnectionPool.js

+ 2 - 4
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}"`);
             //миграции

+ 29 - 27
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 {