Управление переводом на Amazon с помощью Redis
Мне нужно управлять передачей json с помощью aws от Amazon и сохранять кеш в redis.
async function translateSomething(trans, p1, sourceLan, targetLan) {
var paramsName = {
Text: p1,
SourceLanguageCode: sourceLan,
TargetLanguageCode: targetLan,
};
let myPromise = () =>
new Promise((resolve, reject) => {
trans.translateText(paramsName, function (err, data) {
if (err) throw err;
if (data) {
console.log("translated", data.TranslatedText);
resolve(data.TranslatedText);
}
});
});
let res = await myPromise();
return res;
}
// and this function to check if the value is in the menu or not
function storeOrFound(p1, value, sourceLan, targetLan) {
return redisClient.get(p1, async (err, result) => {
if (err) console.log("err", err);
if (result) {
console.log("element is already in cache", JSON.parse(result).val);
let tmp = JSON.parse(result).val;
return tmp;
} else {
var translate = new AWS.Translate({ region: AWS.config.region });
let val = await translateSomething(
translate,
value,
sourceLan,
targetLan,
);
redisClient.setex(
p1,
3600,
JSON.stringify({ source: "Redis Cache", val }),
);
return val;
}
});
}
// and after i execute the query of the db i use this function to check if is present or not on the db or not
something().then((doc) => {
for (let i = 0; i < doc.items.length; i++) {
const menuRedisKeyName = `name:${doc.items[i].name}21`;
doc.items[i].name = storeOrFound(
menuRedisKeyName,
doc.items[i].name,
menuLang,
targetLan,
);
}
console.log("JSON", JSON.stringify(doc));
res.end(JSON.stringify(doc));
});
Проблема в том, что метод storeOrFound возвращает true или false (потому что return redisClient.get возвращает true или false независимо от того, присутствует объект или нет. Есть идеи по решению этой проблемы? Также на консоли я вижу, что элемент console.log(" уже в кеше "..) печатается в конце. Я что-то пропустил при синхронизации?
1 ответ
Решение
Вы можете захотеть что-то вроде этого.
translateSomething
а такжеcheckCache
возвращать обещания, поэтому вы можете легко использовать их вasync/await
код.getFromCacheOrTranslate
оборачивает эти два в асинхронную функцию.
В коде есть и некоторые будущие TODO-комментарии.
function translateSomething(translate, text, sourceLan, targetLan) {
return new Promise((resolve, reject) => {
translate.translateText(
{
Text: text,
SourceLanguageCode: sourceLan,
TargetLanguageCode: targetLan,
},
function (err, data) {
if (err && !data) {
reject(err);
return;
}
console.log("translated", data.TranslatedText);
resolve(data.TranslatedText);
},
);
});
}
/**
* Promisified version of `redisClient.get()`.
*/
function checkCache(key) {
return new Promise((resolve, reject) => {
redisClient.get(key, (err, result) => {
if (err) {
reject(err);
}
resolve(result);
});
});
}
async function getFromCacheOrTranslate(text, sourceLan, targetLan) {
const key = `translate:${sourceLan}:${targetLan}:${text}`; // TODO: hash the text here for a shorter cache key
let result = await checkCache(key);
if (result) {
// result was in cache, return it
return JSON.parse(result);
}
// Otherwise save it to the cache and return it
const translate = new AWS.Translate({ region: AWS.config.region });
result = await translateSomething(translate, text, sourceLan, targetLan);
redisClient.setex(key, 3600, JSON.stringify(result)); // Async result ignored here
return result;
}
something().then(async (doc) => {
// TODO: this could use `Promise.all` to do this in parallel
for (let i = 0; i < doc.items.length; i++) {
doc.items[i].name = await getFromCacheOrTranslate(
doc.items[i].name,
menuLang,
targetLan,
);
}
console.log("JSON", JSON.stringify(doc));
res.end(JSON.stringify(doc));
});