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

This commit is contained in:
Book Pauk
2022-11-17 16:51:12 +07:00
parent 6b91c43655
commit 412335c0f1
3 changed files with 87 additions and 42 deletions

View File

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

View File

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

View File

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