Compare commits

...

3 commits

Author SHA1 Message Date
Slincnik
c7ebdb78d4
feat(database): add cache to mongoose adapter 2024-12-16 17:41:39 +03:00
Slincnik
ac461a104d
feat: added cache adapter 2024-12-16 17:41:11 +03:00
Slincnik
b26222a947
refactor: delete unusable helper 2024-12-16 16:31:22 +03:00
4 changed files with 62 additions and 56 deletions

9
src/adapters/cache/ICacheAdapter.js vendored Normal file
View file

@ -0,0 +1,9 @@
export default class ICacheAdapter {
get() {}
set() {}
clear() {}
delete() {}
}

24
src/adapters/cache/MapCache.js vendored Normal file
View file

@ -0,0 +1,24 @@
import ICacheAdapter from "./ICacheAdapter";
export default class MapCache extends ICacheAdapter {
constructor() {
super();
this.store = new Map();
}
get(key) {
return this.store.get(key);
}
set(key, value) {
this.store.set(key, value);
}
clear() {
this.store.clear();
}
delete(key) {
this.store.delete(key);
}
}

View file

@ -1,6 +1,7 @@
import mongoose from "mongoose";
import IDatabaseAdapter from "./IDatabaseAdapter.js";
import logger from "../../helpers/logger.js";
import Cache from "../cache/MapCache.js";
export default class MongooseAdapter extends IDatabaseAdapter {
/**
@ -16,8 +17,8 @@ export default class MongooseAdapter extends IDatabaseAdapter {
}
this.uri = uri;
this.options = options;
this.cache = new Cache();
}
async connect() {
@ -28,21 +29,44 @@ export default class MongooseAdapter extends IDatabaseAdapter {
async disconnect() {
await mongoose.disconnect();
logger.warn("Database disconnected.");
this.cache.clear();
}
#generateCacheKey(modelName, query, options) {
return `${modelName}:${JSON.stringify(query)}:${JSON.stringify(options)}`;
}
async find(model, query = {}, options = {}) {
return model.find(query, null, options).exec();
const cacheKey = this.#generateCacheKey(model.modelName, query, options);
if (this.cache.get(cacheKey)) {
return this.cache.get(cacheKey);
}
const result = await model.find(query, null, options).exec();
this.cache.set(cacheKey, result);
return result;
}
async findOne(model, query = {}, options = {}) {
return model.findOne(query, null, options).exec();
const cacheKey = this.#generateCacheKey(model.modelName, query, options);
if (this.cache.get(cacheKey)) {
return this.cache.get(cacheKey);
}
const result = await model.findOne(query, null, options).exec();
this.cache.set(cacheKey, result);
return result;
}
async updateOne(model, filter, update, options = {}) {
return model.updateOne(filter, update, options).exec();
const result = await model.updateOne(filter, update, options).exec();
this.cache.clear();
return result;
}
async deleteOne(model, filter) {
return model.deleteOne(filter).exec();
const result = await model.deleteOne(filter).exec();
this.cache.clear();
return result;
}
}

View file

@ -1,51 +0,0 @@
import { use, init, getFixedT } from "i18next";
import Backend from "i18next-fs-backend";
import { join, resolve } from "path";
import { promises as fs } from "fs";
async function walkDirectory(dir, namespaces = [], folderName = "") {
const files = await fs.readdir(dir);
const languages = [];
for (const file of files) {
const stat = await fs.stat(join(dir, file));
if (stat.isDirectory()) {
const isLanguage = file.includes("-");
if (isLanguage) languages.push(file);
const folder = await walkDirectory(join(dir, file), namespaces, isLanguage ? "" : `${file}/`);
namespaces = folder.namespaces;
} else {
namespaces.push(`${folderName}${file.substr(0, file.length - 5)}`);
}
}
return {
namespaces: [...new Set(namespaces)],
languages,
};
}
export default async () => {
const options = {
loadPath: resolve(__dirname, "../languages/{{lng}}/{{ns}}.json"),
};
const { namespaces, languages } = await walkDirectory(resolve(__dirname, "../languages/"));
use(Backend);
await init({
backend: options,
debug: false,
fallbackLng: "en-US",
initImmediate: false,
interpolation: { escapeValue: false },
load: "all",
ns: namespaces,
preload: languages,
});
return new Map(languages.map(item => [item, getFixedT(item)]));
};