I have to manage a traduction of a json with aws from amazon and saving the cache in 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));
});
The problem is that the method storeOrFound returns true or false (because return redisClient.get return true or false whether the object is present or not . Any ideas for managing this problem? Also on the console i see that the console.log(" element is already in cache"..) is printed at the end. Did i miss something on synchronization?
You might want something like this.
translateSomething
and checkCache
return promises, so you can use them easily in async/await
code.getFromCacheOrTranslate
wraps these two in an async function.There are some future addition TODO comments in the code too.
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));
});