Skip to content

Instantly share code, notes, and snippets.

@16Yongjin
Last active March 25, 2018 10:03
Show Gist options
  • Select an option

  • Save 16Yongjin/4239ae656efb91469fb238f86fa2a39a to your computer and use it in GitHub Desktop.

Select an option

Save 16Yongjin/4239ae656efb91469fb238f86fa2a39a to your computer and use it in GitHub Desktop.
const mongoose = require('mongoose')
const { promisify } = require('util')
const redis = require('redis')
const redisUrl = 'redis://127.0.0.1:6379'
const client = redis.createClient(redisUrl)
client.hget = promisify(client.hget)
const exec = mongoose.Query.prototype.exec
// this 때문에 function 키워드 사용
// 캐시할 것인지 확인하기 위한 메서드
mongoose.Query.prototype.cache = function (options = {}) {
this.useCache = true
// user id를 해시키로 사용하기 위함
this.hashKey = JSON.stringify(options.key || '')
return this
}
// exec 메서드를 오버라이딩해서 쿼리를 가로챔
mongoose.Query.prototype.exec = async function () {
if (!this.useCache) return exec.apply(this, arguments)
const key = JSON.stringify({
...this.getQuery(),
collection: this.mongooseCollection.name
})
// 캐시 가져오기
const cachedValue = await client.hget(this.hashKey, key)
// mongoose는 쿼리의 결과가 모델 문서 객체이길 바래서 데이터에 모델을 씌워준다.
if (cachedValue) {
const doc = JSON.parse(cachedValue)
return Array.isArray(doc)
? doc.map(d => new this.model(d))
: new this.model(doc)
}
const result = await exec.apply(this, arguments)
// 캐싱, 'EX', n - n 초 후 캐시 소멸
client.hset(this.hashKey, key, JSON.stringify(result), 'EX', 10)
return result
}
module.exports = {
clearHash(hashKey) {
client.del(JSON.stringify(hashKey))
}
}
/*
사용
*/
app.get('/api/blogs', requireLogin, async (req, res) => {
const blogs = await Blog
.find({ _user: req.user.id })
.cache({ key: req.user.id }) // 캐시할 것임을 명시함
res.send(blogs)
});
// 캐시를 지우는 미들웨어
const { clearHash } = require('../services/cache')
const cleanCache = async (req, res, next) => {
// 리퀘스트 핸들러 기다린 다음에
await next()
// 캐시를 비움
clearHash(req.user.id)
}
// 새 블로그를 올리면 이전 캐시 없앰
app.post('/api/blogs', requireLogin, cleanCache, async (req, res) => { ... })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment