-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
89 lines (81 loc) · 2.39 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const Joi = require('@hapi/joi');
const schema = Joi.object().keys({
ioredis: Joi.object().required().unknown(),
prefix: Joi.string().required(),
index: Joi.string().required(),
ttl: Joi.number().min(0),
ttlRenewOnWrite: Joi.boolean(),
ttlRenewOnRead: Joi.boolean()
});
class TaskLogCache {
constructor(options){
Object.assign(this,options);
}
async summary(){
const categories = await this.ioredis.smembers(this.index);
if (categories.length===0) return {};
let transaction = this.ioredis.multi();
categories.forEach((k)=>{transaction = transaction.llen(this.prefix+k);});
const counts = await transaction.exec();
const result = {};
categories.forEach((k,i)=>{result[k]=counts[i][1];});
return result;
}
async push(k, status){
const listKey = this.prefix+k;
const stringified = (typeof(status)==="string")? status: JSON.stringify(status);
const firstTransaction = (
this
.ioredis
.multi()
.sadd(this.index,k)
.rpush(listKey,stringified)
);
const firstResult = await firstTransaction.exec();
if (this.ttl>0){
const additionalCategory = firstResult[0][1];
if (additionalCategory || this.ttlRenewOnWrite) {
await this.ioredis.expire(listKey, this.ttl);
}
}
return firstResult[1][1]; // new length of status list
}
async get(key, ifrom=0, ito=-1){
const listKey = this.prefix+key;
if ((this.ttl>0) && (this.ttlRenewOnRead)){
await this.ioredis.expire(listKey,this.ttl);
}
const result = await this.ioredis.lrange(listKey,ifrom,ito);
return result.map((s)=>((s.startsWith("{"))?(JSON.parse(s)):s));
}
async delete(key){
const listKey = this.prefix+key;
await(
this
.ioredis
.multi()
.srem(this.index,key)
.del(listKey)
.exec()
);
}
async reap(){
const all = await this.summary();
const emptyList = Object.keys(all).filter((k)=>(all[k]===0));
if (emptyList.length>0){
let transaction = (
this
.ioredis
.multi()
.srem(this.index,emptyList)
.del(emptyList.map((k)=>(this.prefix+k)))
);
await transaction.exec();
}
}
}
module.exports = function (options) {
const { error, value } = Joi.validate(options,schema);
if (error!==null) throw new Error("TaskLogCache initialization error: "+error);
return new TaskLogCache(value);
};