Last active
March 25, 2018 10:03
-
-
Save 16Yongjin/4239ae656efb91469fb238f86fa2a39a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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