Merge branch 'feature/page-cache' of http://git.yoho.cn/OPENTECH/yoho-node-ci in…
…to feature/page-cache
Showing
14 changed files
with
582 additions
and
60 deletions
apps/models/cdn_cache.js
0 → 100644
1 | +/** | ||
2 | + * | ||
3 | + * @author: chenfeng<feng.chen@yoho.cn> | ||
4 | + * @date: 16/10/19 | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict'; | ||
8 | +import Model from './model'; | ||
9 | +import utils from 'utility'; | ||
10 | +import rp from 'request-promise'; | ||
11 | +import ws from '../../lib/ws'; | ||
12 | + | ||
13 | +class CdnCache extends Model { | ||
14 | + constructor() { | ||
15 | + super('cdn_page'); | ||
16 | + } | ||
17 | + async removeCache(queryUris, objectType) { | ||
18 | + let self = this; | ||
19 | + self._requestApi({ | ||
20 | + Action: 'RefreshObjectCaches', | ||
21 | + ObjectPath: queryUris, | ||
22 | + ObjectType: objectType | ||
23 | + }) | ||
24 | + } | ||
25 | + async _requestApi(params) { | ||
26 | + let self = this; | ||
27 | + let cdns = await self.findAll(); | ||
28 | + | ||
29 | + if (!cdns.length) { | ||
30 | + return; | ||
31 | + } | ||
32 | + params = Object.assign(params, { | ||
33 | + Format: 'JSON', | ||
34 | + Version: '2014-11-11', | ||
35 | + AccessKeyId: cdns[0].keyId, | ||
36 | + SignatureMethod: 'HMAC-SHA1', | ||
37 | + TimeStamp: self._getUtcTime(new Date()), | ||
38 | + SignatureVersion: '1.0', | ||
39 | + SignatureNonce: parseInt(Math.random() * 100000, 10) + '' | ||
40 | + }); | ||
41 | + let sign = self._sign(params, cdns[0].keySecret); | ||
42 | + params.Signature = sign; | ||
43 | + rp({ | ||
44 | + uri: `${cdns[0].scheme}://${cdns[0].cdnApi}`, | ||
45 | + qs: params, | ||
46 | + json: true | ||
47 | + }) | ||
48 | + .then(function (res) { | ||
49 | + self._broadcast(`清理提交成功,RefreshTaskId:${res.RefreshTaskId}`) | ||
50 | + }) | ||
51 | + .catch(function (err) { | ||
52 | + self._broadcast(`清理失败:${err.response.body}`) | ||
53 | + }); | ||
54 | + | ||
55 | + } | ||
56 | + _getUtcTime(date) { | ||
57 | + let year = date.getUTCFullYear(); | ||
58 | + let month = date.getUTCMonth() + 1; | ||
59 | + let day = date.getUTCDate() < 10 ? '0' + date.getUTCDate() : date.getUTCDate(); | ||
60 | + let hour = date.getUTCHours() < 10 ? '0' + date.getUTCHours() : date.getUTCHours(); | ||
61 | + let minute = date.getUTCMinutes() < 10 ? '0' + date.getUTCMinutes() : date.getUTCMinutes(); | ||
62 | + let second = date.getUTCSeconds() < 10 ? '0' + date.getUTCSeconds() : date.getUTCSeconds(); | ||
63 | + month = month < 10 ? '0' + month : month; | ||
64 | + | ||
65 | + return `${year}-${month}-${day}T${hour}:${minute}:${second}Z` | ||
66 | + } | ||
67 | + _sign(params, keySecret) { | ||
68 | + let data = {}; | ||
69 | + Object.keys(params).sort().forEach(k => data[k]=params[k]); | ||
70 | + let signString = ''; | ||
71 | + Object.keys(data).forEach(k => { | ||
72 | + data[k] = encodeURIComponent(data[k]) | ||
73 | + signString += `&${k}=${data[k]}`; | ||
74 | + }); | ||
75 | + if (signString) { | ||
76 | + signString = `GET&%2F&${encodeURIComponent(signString.substring(1, signString.length))}`; | ||
77 | + let sign = utils.hmac('sha1', keySecret + '&', signString); | ||
78 | + return sign; | ||
79 | + } | ||
80 | + return ''; | ||
81 | + } | ||
82 | + _broadcast(message) { | ||
83 | + console.log(message) | ||
84 | + ws.broadcast(`/cdn_cache/log`, { | ||
85 | + message: message | ||
86 | + }); | ||
87 | + } | ||
88 | + async init() { | ||
89 | + let count = await this.count({}); | ||
90 | + if (count === 0) { | ||
91 | + await this.insert({ | ||
92 | + scheme: 'https', | ||
93 | + cdnApi: 'cdn.aliyuncs.com', | ||
94 | + keyId: 'Mt6m3xVdWddj8bDe', | ||
95 | + keySecret: 'ExHpmJJ7ayJEEMz2LUffKRe3ehMGDs' | ||
96 | + }) | ||
97 | + } | ||
98 | + } | ||
99 | +} | ||
100 | + | ||
101 | +export default CdnCache; |
@@ -11,6 +11,8 @@ import UserModel from './user'; | @@ -11,6 +11,8 @@ import UserModel from './user'; | ||
11 | import HotfixModel from './hotfix'; | 11 | import HotfixModel from './hotfix'; |
12 | import OperationLoggerModel from './operation_logger'; | 12 | import OperationLoggerModel from './operation_logger'; |
13 | import PageCacheModel from './page_cache'; | 13 | import PageCacheModel from './page_cache'; |
14 | +import CdnCacheModel from './cdn_cache'; | ||
15 | +import ProductCacheModel from './product_cache'; | ||
14 | import MemcachedHostModel from './memcached_host'; | 16 | import MemcachedHostModel from './memcached_host'; |
15 | import DegradeModel from './degrade'; | 17 | import DegradeModel from './degrade'; |
16 | import DegradeServerModel from './degrade_server'; | 18 | import DegradeServerModel from './degrade_server'; |
@@ -27,12 +29,16 @@ const User = new UserModel(); | @@ -27,12 +29,16 @@ const User = new UserModel(); | ||
27 | const Hotfix = new HotfixModel(); | 29 | const Hotfix = new HotfixModel(); |
28 | const OperationLogger = new OperationLoggerModel(); | 30 | const OperationLogger = new OperationLoggerModel(); |
29 | const PageCache = new PageCacheModel(); | 31 | const PageCache = new PageCacheModel(); |
32 | +const CdnCache = new CdnCacheModel(); | ||
33 | +const ProductCache = new ProductCacheModel(); | ||
30 | const MemcachedHost = new MemcachedHostModel(); | 34 | const MemcachedHost = new MemcachedHostModel(); |
31 | const Degrade = new DegradeModel(); | 35 | const Degrade = new DegradeModel(); |
32 | const DegradeServer = new DegradeServerModel(); | 36 | const DegradeServer = new DegradeServerModel(); |
33 | 37 | ||
34 | User.init(); | 38 | User.init(); |
35 | PageCache.init(); | 39 | PageCache.init(); |
40 | +CdnCache.init(); | ||
41 | +ProductCache.init(); | ||
36 | 42 | ||
37 | Degrade.init(); | 43 | Degrade.init(); |
38 | 44 | ||
@@ -45,6 +51,8 @@ export { | @@ -45,6 +51,8 @@ export { | ||
45 | Hotfix, | 51 | Hotfix, |
46 | OperationLogger, | 52 | OperationLogger, |
47 | PageCache, | 53 | PageCache, |
54 | + CdnCache, | ||
55 | + ProductCache, | ||
48 | MemcachedHost, | 56 | MemcachedHost, |
49 | RestartInfo, | 57 | RestartInfo, |
50 | DeleteRestartInfo, | 58 | DeleteRestartInfo, |
@@ -28,7 +28,7 @@ class PageCahe extends Model { | @@ -28,7 +28,7 @@ class PageCahe extends Model { | ||
28 | * @param {[array]} keys [key列表] | 28 | * @param {[array]} keys [key列表] |
29 | * @param {[string]} storeTableName [pc和wap的标识] | 29 | * @param {[string]} storeTableName [pc和wap的标识] |
30 | */ | 30 | */ |
31 | - async removeCache(queryUris, storeTableName) { | 31 | + async removeCache(queryUris, storeTableName, serverType) { |
32 | let self = this; | 32 | let self = this; |
33 | let queryUriList = queryUris.split('\n'); | 33 | let queryUriList = queryUris.split('\n'); |
34 | 34 | ||
@@ -49,8 +49,7 @@ class PageCahe extends Model { | @@ -49,8 +49,7 @@ class PageCahe extends Model { | ||
49 | // } | 49 | // } |
50 | 50 | ||
51 | } | 51 | } |
52 | - let servers = await self.findAll(); | ||
53 | - | 52 | + let servers = await self.find({server: { $in: serverType }}); |
54 | self._broadcast(`共${servers.length}台nginx准备清理..`) | 53 | self._broadcast(`共${servers.length}台nginx准备清理..`) |
55 | for (let i = 0; i < servers.length; i++) { | 54 | for (let i = 0; i < servers.length; i++) { |
56 | try { | 55 | try { |
@@ -67,9 +66,9 @@ class PageCahe extends Model { | @@ -67,9 +66,9 @@ class PageCahe extends Model { | ||
67 | * [全量清理缓存] | 66 | * [全量清理缓存] |
68 | * @param {[string]} storeTableName [pc和wap的标识] | 67 | * @param {[string]} storeTableName [pc和wap的标识] |
69 | */ | 68 | */ |
70 | - async removeAllCache(storeTableName) { | 69 | + async removeAllCache(storeTableName, serverType) { |
71 | let self = this; | 70 | let self = this; |
72 | - let servers = await self.findAll(); | 71 | + let servers = await self.find({server: { $in: serverType }}); |
73 | 72 | ||
74 | self._broadcast(`共${servers.length}台nginx准备清理`) | 73 | self._broadcast(`共${servers.length}台nginx准备清理`) |
75 | for (let i = 0; i < servers.length; i++) { | 74 | for (let i = 0; i < servers.length; i++) { |
@@ -222,15 +221,26 @@ class PageCahe extends Model { | @@ -222,15 +221,26 @@ class PageCahe extends Model { | ||
222 | // password: '1', | 221 | // password: '1', |
223 | // port: 22, | 222 | // port: 22, |
224 | // tag: 'nginx2', | 223 | // tag: 'nginx2', |
225 | - // cachepath: '/usr/local/nginx' | 224 | + // cachepath: '/usr/local/nginx', |
225 | + // server: 'qCloud' | ||
226 | + // }); | ||
227 | + // await this.insert({ | ||
228 | + // host: '127.0.0.1', | ||
229 | + // username: 'chenfeng', | ||
230 | + // password: '1', | ||
231 | + // port: 22, | ||
232 | + // tag: 'nginx2', | ||
233 | + // cachepath: '/usr/local/nginx', | ||
234 | + // server: 'AWS' | ||
226 | // }); | 235 | // }); |
227 | // await this.insert({ | 236 | // await this.insert({ |
228 | // host: '10.66.1.2', | 237 | // host: '10.66.1.2', |
229 | - // username: 'node', | 238 | + // username: 'www', |
230 | // password: 'yoho9646', | 239 | // password: 'yoho9646', |
231 | // port: 22, | 240 | // port: 22, |
232 | // tag: 'nginx2', | 241 | // tag: 'nginx2', |
233 | - // cachepath: '/usr/local/openresty/nginx' | 242 | + // cachepath: '/usr/local/openresty/nginx', |
243 | + // server: 'qCloud' | ||
234 | // }); | 244 | // }); |
235 | await this.insert({ | 245 | await this.insert({ |
236 | host: '10.66.1.3', | 246 | host: '10.66.1.3', |
@@ -238,32 +248,54 @@ class PageCahe extends Model { | @@ -238,32 +248,54 @@ class PageCahe extends Model { | ||
238 | password: 'yoho9646', | 248 | password: 'yoho9646', |
239 | port: 22, | 249 | port: 22, |
240 | tag: 'nginx3', | 250 | tag: 'nginx3', |
241 | - cachepath: '/usr/local/openresty/nginx' | 251 | + cachepath: '/usr/local/openresty/nginx', |
252 | + server: 'qCloud' | ||
242 | }); | 253 | }); |
243 | // await this.insert({ | 254 | // await this.insert({ |
244 | // host: '10.66.1.15', | 255 | // host: '10.66.1.15', |
245 | - // username: 'node', | 256 | + // username: 'www', |
246 | // password: 'yoho9646', | 257 | // password: 'yoho9646', |
247 | // port: 22, | 258 | // port: 22, |
248 | // tag: 'nginx15', | 259 | // tag: 'nginx15', |
249 | - // cachepath: '/usr/local/openresty/nginx' | 260 | + // cachepath: '/usr/local/openresty/nginx', |
261 | + // server: 'qCloud' | ||
250 | // }); | 262 | // }); |
251 | // await this.insert({ | 263 | // await this.insert({ |
252 | // host: '10.66.1.84', | 264 | // host: '10.66.1.84', |
253 | - // username: 'node', | 265 | + // username: 'www', |
254 | // password: 'yoho9646', | 266 | // password: 'yoho9646', |
255 | // port: 22, | 267 | // port: 22, |
256 | // tag: 'nginx84', | 268 | // tag: 'nginx84', |
257 | - // cachepath: '/usr/local/openresty/nginx' | 269 | + // cachepath: '/usr/local/openresty/nginx', |
270 | + // server: 'qCloud' | ||
258 | // }); | 271 | // }); |
259 | // await this.insert({ | 272 | // await this.insert({ |
260 | // host: '10.66.1.97', | 273 | // host: '10.66.1.97', |
261 | - // username: 'node', | 274 | + // username: 'www', |
262 | // password: 'yoho9646', | 275 | // password: 'yoho9646', |
263 | // port: 22, | 276 | // port: 22, |
264 | // tag: 'nginx97', | 277 | // tag: 'nginx97', |
265 | - // cachepath: '/usr/local/openresty/nginx' | 278 | + // cachepath: '/usr/local/openresty/nginx', |
279 | + // server: 'qCloud' | ||
266 | // }); | 280 | // }); |
281 | + await this.insert({ | ||
282 | + host: '172.31.23.111', | ||
283 | + username: 'www', | ||
284 | + password: 'yoho9646', | ||
285 | + port: 22, | ||
286 | + tag: 'aws1', | ||
287 | + cachepath: '/usr/local/openresty/nginx', | ||
288 | + server: 'AWS' | ||
289 | + }); | ||
290 | + await this.insert({ | ||
291 | + host: '172.31.21.139', | ||
292 | + username: 'www', | ||
293 | + password: 'yoho9646', | ||
294 | + port: 22, | ||
295 | + tag: 'aws2', | ||
296 | + cachepath: '/usr/local/openresty/nginx', | ||
297 | + server: 'AWS' | ||
298 | + }); | ||
267 | } | 299 | } |
268 | } | 300 | } |
269 | } | 301 | } |
apps/models/product_cache.js
0 → 100644
1 | +/** | ||
2 | + * | ||
3 | + * @author: chenfeng<feng.chen@yoho.cn> | ||
4 | + * @date: 16/10/20 | ||
5 | + */ | ||
6 | + | ||
7 | +import Model from './model'; | ||
8 | +import rp from 'request-promise'; | ||
9 | +import ws from '../../lib/ws'; | ||
10 | + | ||
11 | +class ProductCache extends Model{ | ||
12 | + constructor() { | ||
13 | + super('product_cache'); | ||
14 | + } | ||
15 | + async removePriceCache(list) { | ||
16 | + let self = this; | ||
17 | + let apis = await self.findAll(); | ||
18 | + | ||
19 | + if (!apis.length) { | ||
20 | + return; | ||
21 | + } | ||
22 | + let url = apis[0].priceCacheApi; | ||
23 | + await self._batchPost(list, url); | ||
24 | + } | ||
25 | + async removeProductCache(list) { | ||
26 | + let self = this; | ||
27 | + let apis = await self.findAll(); | ||
28 | + | ||
29 | + if (!apis.length) { | ||
30 | + return; | ||
31 | + } | ||
32 | + let url = apis[0].productCacheApi; | ||
33 | + await self._batchPost(list, url); | ||
34 | + } | ||
35 | + async _batchPost(list, url) { | ||
36 | + let self = this; | ||
37 | + let interval = 2; | ||
38 | + return new Promise(async (resolve, reject) => { | ||
39 | + let tick = parseInt(list.length / interval, 10) + (list.length % interval > 0 ? 1 : 0); | ||
40 | + let post = async (i, len) => { | ||
41 | + if (i < len) { | ||
42 | + let limit = list.length > (i + 1) * interval ? (i + 1) * interval : list.length; | ||
43 | + let datas = list.slice(i * interval, limit); | ||
44 | + try { | ||
45 | + await self._postApi(datas, url); | ||
46 | + self._broadcast(`进度:${limit}/${list.length}`) | ||
47 | + } catch(err) { | ||
48 | + self._broadcast(`错误:${err.message}`) | ||
49 | + } | ||
50 | + setTimeout(async () => { | ||
51 | + await post(++i, tick); | ||
52 | + }, 500); | ||
53 | + } else { | ||
54 | + resolve(); | ||
55 | + } | ||
56 | + } | ||
57 | + await post(0, tick); | ||
58 | + }); | ||
59 | + } | ||
60 | + async _postApi(data, url) { | ||
61 | + return new Promise((resolve, reject) => { | ||
62 | + rp({ | ||
63 | + method: 'POST', | ||
64 | + uri: url, | ||
65 | + body: data, | ||
66 | + json: true | ||
67 | + }) | ||
68 | + .then(function (res) { | ||
69 | + res.code === 200 ? resolve(res) : reject(res); | ||
70 | + }) | ||
71 | + .catch(function (err) { | ||
72 | + console.log(err.response.body); | ||
73 | + reject(err.response.body) | ||
74 | + }); | ||
75 | + }) | ||
76 | + | ||
77 | + } | ||
78 | + _broadcast(message) { | ||
79 | + console.log(message) | ||
80 | + ws.broadcast(`/product_cache/log`, { | ||
81 | + message: message | ||
82 | + }); | ||
83 | + } | ||
84 | + async init() { | ||
85 | + let count = await this.count({}); | ||
86 | + | ||
87 | + if (count === 0) { | ||
88 | + await this.insert({ | ||
89 | + priceCacheApi: 'http://service-test3.yohops.com:9999/erp/clear/batch/productPriceCache', | ||
90 | + productCacheApi: 'http://service-test3.yohops.com:9999/erp/clear/batch/productCache' | ||
91 | + }); | ||
92 | + } | ||
93 | + } | ||
94 | +} | ||
95 | +export default ProductCache; |
apps/web/actions/cdn_cache.js
0 → 100644
1 | +/** | ||
2 | + * | ||
3 | + * @author: chenfeng<feng.chen@yoho.cn> | ||
4 | + * @date: 16/10/19 | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +import Router from 'koa-router'; | ||
10 | +import { | ||
11 | + CdnCache | ||
12 | +} from '../../models' | ||
13 | + | ||
14 | +const r = new Router(); | ||
15 | + | ||
16 | +const cdnCache = { | ||
17 | + async query(ctx) { | ||
18 | + let date = { | ||
19 | + typeList: [{ | ||
20 | + name: '文件', | ||
21 | + typeName: 'File', | ||
22 | + }, { | ||
23 | + name: '目录', | ||
24 | + typeName: 'Directory', | ||
25 | + }] | ||
26 | + } | ||
27 | + await ctx.render('action/cdn_cache', date); | ||
28 | + }, | ||
29 | + async clear(ctx) { | ||
30 | + let queryUris = ctx.request.body.query_uri; | ||
31 | + let objectType = ctx.request.body.object_type; | ||
32 | + if (queryUris.trim() && objectType) { | ||
33 | + CdnCache.removeCache(queryUris, objectType); | ||
34 | + } | ||
35 | + return ctx.body = { | ||
36 | + code: 200 | ||
37 | + }; | ||
38 | + } | ||
39 | +} | ||
40 | +r.get('/query', cdnCache.query); | ||
41 | +r.post('/clear', cdnCache.clear); | ||
42 | + | ||
43 | +export default r; |
@@ -24,6 +24,11 @@ const pageCahe = { | @@ -24,6 +24,11 @@ const pageCahe = { | ||
24 | tableName: 'ngx_cache_wap', | 24 | tableName: 'ngx_cache_wap', |
25 | name: 'Wap' | 25 | name: 'Wap' |
26 | }], | 26 | }], |
27 | + serverList: [{ | ||
28 | + name: 'AWS' | ||
29 | + }, { | ||
30 | + name: 'qCloud' | ||
31 | + }], | ||
27 | count: 0 | 32 | count: 0 |
28 | }; | 33 | }; |
29 | await ctx.render('action/page_cache', data); | 34 | await ctx.render('action/page_cache', data); |
@@ -31,16 +36,25 @@ const pageCahe = { | @@ -31,16 +36,25 @@ const pageCahe = { | ||
31 | async clear(ctx) { | 36 | async clear(ctx) { |
32 | let queryUris = ctx.request.body.query_uri; | 37 | let queryUris = ctx.request.body.query_uri; |
33 | let storeTableName = ctx.request.body.table_name; | 38 | let storeTableName = ctx.request.body.table_name; |
34 | - if (queryUris && storeTableName) { | ||
35 | - await PageCache.removeCache(queryUris, storeTableName); | 39 | + let serverType = ctx.request.body.server; |
40 | + let servers = serverType.split(',').filter(server => server); | ||
41 | + if (queryUris && storeTableName && servers.length) { | ||
42 | + PageCache.removeCache(queryUris, storeTableName, servers); | ||
36 | } | 43 | } |
37 | - | 44 | + return ctx.body = { |
45 | + code: 200 | ||
46 | + }; | ||
38 | }, | 47 | }, |
39 | async clearAll(ctx) { | 48 | async clearAll(ctx) { |
40 | let storeTableName = ctx.request.body.table_name; | 49 | let storeTableName = ctx.request.body.table_name; |
41 | - if (storeTableName) { | ||
42 | - await PageCache.removeAllCache(storeTableName); | 50 | + let serverType = ctx.request.body.server; |
51 | + let servers = serverType.split(',').filter(server => server); | ||
52 | + if (storeTableName && servers.length) { | ||
53 | + PageCache.removeAllCache(storeTableName, servers); | ||
43 | } | 54 | } |
55 | + return ctx.body = { | ||
56 | + code: 200 | ||
57 | + }; | ||
44 | } | 58 | } |
45 | } | 59 | } |
46 | r.get('/query', pageCahe.query); | 60 | r.get('/query', pageCahe.query); |
apps/web/actions/product_cache.js
0 → 100644
1 | +/** | ||
2 | + * | ||
3 | + * @author: chenfeng<feng.chen@yoho.cn> | ||
4 | + * @date: 16/10/19 | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +import Router from 'koa-router'; | ||
10 | +import { | ||
11 | + ProductCache | ||
12 | +} from '../../models' | ||
13 | + | ||
14 | +const r = new Router(); | ||
15 | + | ||
16 | +const productCache = { | ||
17 | + async query(ctx) { | ||
18 | + await ctx.render('action/product_cache'); | ||
19 | + }, | ||
20 | + async clear(ctx) { | ||
21 | + let type = ctx.request.body.type; | ||
22 | + if (type) { | ||
23 | + ProductCache.removePriceCache([51068877, 51068893, 51117073]) | ||
24 | + } | ||
25 | + return ctx.body = { | ||
26 | + code: 200 | ||
27 | + }; | ||
28 | + } | ||
29 | +} | ||
30 | + | ||
31 | +r.get('/query', productCache.query); | ||
32 | +r.post('/clear', productCache.clear); | ||
33 | + | ||
34 | +export default r; |
@@ -9,7 +9,9 @@ import monitor from './actions/monitor'; | @@ -9,7 +9,9 @@ import monitor from './actions/monitor'; | ||
9 | import users from './actions/users'; | 9 | import users from './actions/users'; |
10 | import hotfix from './actions/hotfix'; | 10 | import hotfix from './actions/hotfix'; |
11 | import operationLog from './actions/operation_log'; | 11 | import operationLog from './actions/operation_log'; |
12 | -import pageCahe from './actions/page_cache'; | 12 | +import pageCache from './actions/page_cache'; |
13 | +import cdnCache from './actions/cdn_cache'; | ||
14 | +import productCache from './actions/product_cache'; | ||
13 | import apiCache from './actions/api_cache'; | 15 | import apiCache from './actions/api_cache'; |
14 | import degrade from './actions/degrade'; | 16 | import degrade from './actions/degrade'; |
15 | 17 | ||
@@ -37,9 +39,10 @@ export default function (app) { | @@ -37,9 +39,10 @@ export default function (app) { | ||
37 | base.use('/users', users.routes(), users.allowedMethods()); | 39 | base.use('/users', users.routes(), users.allowedMethods()); |
38 | base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods()); | 40 | base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods()); |
39 | base.use('/operation', operationLog.routes(), operationLog.allowedMethods()); | 41 | base.use('/operation', operationLog.routes(), operationLog.allowedMethods()); |
40 | - base.use('/page_cache', pageCahe.routes(), pageCahe.allowedMethods()); | 42 | + base.use('/page_cache', pageCache.routes(), pageCache.allowedMethods()); |
43 | + base.use('/cdn_cache', cdnCache.routes(), cdnCache.allowedMethods()); | ||
44 | + base.use('/product_cache', productCache.routes(), productCache.allowedMethods()); | ||
41 | base.use('/api_cache', apiCache.routes(), apiCache.allowedMethods()); | 45 | base.use('/api_cache', apiCache.routes(), apiCache.allowedMethods()); |
42 | - | ||
43 | base.use('/degrade', degrade.routes(), degrade.allowedMethods()); | 46 | base.use('/degrade', degrade.routes(), degrade.allowedMethods()); |
44 | 47 | ||
45 | base.use('', index.routes(), index.allowedMethods()); | 48 | base.use('', index.routes(), index.allowedMethods()); |
apps/web/views/action/cdn_cache.hbs
0 → 100644
1 | +<div class="pageheader"> | ||
2 | + <div class="media"> | ||
3 | + <div class="pageicon pull-left"> | ||
4 | + <i class="fa fa-th-list"></i> | ||
5 | + </div> | ||
6 | + <div class="media-body"> | ||
7 | + <ul class="breadcrumb"> | ||
8 | + <li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li> | ||
9 | + <li><a href="/servers">缓存管理</a></li> | ||
10 | + </ul> | ||
11 | + <h4>清理CdnCahe缓存</h4> | ||
12 | + </div> | ||
13 | + </div> | ||
14 | + <!-- media --> | ||
15 | +</div> | ||
16 | + | ||
17 | +<div class="contentpanel"> | ||
18 | + <div class="row cache-panel"> | ||
19 | + <div class="panel panel-default"> | ||
20 | + <div class="panel-body"> | ||
21 | + <div class="col-sm-6"> | ||
22 | + <div class="operations mb20"> | ||
23 | + | ||
24 | + </div> | ||
25 | + <div class="query"> | ||
26 | + <textarea name="" id="uri" cols="30" rows="20" class="form-control" placeholder="支持多条换行输入"></textarea> | ||
27 | + </div> | ||
28 | + </div> | ||
29 | + <div class="col-sm-6"> | ||
30 | + <div class="panel"> | ||
31 | + <div class="panel-heading"> | ||
32 | + <h4 class="panel-title">日志</h4> | ||
33 | + </div><!-- panel-heading --> | ||
34 | + <div class="panel-body yoho-log-dark"> | ||
35 | + <div class="results-list "> | ||
36 | + | ||
37 | + </div><!-- results-list --> | ||
38 | + </div><!-- panel-body --> | ||
39 | + </div><!-- panel --> | ||
40 | + </div> | ||
41 | + </div> | ||
42 | + <div class="panel-footer"> | ||
43 | + <select id="objectType" class="form-control input-sm selcet-auto pull-left mr20"> | ||
44 | + {{#each typeList}} | ||
45 | + <option value="{{typeName}}">{{name}}</option> | ||
46 | + {{/each}} | ||
47 | + </select> | ||
48 | + <button class="btn btn-warning btn-clear pull-left">清除</button> | ||
49 | + <div class="result pull-left ml20"></div> | ||
50 | + </div> | ||
51 | + </div> | ||
52 | + </div> | ||
53 | +</div> | ||
54 | + | ||
55 | +<script> | ||
56 | + var posing = false; | ||
57 | + $(document).on('ready pjax:success', function() { | ||
58 | + $('.btn-clear').click(function() { | ||
59 | + var typeName = $('#objectType').val(); | ||
60 | + var uri = $('#uri').val(); | ||
61 | + if (uri && typeName) { | ||
62 | + $logs.empty(); | ||
63 | + $.post('/cdn_cache/clear', { | ||
64 | + query_uri: uri, | ||
65 | + object_type: typeName | ||
66 | + }, function(res) { | ||
67 | + }); | ||
68 | + } | ||
69 | + }) | ||
70 | + | ||
71 | + function layoutResize() { | ||
72 | + $('.yoho-log-dark').height($('body').height() - 450); | ||
73 | + } | ||
74 | + | ||
75 | + $(window).resize(function() { | ||
76 | + layoutResize(); | ||
77 | + }); | ||
78 | + | ||
79 | + layoutResize(); | ||
80 | + var $logs = $('.yoho-log-dark .results-list'); | ||
81 | + var $dark = $('.yoho-log-dark'); | ||
82 | + function appendLog(message) { | ||
83 | + var html = '<p><span class="message">- ' + message + '</span></p>'; | ||
84 | + $logs.append(html); | ||
85 | + $dark.scrollTop($logs[0].scrollHeight); | ||
86 | + } | ||
87 | + | ||
88 | + var ws = io(); | ||
89 | + ws.on('connect', function() { | ||
90 | + ws.on('/cdn_cache/log', function(data) { | ||
91 | + appendLog(data.message) | ||
92 | + }); | ||
93 | + }); | ||
94 | + | ||
95 | + }); | ||
96 | +</script> |
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | <li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li> | 8 | <li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li> |
9 | <li><a href="/servers">缓存管理</a></li> | 9 | <li><a href="/servers">缓存管理</a></li> |
10 | </ul> | 10 | </ul> |
11 | - <h4>清理缓存</h4> | 11 | + <h4>清理PageCahe缓存</h4> |
12 | </div> | 12 | </div> |
13 | </div> | 13 | </div> |
14 | <!-- media --> | 14 | <!-- media --> |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | 23 | ||
24 | </div> | 24 | </div> |
25 | <div class="query"> | 25 | <div class="query"> |
26 | - <textarea name="" id="uri" cols="30" rows="20" class="form-control" placeholder="支持多条换行输入">http://m.yohobuy.com</textarea> | 26 | + <textarea name="" id="uri" cols="30" rows="20" class="form-control" placeholder="支持多条换行输入"></textarea> |
27 | </div> | 27 | </div> |
28 | </div> | 28 | </div> |
29 | <div class="col-sm-6"> | 29 | <div class="col-sm-6"> |
@@ -39,7 +39,17 @@ | @@ -39,7 +39,17 @@ | ||
39 | </div><!-- panel --> | 39 | </div><!-- panel --> |
40 | </div> | 40 | </div> |
41 | </div> | 41 | </div> |
42 | - <div class="panel-footer"> | 42 | + <div class="panel-footer "> |
43 | + <div class="ckbox ckbox-primary pull-left mr20"> | ||
44 | + <input type="checkbox" id="chk_aws" value="AWS" name="server" checked="checked"> | ||
45 | + <label for="chk_aws">AWS</label> | ||
46 | + </div> | ||
47 | + | ||
48 | + <div class="ckbox ckbox-primary pull-left mr20"> | ||
49 | + <input type="checkbox" value="qCloud" id="chk_qcloud" name="server" checked="checked"> | ||
50 | + <label for="chk_qcloud">qCloud</label> | ||
51 | + </div> | ||
52 | + | ||
43 | <select id="stores" class="form-control input-sm selcet-auto pull-left mr20"> | 53 | <select id="stores" class="form-control input-sm selcet-auto pull-left mr20"> |
44 | {{#each storeList}} | 54 | {{#each storeList}} |
45 | <option value="{{tableName}}">{{name}}</option> | 55 | <option value="{{tableName}}">{{name}}</option> |
@@ -56,49 +66,34 @@ | @@ -56,49 +66,34 @@ | ||
56 | <script> | 66 | <script> |
57 | var posing = false; | 67 | var posing = false; |
58 | $(document).on('ready pjax:success', function() { | 68 | $(document).on('ready pjax:success', function() { |
59 | - $('.btn-success').click(function() { | ||
60 | - if (posing) { | ||
61 | - return; | ||
62 | - } | ||
63 | - posing = true; | ||
64 | - $('.page-count>span').text('查询中..'); | ||
65 | - $('.btn-search').addClass('disabled'); | ||
66 | - var tableName = $('#stores').val(); | ||
67 | - var uri = $('#uri').val(); | ||
68 | - if (uri && tableName) { | ||
69 | - $.post('/page_cache/search', { | ||
70 | - query_uri: uri, | ||
71 | - table_name: tableName | ||
72 | - }, function (res) { | ||
73 | - posing = false; | ||
74 | - $('.btn-search').removeClass('disabled'); | ||
75 | - if (res.code === 200) { | ||
76 | - $('.page-count>span').text(res.data); | ||
77 | - } else { | ||
78 | - $('.page-count>span').text('查询失败'); | ||
79 | - } | ||
80 | - | ||
81 | - }) | ||
82 | - } | ||
83 | - }); | ||
84 | $('.btn-clear').click(function() { | 69 | $('.btn-clear').click(function() { |
70 | + var servers = ""; | ||
71 | + $(':checkbox[name="server"]:checked').each(function() { | ||
72 | + servers += $(this).val() + ','; | ||
73 | + }) | ||
85 | var tableName = $('#stores').val(); | 74 | var tableName = $('#stores').val(); |
86 | var uri = $('#uri').val(); | 75 | var uri = $('#uri').val(); |
87 | - if (uri && tableName) { | 76 | + if (uri && tableName && servers) { |
88 | $logs.empty(); | 77 | $logs.empty(); |
89 | $.post('/page_cache/clear', { | 78 | $.post('/page_cache/clear', { |
90 | query_uri: uri, | 79 | query_uri: uri, |
91 | - table_name: tableName | 80 | + table_name: tableName, |
81 | + server: servers | ||
92 | }, function(res) { | 82 | }, function(res) { |
93 | }); | 83 | }); |
94 | } | 84 | } |
95 | }) | 85 | }) |
96 | $('.btn-all-clear').click(function() { | 86 | $('.btn-all-clear').click(function() { |
87 | + var servers = ""; | ||
88 | + $(':checkbox[name="server"]:checked').each(function() { | ||
89 | + servers += $(this).val() + ','; | ||
90 | + }) | ||
97 | var tableName = $('#stores').val(); | 91 | var tableName = $('#stores').val(); |
98 | - if (tableName) { | 92 | + if (tableName && servers) { |
99 | $logs.empty(); | 93 | $logs.empty(); |
100 | $.post('/page_cache/clear/all', { | 94 | $.post('/page_cache/clear/all', { |
101 | - table_name: tableName | 95 | + table_name: tableName, |
96 | + server: servers | ||
102 | }, function(res) { | 97 | }, function(res) { |
103 | }); | 98 | }); |
104 | } | 99 | } |
apps/web/views/action/product_cache.hbs
0 → 100644
1 | +<div class="pageheader"> | ||
2 | + <div class="media"> | ||
3 | + <div class="pageicon pull-left"> | ||
4 | + <i class="fa fa-th-list"></i> | ||
5 | + </div> | ||
6 | + <div class="media-body"> | ||
7 | + <ul class="breadcrumb"> | ||
8 | + <li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li> | ||
9 | + <li><a href="/servers">缓存管理</a></li> | ||
10 | + </ul> | ||
11 | + <h4>清理商品缓存</h4> | ||
12 | + </div> | ||
13 | + </div> | ||
14 | + <!-- media --> | ||
15 | +</div> | ||
16 | + | ||
17 | +<div class="contentpanel"> | ||
18 | + <div class="row cache-panel"> | ||
19 | + <div class="panel panel-default"> | ||
20 | + <div class="panel-body"> | ||
21 | + <div class="col-sm-6"> | ||
22 | + <div class="operations mb20"> | ||
23 | + | ||
24 | + </div> | ||
25 | + <div class="query"> | ||
26 | + <textarea name="" id="uri" cols="30" rows="20" class="form-control" placeholder="支持多条换行输入"></textarea> | ||
27 | + </div> | ||
28 | + </div> | ||
29 | + <div class="col-sm-6"> | ||
30 | + <div class="panel"> | ||
31 | + <div class="panel-heading"> | ||
32 | + <h4 class="panel-title">日志</h4> | ||
33 | + </div><!-- panel-heading --> | ||
34 | + <div class="panel-body yoho-log-dark"> | ||
35 | + <div class="results-list "> | ||
36 | + | ||
37 | + </div><!-- results-list --> | ||
38 | + </div><!-- panel-body --> | ||
39 | + </div><!-- panel --> | ||
40 | + </div> | ||
41 | + </div> | ||
42 | + <div class="panel-footer"> | ||
43 | + <select id="selectType" class="form-control input-sm selcet-auto pull-left mr20"> | ||
44 | + <option value="1">批量变价</option> | ||
45 | + <option value="2">其它批量</option> | ||
46 | + </select> | ||
47 | + <button class="btn btn-warning btn-clear pull-left">清除</button> | ||
48 | + <div class="result pull-left ml20"></div> | ||
49 | + </div> | ||
50 | + </div> | ||
51 | + </div> | ||
52 | +</div> | ||
53 | + | ||
54 | +<script> | ||
55 | + var posing = false; | ||
56 | + $(document).on('ready pjax:success', function() { | ||
57 | + $('.btn-clear').click(function() { | ||
58 | + var selectType = $('#selectType').val(); | ||
59 | + if (selectType) { | ||
60 | + $logs.empty(); | ||
61 | + $.post('/product_cache/clear', { | ||
62 | + type: selectType | ||
63 | + }, function(res) { | ||
64 | + }); | ||
65 | + } | ||
66 | + }) | ||
67 | + | ||
68 | + function layoutResize() { | ||
69 | + $('.yoho-log-dark').height($('body').height() - 450); | ||
70 | + } | ||
71 | + | ||
72 | + $(window).resize(function() { | ||
73 | + layoutResize(); | ||
74 | + }); | ||
75 | + | ||
76 | + layoutResize(); | ||
77 | + var $logs = $('.yoho-log-dark .results-list'); | ||
78 | + var $dark = $('.yoho-log-dark'); | ||
79 | + function appendLog(message) { | ||
80 | + var html = '<p><span class="message">- ' + message + '</span></p>'; | ||
81 | + $logs.append(html); | ||
82 | + $dark.scrollTop($logs[0].scrollHeight); | ||
83 | + } | ||
84 | + | ||
85 | + var ws = io(); | ||
86 | + ws.on('connect', function() { | ||
87 | + ws.on('/product_cache/log', function(data) { | ||
88 | + appendLog(data.message) | ||
89 | + }); | ||
90 | + }); | ||
91 | + | ||
92 | + }); | ||
93 | +</script> |
@@ -75,14 +75,20 @@ | @@ -75,14 +75,20 @@ | ||
75 | <span class="label label-serstatus"></span> | 75 | <span class="label label-serstatus"></span> |
76 | </div> | 76 | </div> |
77 | <div class="clearfix mt5"> | 77 | <div class="clearfix mt5"> |
78 | - <div class="col-xs-3 project-env" data-env="test"> | 78 | + <div class="col-xs-4 project-env" data-env="test"> |
79 | <h5 class="md-title mt10">当前状态</h5> | 79 | <h5 class="md-title mt10">当前状态</h5> |
80 | + </div> | ||
81 | + <div class="col-xs-4"> | ||
82 | + <h5 class="md-title mt10">进程状态</h5> | ||
83 | + </div> | ||
84 | + </div> | ||
85 | + <div class="clearfix mt5"> | ||
86 | + <div class="col-xs-4 project-env" data-env="test"> | ||
80 | <span class="label label-success deploy-log-btn" data-host="{{host}}"><i | 87 | <span class="label label-success deploy-log-btn" data-host="{{host}}"><i |
81 | class="fa fa-spinner fa-spin fa-fw margin-bottom"></i> <b>{{#if info}}{{info.state}}{{^}} | 88 | class="fa fa-spinner fa-spin fa-fw margin-bottom"></i> <b>{{#if info}}{{info.state}}{{^}} |
82 | 未知部署{{/if}}</b></span> | 89 | 未知部署{{/if}}</b></span> |
83 | </div> | 90 | </div> |
84 | - <div class="col-xs-3"> | ||
85 | - <h5 class="md-title mt10">进程状态</h5> | 91 | + <div class="col-xs-4"> |
86 | <span class="label label-status"></span> | 92 | <span class="label label-status"></span> |
87 | </div> | 93 | </div> |
88 | </div> | 94 | </div> |
@@ -28,8 +28,9 @@ | @@ -28,8 +28,9 @@ | ||
28 | <li class="parent"><a href=""><i class="fa fa-history"></i> <span>缓存管理</span></a> | 28 | <li class="parent"><a href=""><i class="fa fa-history"></i> <span>缓存管理</span></a> |
29 | <ul class="children"> | 29 | <ul class="children"> |
30 | <li><a href="/page_cache/query">PageCahe清理</a></li> | 30 | <li><a href="/page_cache/query">PageCahe清理</a></li> |
31 | + {{!-- <li><a href="/cdn_cache/query">CDN清理</a></li> | ||
32 | + <li><a href="/product_cache/query">商品清理</a></li> --}} | ||
31 | <li><a href="/api_cache">ApiCahe清理</a></li> | 33 | <li><a href="/api_cache">ApiCahe清理</a></li> |
32 | - {{!-- <li><a href="/cdn_cache/query">CDN清理</a></li> --}} | ||
33 | </ul> | 34 | </ul> |
34 | </li> | 35 | </li> |
35 | {{#if is_master}} | 36 | {{#if is_master}} |
@@ -62,7 +62,8 @@ | @@ -62,7 +62,8 @@ | ||
62 | "shelljs": "^0.7.0", | 62 | "shelljs": "^0.7.0", |
63 | "socket.io": "^1.4.6", | 63 | "socket.io": "^1.4.6", |
64 | "ssh2": "^0.5.0", | 64 | "ssh2": "^0.5.0", |
65 | - "tar": "^2.2.1" | 65 | + "tar": "^2.2.1", |
66 | + "utility": "^1.8.0" | ||
66 | }, | 67 | }, |
67 | "devDependencies": { | 68 | "devDependencies": { |
68 | "ava": "^0.14.0", | 69 | "ava": "^0.14.0", |
-
Please register or login to post a comment