const { db } = require('./mongodb') const mongoCache = require('./MongoCache') const logger = require('@overleaf/logger') const metrics = require('@overleaf/metrics') const { promisify } = require('util') const OError = require('@overleaf/o-error') const LearnedWordsManager = { learnWord(userToken, word, callback) { if (callback == null) { callback = () => {} } mongoCache.del(userToken) return db.spellingPreferences.updateOne( { token: userToken, }, { $addToSet: { learnedWords: word }, }, { upsert: true, }, callback ) }, unlearnWord(userToken, word, callback) { if (callback == null) { callback = () => {} } mongoCache.del(userToken) return db.spellingPreferences.updateOne( { token: userToken, }, { $pull: { learnedWords: word }, }, callback ) }, getLearnedWords(userToken, callback) { if (callback == null) { callback = () => {} } const mongoCachedWords = mongoCache.get(userToken) if (mongoCachedWords != null) { metrics.inc('mongoCache', 0.1, { status: 'hit' }) return callback(null, mongoCachedWords) } metrics.inc('mongoCache', 0.1, { status: 'miss' }) logger.info({ userToken }, 'mongoCache miss') LearnedWordsManager.getLearnedWordsNoCache(userToken, (err, words) => { if (err) return callback(err) mongoCache.set(userToken, words) callback(null, words) }) }, getLearnedWordsNoCache(userToken, callback) { db.spellingPreferences.findOne( { token: userToken }, function (error, preferences) { if (error != null) { return callback(OError.tag(error)) } let words = (preferences != null ? preferences.learnedWords : undefined) || [] if (words) { // remove duplicates words = words.filter( (value, index, self) => self.indexOf(value) === index ) } callback(null, words) } ) }, deleteUsersLearnedWords(userToken, callback) { if (callback == null) { callback = () => {} } db.spellingPreferences.deleteOne({ token: userToken }, callback) }, } const promises = { learnWord: promisify(LearnedWordsManager.learnWord), unlearnWord: promisify(LearnedWordsManager.unlearnWord), getLearnedWords: promisify(LearnedWordsManager.getLearnedWords), deleteUsersLearnedWords: promisify( LearnedWordsManager.deleteUsersLearnedWords ), } LearnedWordsManager.promises = promises module.exports = LearnedWordsManager ;['learnWord', 'unlearnWord', 'getLearnedWords'].map(method => metrics.timeAsyncMethod( LearnedWordsManager, method, 'mongo.LearnedWordsManager', logger ) )