Showing
5 changed files
with
99 additions
and
80 deletions
@@ -11,11 +11,12 @@ const TABLE_ACT_PRIZE_PRODUCT = 'act_prize_product'; | @@ -11,11 +11,12 @@ const TABLE_ACT_PRIZE_PRODUCT = 'act_prize_product'; | ||
11 | const TABLE_ACT_PRIZE_PRODUCT_CONTENT = 'act_prize_product_content'; | 11 | const TABLE_ACT_PRIZE_PRODUCT_CONTENT = 'act_prize_product_content'; |
12 | const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user'; | 12 | const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user'; |
13 | 13 | ||
14 | -const CACHE_TIMES = 60 * 5; // 缓存时间 | 14 | +const MINUTE_TIMES = 60; |
15 | +const PRODUCT_CACHE_TIMES = MINUTE_TIMES * 5; // 商品(列表&详情)缓存时间 | ||
16 | +const RECENT_CODE_CACHE_TIME = MINUTE_TIMES; // 最近获取记录缓存时间 | ||
15 | const MAX_JOIN_TIMES = 2; // 最大活动参与次数 | 17 | const MAX_JOIN_TIMES = 2; // 最大活动参与次数 |
16 | 18 | ||
17 | const userTimesCache = new MemoryCache(); | 19 | const userTimesCache = new MemoryCache(); |
18 | -const productCache = new MemoryCache(300); | ||
19 | 20 | ||
20 | function handelResult(result) { | 21 | function handelResult(result) { |
21 | return { | 22 | return { |
@@ -57,16 +58,6 @@ module.exports = class extends global.yoho.BaseModel { | @@ -57,16 +58,6 @@ module.exports = class extends global.yoho.BaseModel { | ||
57 | status = parseInt(status, 10); | 58 | status = parseInt(status, 10); |
58 | page = parseInt(page, 10) || 1; | 59 | page = parseInt(page, 10) || 1; |
59 | 60 | ||
60 | - const listCacheKey = `list_${actId}_${status}_${page}_${status}`; | ||
61 | - | ||
62 | - if (!extra.noCache) { | ||
63 | - let cacheList = productCache.get(listCacheKey); | ||
64 | - | ||
65 | - if (!_.isUndefined(cacheList)) { | ||
66 | - return handelResult(cacheList); | ||
67 | - } | ||
68 | - } | ||
69 | - | ||
70 | status = _.isNaN(status) ? '> 0' : `= ${status}`; | 61 | status = _.isNaN(status) ? '> 0' : `= ${status}`; |
71 | 62 | ||
72 | let limit = `${(page - 1) * pageSize},${page * pageSize}`; | 63 | let limit = `${(page - 1) * pageSize},${page * pageSize}`; |
@@ -74,11 +65,9 @@ module.exports = class extends global.yoho.BaseModel { | @@ -74,11 +65,9 @@ module.exports = class extends global.yoho.BaseModel { | ||
74 | return mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} | 65 | return mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} |
75 | where act_id = :actId and status ${status} limit ${limit}`, { | 66 | where act_id = :actId and status ${status} limit ${limit}`, { |
76 | actId | 67 | actId |
77 | - }).then(result => { | ||
78 | - productCache.set(listCacheKey, result, CACHE_TIMES); | ||
79 | - | ||
80 | - return handelResult(result); | ||
81 | - }); | 68 | + }, { |
69 | + cache: extra.noCache ? 0 : PRODUCT_CACHE_TIMES | ||
70 | + }).then(handelResult); | ||
82 | } | 71 | } |
83 | 72 | ||
84 | /** | 73 | /** |
@@ -114,21 +103,15 @@ module.exports = class extends global.yoho.BaseModel { | @@ -114,21 +103,15 @@ module.exports = class extends global.yoho.BaseModel { | ||
114 | return Promise.resolve(handelResult(resData)); | 103 | return Promise.resolve(handelResult(resData)); |
115 | } | 104 | } |
116 | 105 | ||
117 | - const contentCacheKey = `content_${actPrizeId}`; | ||
118 | - | ||
119 | - if (!extra.noCache) { | ||
120 | - let cacheContent = productCache.get(contentCacheKey); | ||
121 | - | ||
122 | - if (!_.isUndefined(cacheContent)) { | ||
123 | - return handelResult(cacheContent); | ||
124 | - } | ||
125 | - } | ||
126 | - | ||
127 | return Promise.all([ | 106 | return Promise.all([ |
128 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} | 107 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} |
129 | - where id = :actPrizeId limit 1;`, {actPrizeId}), | 108 | + where id = :actPrizeId limit 1;`, {actPrizeId}, { |
109 | + cache: extra.noCache ? 0 : PRODUCT_CACHE_TIMES | ||
110 | + }), | ||
130 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} | 111 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} |
131 | - where act_prize_id = :actPrizeId;`, {actPrizeId}) | 112 | + where act_prize_id = :actPrizeId;`, {actPrizeId}, { |
113 | + cache: extra.noCache ? 0 : PRODUCT_CACHE_TIMES | ||
114 | + }) | ||
132 | ]).then(result => { | 115 | ]).then(result => { |
133 | let [product, content] = result; | 116 | let [product, content] = result; |
134 | 117 | ||
@@ -139,20 +122,27 @@ module.exports = class extends global.yoho.BaseModel { | @@ -139,20 +122,27 @@ module.exports = class extends global.yoho.BaseModel { | ||
139 | }); | 122 | }); |
140 | } | 123 | } |
141 | 124 | ||
142 | - productCache.set(contentCacheKey, resData, CACHE_TIMES); | ||
143 | - | ||
144 | return resData; | 125 | return resData; |
145 | }).then(handelResult); | 126 | }).then(handelResult); |
146 | } | 127 | } |
147 | 128 | ||
148 | /** | 129 | /** |
149 | * 0元购抽奖码最近获取记录 | 130 | * 0元购抽奖码最近获取记录 |
131 | + * @param actId | ||
150 | * @returns {*} | 132 | * @returns {*} |
151 | */ | 133 | */ |
152 | - getCodeRecent() { | 134 | + getCodeRecent(actId) { |
135 | + actId = parseInt(actId, 10) || 0; | ||
136 | + | ||
153 | return mysqlCli.query(`select user_name, user_thumb, create_time | 137 | return mysqlCli.query(`select user_name, user_thumb, create_time |
154 | - from ${TABLE_ACT_PRIZE_PRODUCT_USER} | ||
155 | - order by u.create_time desc limit 10;`).then(handelResult); | 138 | + from ${TABLE_ACT_PRIZE_PRODUCT_USER} where act_id = :actId |
139 | + order by u.create_time desc limit 10;`, { | ||
140 | + actId | ||
141 | + }, { | ||
142 | + cache: RECENT_CODE_CACHE_TIME | ||
143 | + }).then(result => { | ||
144 | + return handelResult(result); | ||
145 | + }); | ||
156 | } | 146 | } |
157 | 147 | ||
158 | /** | 148 | /** |
@@ -184,7 +174,7 @@ module.exports = class extends global.yoho.BaseModel { | @@ -184,7 +174,7 @@ module.exports = class extends global.yoho.BaseModel { | ||
184 | 174 | ||
185 | let info = await Promise.all([ | 175 | let info = await Promise.all([ |
186 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} | 176 | mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} |
187 | - where id = :actPrizeId limit 1;`, {actPrizeId}), | 177 | + where id = :actPrizeId limit 1;`, {actPrizeId}, {cache: MINUTE_TIMES / 2}), |
188 | mysqlCli.query(`select count(distinct uid) as join_num from ${TABLE_ACT_PRIZE_PRODUCT_USER} | 178 | mysqlCli.query(`select count(distinct uid) as join_num from ${TABLE_ACT_PRIZE_PRODUCT_USER} |
189 | where act_prize_id = :actPrizeId;`, {actPrizeId}) | 179 | where act_prize_id = :actPrizeId;`, {actPrizeId}) |
190 | ]); | 180 | ]); |
@@ -241,7 +231,7 @@ module.exports = class extends global.yoho.BaseModel { | @@ -241,7 +231,7 @@ module.exports = class extends global.yoho.BaseModel { | ||
241 | */ | 231 | */ |
242 | async sendPrizeCode(uid, actPrizeId, extra = {}) { | 232 | async sendPrizeCode(uid, actPrizeId, extra = {}) { |
243 | // 查询用户参与次数 | 233 | // 查询用户参与次数 |
244 | - const TimesCacheKey = `${actPrizeId}_${uid}`; | 234 | + const TimesCacheKey = `times_${actPrizeId}_${uid}`; |
245 | 235 | ||
246 | let userJoinTimes = userTimesCache.get(TimesCacheKey); | 236 | let userJoinTimes = userTimesCache.get(TimesCacheKey); |
247 | 237 | ||
@@ -252,6 +242,7 @@ module.exports = class extends global.yoho.BaseModel { | @@ -252,6 +242,7 @@ module.exports = class extends global.yoho.BaseModel { | ||
252 | uid | 242 | uid |
253 | }); | 243 | }); |
254 | 244 | ||
245 | + // 用户参与次数超限(业务缓存) | ||
255 | if (userJoinTimes >= MAX_JOIN_TIMES) { | 246 | if (userJoinTimes >= MAX_JOIN_TIMES) { |
256 | userTimesCache.set(TimesCacheKey, userJoinTimes); | 247 | userTimesCache.set(TimesCacheKey, userJoinTimes); |
257 | } | 248 | } |
@@ -67,6 +67,7 @@ | @@ -67,6 +67,7 @@ | ||
67 | "plupload": "^2.3.3", | 67 | "plupload": "^2.3.3", |
68 | "qiniu": "^7.0.4", | 68 | "qiniu": "^7.0.4", |
69 | "qiniu-js": "^1.0.22", | 69 | "qiniu-js": "^1.0.22", |
70 | + "querystring": "^0.2.0", | ||
70 | "request": "^2.81.0", | 71 | "request": "^2.81.0", |
71 | "request-promise": "^4.2.1", | 72 | "request-promise": "^4.2.1", |
72 | "semver": "^5.3.0", | 73 | "semver": "^5.3.0", |
@@ -6,74 +6,77 @@ | @@ -6,74 +6,77 @@ | ||
6 | 6 | ||
7 | const _ = require('lodash'); | 7 | const _ = require('lodash'); |
8 | 8 | ||
9 | -function _clearArray(list, key) { | ||
10 | - _.remove(list, (n) => { | ||
11 | - return n === key; | ||
12 | - }); | ||
13 | -} | ||
14 | 9 | ||
15 | -function _clearObject(obj, key) { | ||
16 | - delete obj[key]; | ||
17 | -} | ||
18 | - | ||
19 | -function _getNowTime() { | ||
20 | - return new Date().getTime() / 1000; | ||
21 | -} | ||
22 | - | ||
23 | -module.exports = function memoryCache(maxLength = 1000) { | ||
24 | - let cache = {}; | ||
25 | - let mapList = []; | 10 | +module.exports = class memoryCache { |
11 | + constructor(options) { | ||
12 | + this.options = Object.assign({}, options); | ||
13 | + this.cache = {}; | ||
14 | + this.map = []; | ||
15 | + | ||
16 | + this.options.maxLength = parseInt(this.options.maxLength, 10) || 1000; | ||
17 | + } | ||
18 | + _deleteCache(key) { | ||
19 | + delete this.cache[key]; | ||
20 | + } | ||
21 | + _deleteMap(key) { | ||
22 | + _.remove(this.map, (n) => { | ||
23 | + return n === key; | ||
24 | + }); | ||
25 | + } | ||
26 | + _getNowTime() { | ||
27 | + return new Date().getTime() / 1000; | ||
28 | + } | ||
26 | 29 | ||
27 | // 获取缓存数据 | 30 | // 获取缓存数据 |
28 | - this.get = (key) => { | ||
29 | - if (!cache.hasOwnProperty(key)) { | 31 | + get(key) { |
32 | + if (!this.cache.hasOwnProperty(key)) { | ||
30 | return; | 33 | return; |
31 | } | 34 | } |
32 | 35 | ||
33 | - let info = cache[key]; | 36 | + let info = this.cache[key]; |
34 | 37 | ||
35 | // 校验过期时间 | 38 | // 校验过期时间 |
36 | - if (info.exptime && info.exptime - _getNowTime() < 0) { | 39 | + if (info.exptime && info.exptime - this._getNowTime() < 0) { |
37 | this.clear(key); | 40 | this.clear(key); |
38 | return; | 41 | return; |
39 | } | 42 | } |
40 | 43 | ||
41 | return info.value; | 44 | return info.value; |
42 | - }; | 45 | + } |
43 | 46 | ||
44 | // 设置缓存数据 | 47 | // 设置缓存数据 |
45 | - this.set = (key, value, exptime) => { | ||
46 | - cache.hasOwnProperty(key) && _clearArray(mapList, key); | 48 | + set(key, value, exptime) { |
49 | + this.cache.hasOwnProperty(key) && this._deleteMap(key); | ||
47 | 50 | ||
48 | - mapList.push(key); | ||
49 | - cache[key] = { | 51 | + this.map.push(key); |
52 | + this.cache[key] = { | ||
50 | value, | 53 | value, |
51 | - exptime: exptime ? (exptime + _getNowTime()) : 0 // 过期时间 | 54 | + exptime: exptime ? (exptime + this._getNowTime()) : 0 // 过期时间 |
52 | }; | 55 | }; |
53 | 56 | ||
57 | + const maxLength = this.options.maxLength; | ||
58 | + | ||
54 | // 清除老旧数据 | 59 | // 清除老旧数据 |
55 | - if (mapList.length > maxLength) { | ||
56 | - let len = mapList.length - maxLength; | 60 | + if (this.map.length > maxLength) { |
61 | + let len = this.map.length - maxLength; | ||
57 | 62 | ||
58 | for (let i = 0; i < len; i++) { | 63 | for (let i = 0; i < len; i++) { |
59 | - _clearObject(cache, mapList.shift()); | 64 | + this._deleteCache(this.map.shift()); |
60 | } | 65 | } |
61 | } | 66 | } |
62 | - }; | 67 | + } |
63 | 68 | ||
64 | // 清除单条缓存数据 | 69 | // 清除单条缓存数据 |
65 | - this.clear = (key) => { | ||
66 | - if (cache.hasOwnProperty(key)) { | ||
67 | - _clearArray(mapList, key); | ||
68 | - _clearObject(cache, key); | 70 | + clear(key) { |
71 | + if (this.cache.hasOwnProperty(key)) { | ||
72 | + this._deleteMap(key); | ||
73 | + this._deleteCache(key); | ||
69 | } | 74 | } |
70 | - }; | 75 | + } |
71 | 76 | ||
72 | // 清除所有缓存数据 | 77 | // 清除所有缓存数据 |
73 | - this.clearAll = () => { | ||
74 | - cache = {}; | ||
75 | - mapList = []; | ||
76 | - }; | ||
77 | - | ||
78 | - return this; | 78 | + clearAll() { |
79 | + this.cache = {}; | ||
80 | + this.map = []; | ||
81 | + } | ||
79 | }; | 82 | }; |
1 | const mysql = require('mysql'); | 1 | const mysql = require('mysql'); |
2 | const _ = require('lodash'); | 2 | const _ = require('lodash'); |
3 | +const md5 = require('yoho-md5'); | ||
4 | +const qs = require('querystring'); | ||
5 | +const MemoryCache = require('./memory-cache'); | ||
3 | 6 | ||
4 | class SqlHelper { | 7 | class SqlHelper { |
5 | constructor(database) { | 8 | constructor(database) { |
6 | this.config = global.yoho.config.mysql; | 9 | this.config = global.yoho.config.mysql; |
7 | this.logger = global.yoho.logger; | 10 | this.logger = global.yoho.logger; |
11 | + this.memoryCache = new MemoryCache(); | ||
8 | database = database || 'mysql'; | 12 | database = database || 'mysql'; |
9 | this.createPool(database); | 13 | this.createPool(database); |
10 | } | 14 | } |
@@ -37,8 +41,8 @@ class SqlHelper { | @@ -37,8 +41,8 @@ class SqlHelper { | ||
37 | }); | 41 | }); |
38 | }); | 42 | }); |
39 | } | 43 | } |
40 | - query(sql, params) { | ||
41 | - return this.execute(sql, params); | 44 | + query(sql, params, options) { |
45 | + return this.execute(sql, params, options); | ||
42 | } | 46 | } |
43 | delete(sql, params) { | 47 | delete(sql, params) { |
44 | return this.execute(sql, params).then(result => { | 48 | return this.execute(sql, params).then(result => { |
@@ -55,7 +59,21 @@ class SqlHelper { | @@ -55,7 +59,21 @@ class SqlHelper { | ||
55 | return result.insertId; | 59 | return result.insertId; |
56 | }); | 60 | }); |
57 | } | 61 | } |
58 | - execute(sql, params) { | 62 | + execute(sql, params, options = {}) { |
63 | + let cache = parseInt(options.cache, 10) || 0; | ||
64 | + let cacheKey; | ||
65 | + | ||
66 | + // 读取缓存 | ||
67 | + if (cache) { | ||
68 | + cacheKey = md5(`${sql}${qs.stringify(params)}${cache}`); | ||
69 | + | ||
70 | + let cacheResult = this.memoryCache.get(cacheKey); | ||
71 | + | ||
72 | + if (!_.isUndefined(cacheResult)) { | ||
73 | + return Promise.resolve(cacheResult); | ||
74 | + } | ||
75 | + } | ||
76 | + | ||
59 | return new Promise((resolve, reject) => { | 77 | return new Promise((resolve, reject) => { |
60 | this.getConnection().then(connection => { | 78 | this.getConnection().then(connection => { |
61 | connection.query(sql, params, (queryErr, result) => { | 79 | connection.query(sql, params, (queryErr, result) => { |
@@ -64,6 +82,8 @@ class SqlHelper { | @@ -64,6 +82,8 @@ class SqlHelper { | ||
64 | this.logger.error(queryErr); | 82 | this.logger.error(queryErr); |
65 | reject(queryErr); | 83 | reject(queryErr); |
66 | } else { | 84 | } else { |
85 | + // 写入缓存 | ||
86 | + cache && this.memoryCache.set(cacheKey, result, cache); | ||
67 | resolve(result); | 87 | resolve(result); |
68 | } | 88 | } |
69 | }); | 89 | }); |
@@ -7986,6 +7986,10 @@ querystring@0.2.0: | @@ -7986,6 +7986,10 @@ querystring@0.2.0: | ||
7986 | version "0.2.0" | 7986 | version "0.2.0" |
7987 | resolved "http://npm.yohops.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" | 7987 | resolved "http://npm.yohops.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" |
7988 | 7988 | ||
7989 | +querystring@^0.2.0: | ||
7990 | + version "0.2.0" | ||
7991 | + resolved "http://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" | ||
7992 | + | ||
7989 | querystringify@0.0.x: | 7993 | querystringify@0.0.x: |
7990 | version "0.0.4" | 7994 | version "0.0.4" |
7991 | resolved "http://npm.yohops.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" | 7995 | resolved "http://npm.yohops.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" |
-
Please register or login to post a comment