瀏覽代碼

В конфиг добавлены параметры queryCacheMemSize, queryCacheDiskSize

Book Pauk 2 年之前
父節點
當前提交
412335c0f1
共有 3 個文件被更改,包括 88 次插入43 次删除
  1. 2 0
      server/config/base.js
  2. 2 0
      server/config/index.js
  3. 84 43
      server/core/DbSearcher.js

+ 2 - 0
server/config/base.js

@@ -22,6 +22,8 @@ module.exports = {
     maxPayloadSize: 500,//in MB
     maxFilesDirSize: 1024*1024*1024,//1Gb
     queryCacheEnabled: true,
+    queryCacheMemSize: 50,
+    queryCacheDiskSize: 500,
     cacheCleanInterval: 60,//minutes
     inpxCheckInterval: 60,//minutes
     lowMemoryMode: false,

+ 2 - 0
server/config/index.js

@@ -11,6 +11,8 @@ const propsToSave = [
     'dbCacheSize',
     'maxFilesDirSize',
     'queryCacheEnabled',
+    'queryCacheMemSize',
+    'queryCacheDiskSize',
     'cacheCleanInterval',
     'inpxCheckInterval',
     'lowMemoryMode',

+ 84 - 43
server/core/DbSearcher.js

@@ -3,7 +3,6 @@ const fs = require('fs-extra');
 const LockQueue = require('./LockQueue');
 const utils = require('./utils');
 
-const maxMemCacheSize = 100;
 const maxLimit = 1000;
 
 const emptyFieldValue = '?';
@@ -15,6 +14,11 @@ const enruArr = (ruAlphabet + enAlphabet).split('');
 class DbSearcher {
     constructor(config, db) {
         this.config = config;
+        this.queryCacheMemSize = this.config.queryCacheMemSize;
+        this.queryCacheDiskSize = this.config.queryCacheDiskSize;
+        this.queryCacheEnabled = this.config.queryCacheEnabled
+            && (this.queryCacheMemSize > 0 || this.queryCacheDiskSize > 0);
+
         this.db = db;
 
         this.lock = new LockQueue();
@@ -501,7 +505,7 @@ class DbSearcher {
             const offset = (query.offset ? query.offset : 0);
 
             const slice = ids.slice(offset, offset + limit);
-            
+
             //выборка найденных значений
             const found = await db.select({
                 table: from,
@@ -594,7 +598,7 @@ class DbSearcher {
     }
 
     async getCached(key) {
-        if (!this.config.queryCacheEnabled)
+        if (!this.queryCacheEnabled)
             return null;
 
         let result = null;
@@ -602,13 +606,13 @@ class DbSearcher {
         const db = this.db;
         const memCache = this.memCache;
 
-        if (memCache.has(key)) {//есть в недавних
+        if (this.queryCacheMemSize > 0 && memCache.has(key)) {//есть в недавних
             result = memCache.get(key);
 
             //изменим порядок ключей, для последующей правильной чистки старых
             memCache.delete(key);
             memCache.set(key, result);
-        } else {//смотрим в таблице
+        } else if (this.queryCacheDiskSize > 0) {//смотрим в таблице
             const rows = await db.select({table: 'query_cache', where: `@@id(${db.esc(key)})`});
 
             if (rows.length) {//нашли в кеше
@@ -619,13 +623,17 @@ class DbSearcher {
                 });
 
                 result = rows[0].value;
-                memCache.set(key, result);
 
-                if (memCache.size > maxMemCacheSize) {
-                    //удаляем самый старый ключ-значение
-                    for (const k of memCache.keys()) {
-                        memCache.delete(k);
-                        break;
+                //заполняем кеш в памяти
+                if (this.queryCacheMemSize > 0) {
+                    memCache.set(key, result);
+
+                    if (memCache.size > this.queryCacheMemSize) {
+                        //удаляем самый старый ключ-значение
+                        for (const k of memCache.keys()) {
+                            memCache.delete(k);
+                            break;
+                        }
                     }
                 }
             }
@@ -635,40 +643,44 @@ class DbSearcher {
     }
 
     async putCached(key, value) {
-        if (!this.config.queryCacheEnabled)
+        if (!this.queryCacheEnabled)
             return;
 
         const db = this.db;
 
-        const memCache = this.memCache;
-        memCache.set(key, value);
+        if (this.queryCacheMemSize > 0) {
+            const memCache = this.memCache;
+            memCache.set(key, value);
 
-        if (memCache.size > maxMemCacheSize) {
-            //удаляем самый старый ключ-значение
-            for (const k of memCache.keys()) {
-                memCache.delete(k);
-                break;
+            if (memCache.size > this.queryCacheMemSize) {
+                //удаляем самый старый ключ-значение
+                for (const k of memCache.keys()) {
+                    memCache.delete(k);
+                    break;
+                }
             }
         }
 
-        //кладем в таблицу асинхронно
-        (async() => {
-            try {
-                await db.insert({
-                    table: 'query_cache',
-                    replace: true,
-                    rows: [{id: key, value}],
-                });
-
-                await db.insert({
-                    table: 'query_time',
-                    replace: true,
-                    rows: [{id: key, time: Date.now()}],
-                });
-            } catch(e) {
-                console.error(`putCached: ${e.message}`);
-            }
-        })();
+        if (this.queryCacheDiskSize > 0) {
+            //кладем в таблицу асинхронно
+            (async() => {
+                try {
+                    await db.insert({
+                        table: 'query_cache',
+                        replace: true,
+                        rows: [{id: key, value}],
+                    });
+
+                    await db.insert({
+                        table: 'query_time',
+                        replace: true,
+                        rows: [{id: key, time: Date.now()}],
+                    });
+                } catch(e) {
+                    console.error(`putCached: ${e.message}`);
+                }
+            })();
+        }
     }
 
     async periodicCleanCache() {
@@ -678,21 +690,50 @@ class DbSearcher {
             return;
 
         try {
+            if (!this.queryCacheEnabled || this.queryCacheDiskSize <= 0)
+                return;
+
             const db = this.db;
 
-            const oldThres = Date.now() - cleanInterval;
+            let rows = await db.select({table: 'query_time', count: true});
+            const delCount = rows[0].count - this.queryCacheDiskSize;
+
+            if (delCount < 1)
+                return;
 
             //выберем всех кандидатов на удаление
-            const rows = await db.select({
+            //находим delCount минимальных по time
+            rows = await db.select({
                 table: 'query_time',
+                rawResult: true,
                 where: `
-                    @@iter(@all(), (r) => (r.time < ${db.esc(oldThres)}));
+                    const res = Array(${db.esc(delCount)}).fill({time: Date.now()});
+
+                    @unsafeIter(@all(), (r) => {
+                        if (r.time >= res[${db.esc(delCount - 1)}].time)
+                            return false;
+
+                        let ins = {id: r.id, time: r.time};
+
+                        for (let i = 0; i < res.length; i++) {
+                            if (!res[i].id || ins.time < res[i].time) {
+                                const t = res[i];
+                                res[i] = ins;
+                                ins = t;
+                            }
+
+                            if (!ins.id)
+                                break;
+                        }
+                        
+                        return false;
+                    });
+
+                    return res.filter(r => r.id).map(r => r.id);
                 `
             });
 
-            const ids = [];
-            for (const row of rows)
-                ids.push(row.id);
+            const ids = rows[0].rawResult;
 
             //удаляем
             await db.delete({table: 'query_cache', where: `@@id(${db.esc(ids)})`});