@63pokupki/nodejs-common
Version:
Common nodejs functionality
117 lines • 5.02 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AvgCacheSys = void 0;
const knex_1 = __importDefault(require("knex"));
const lodash_1 = __importDefault(require("lodash"));
/**
* агрегированное кеширование
* кеширует данные в денормализованном виде
* для их быстрой выборки
* предполагается что кешируемые данные живу
*/
class AvgCacheSys {
/** init */
constructor(conf) {
// TODO - реализовать пул БД для кеширования с распределением данных по ним - на основе деления на остаток
/** задержка */
this.iLatency = 0;
if (conf) {
this.dbCache = (0, knex_1.default)(conf);
}
else {
console.log('AvgCacheSys - Не указана БД для агрегационного кеширования');
}
}
/** Конфигурация кеширования */
fConf(param) {
if (param) {
if (param.latency) {
this.iLatency = param.latency;
}
}
}
/** Сбросить агрегационные данные */
async avgReset(sTable, aidRecord) {
if (this.dbCache) {
try {
await this.dbCache({ t: sTable })
.whereIn('t.id', aidRecord)
.where('v', '=', 0)
.update({ v: 1 });
}
catch (e) {
console.log('AvgCacheSys.avgReset - ', e);
}
}
}
/**
* Агрегационное кеширование
* необходимо передавть фунцию для создания агрегации
*/
async avgCache(sTable, aidRecord, callback) {
let ixCacheIgnore = {}; // Словарь для ингорирования кеша, в случае если стоит задержка latency
let aidRecordDiff = []; // Разница для выборки новых данных
let aDataCache = []; // Закешированые данные
if (this.dbCache) {
const [aCache, aidCacheIgnore] = await Promise.all([
this.dbCache({ t: sTable })
.whereIn('t.id', aidRecord)
.where('t.v', '=', 0)
.select(),
this.dbCache({ t: sTable })
.whereIn('t.id', aidRecord)
.where('t.v', '>', 0)
.whereRaw(`NOW() < t.updated_at + INTERVAL ${this.iLatency} SECOND `)
.pluck('t.id')
]);
ixCacheIgnore = lodash_1.default.keyBy(aidCacheIgnore);
// Декодируем данные из кеша
const aidRecordCache = aCache.map(el => el.id);
aDataCache = aCache.map((el) => JSON.parse(el.data));
// Вычисляем разницу в данных
aidRecordDiff = lodash_1.default.difference(aidRecord, aidRecordCache);
}
const aDataNew = await callback(aidRecordDiff);
// console.log('[DATA_NEW]>>', 'new:', aDataNew.length, 'dif:', aidRecordDiff.length, 'ign:', aidCacheIgnore.length);
const aItemCacheNew = [];
for (let i = 0; i < aDataNew.length; i++) {
const vDataNew = aDataNew[i];
if (vDataNew) {
const idRecord = vDataNew.id;
aDataCache.push(vDataNew);
if (!ixCacheIgnore[idRecord]) {
aItemCacheNew.push({ id: idRecord, v: 0, data: JSON.stringify(vDataNew) });
}
}
}
if (this.dbCache && aItemCacheNew.length) { // Дописываем данные в кеш
try {
// const insertResult = await mgItemCache.insertMany(aItemCacheNew);
let sql = (this.dbCache(sTable).insert(aItemCacheNew))
.toString();
sql = sql.replace(/^insert/i, 'replace');
// console.log(sql);
await this.dbCache.raw(sql);
}
catch (e) {
console.log('AvgCacheSys.avgCache - ', e);
}
}
// Сортировка
const ixDataCache = lodash_1.default.keyBy(aDataCache, 'id');
const aDataCacheSort = [];
for (let i = 0; i < aidRecord.length; i++) {
const idRecord = aidRecord[i];
const vDataCache = ixDataCache[idRecord];
if (vDataCache) {
aDataCacheSort.push(vDataCache);
}
}
return aDataCacheSort;
}
}
exports.AvgCacheSys = AvgCacheSys;
//# sourceMappingURL=AvgCacheSys.js.map