UNPKG

10.1 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __importDefault = (this && this.__importDefault) || function (mod) {
12 return (mod && mod.__esModule) ? mod : { "default": mod };
13};
14Object.defineProperty(exports, "__esModule", { value: true });
15const Util_1 = require("./Util");
16const fs_1 = require("fs");
17const path_1 = require("path");
18const exec_pools_1 = require("./exec_pools");
19const cluster_1 = __importDefault(require("cluster"));
20// 先提供一个同步版本的获取信息
21class CacheMoudle {
22 constructor(name, ttl, keep) {
23 this.valueCache = {};
24 this.getfresh = false;
25 this.ttl = 0;
26 this.name = '';
27 this.change = false;
28 this.name = name || '';
29 this.ttl = ttl || this.ttl;
30 keep = keep || { type: "unknow" };
31 switch (keep.type) {
32 case 'mongo':
33 this.loader = new Keep_Mongo(this.name, keep);
34 break;
35 case 'file': {
36 this.loader = new Keep_File(this.name, keep);
37 break;
38 }
39 default: {
40 this.loader = new Keep_base(this.name, keep);
41 break;
42 }
43 }
44 }
45 /**5s 检查一次 */
46 static init() {
47 if (this.handle) {
48 this.handle.stop();
49 }
50 this.handle = Util_1.Util.setInterval(CacheMoudle.update.bind(CacheMoudle), 5 * 1000);
51 return Promise.resolve();
52 }
53 /**
54 * 创建cache
55 * @param name 模块名字 如果没有名字将不支持自动update功能
56 * @param ttl 数据有效期 等于0的时候不更新 小于0的时候不计算ttl
57 */
58 static createCache(name, ttl, keep) {
59 if (name == undefined) {
60 return new CacheMoudle(name, ttl, keep);
61 }
62 else {
63 if (!this.cacheMap.hasOwnProperty(name)) {
64 this.cacheMap[name] = new CacheMoudle(name, ttl, keep);
65 }
66 this.thread = Math.ceil(Math.sqrt(Object.keys(this.cacheMap).length));
67 return this.cacheMap[name];
68 }
69 }
70 // 移除cache
71 static removeCache(name) {
72 delete this.cacheMap[name];
73 }
74 static update() {
75 return __awaiter(this, void 0, void 0, function* () {
76 let curr = Date.now();
77 let list = [];
78 for (let key in CacheMoudle.cacheMap) {
79 let unit = CacheMoudle.cacheMap[key];
80 list.push(unit._update.bind(unit));
81 }
82 yield exec_pools_1.execPools(list, this.thread, curr);
83 return Promise.resolve();
84 });
85 }
86 init() {
87 return __awaiter(this, void 0, void 0, function* () {
88 if (!this.loader)
89 return true;
90 this.valueCache = yield this.loader.load();
91 return true;
92 });
93 }
94 /**
95 *
96 * @param key
97 * @param value 内容
98 * @param time 当 ttl 大于等于0时设置的当前时间或者不设置,ttl小于0时设置过期的时间
99 */
100 set(key, value, time) {
101 return __awaiter(this, void 0, void 0, function* () {
102 let change = false;
103 if (!this.valueCache.hasOwnProperty(key)) {
104 this.valueCache[key] = { value: value, time: time || Date.now() };
105 change = true;
106 }
107 else {
108 if (time && this.valueCache[key].time != time) {
109 this.valueCache[key].time = time;
110 change = true;
111 }
112 if (this.valueCache[key].value != value || JSON.stringify(this.valueCache[key].value) != JSON.stringify(value)) {
113 this.valueCache[key].value = value;
114 change = true;
115 }
116 }
117 if (change)
118 yield this.loader.set(key, this.valueCache[key].value, this.valueCache[key].time);
119 return true;
120 });
121 }
122 has(key) {
123 return this.hasOwnProperty(key);
124 }
125 hasOwnProperty(key) {
126 return this.valueCache.hasOwnProperty(key);
127 }
128 get(key) {
129 if (this.valueCache.hasOwnProperty(key)) {
130 if (this.getfresh && this.ttl > 0) {
131 this.valueCache[key].time = Date.now();
132 }
133 return this.valueCache[key].value;
134 }
135 else
136 return undefined;
137 }
138 del(key) {
139 return __awaiter(this, void 0, void 0, function* () {
140 if (!this.valueCache.hasOwnProperty(key))
141 return;
142 delete this.valueCache[key];
143 return yield this.loader.del(key);
144 });
145 }
146 /**
147 * 遍历内容
148 * @param cb 当方法返回 true时 结束遍历(break)
149 */
150 forEach(cb) {
151 for (let key in this.valueCache) {
152 if (cb(this.valueCache[key].value, key)) {
153 return this.valueCache[key].value;
154 }
155 }
156 return undefined;
157 }
158 clear() {
159 this.valueCache = {};
160 this.change = true;
161 }
162 _update(curr) {
163 return __awaiter(this, void 0, void 0, function* () {
164 // 增加淘汰算法空间
165 if (this.ttl == 0) {
166 yield this.loader.save();
167 return;
168 }
169 let ttl = this.ttl;
170 if (ttl < 0)
171 ttl = 0;
172 for (let key in this.valueCache) {
173 let unit = this.valueCache[key];
174 if (unit.time + ttl < curr) {
175 yield this.del(key);
176 }
177 }
178 yield this.loader.save();
179 return;
180 });
181 }
182}
183exports.CacheMoudle = CacheMoudle;
184CacheMoudle.thread = 1;
185CacheMoudle.cacheMap = {};
186class Keep_base {
187 constructor(name, keep) {
188 }
189 set(key, value) {
190 return __awaiter(this, void 0, void 0, function* () {
191 return true;
192 });
193 }
194 load() {
195 return __awaiter(this, void 0, void 0, function* () {
196 return {};
197 });
198 }
199 save() {
200 return __awaiter(this, void 0, void 0, function* () {
201 return true;
202 });
203 }
204 del(key) {
205 return __awaiter(this, void 0, void 0, function* () {
206 return true;
207 });
208 }
209}
210class Keep_Mongo {
211 constructor(name, keep) {
212 this._data = {};
213 this.keep = keep;
214 this.name = name;
215 }
216 load() {
217 return __awaiter(this, void 0, void 0, function* () {
218 let list = yield this.keep.path.get_list(this.name, {}).load();
219 for (let i = 0; i < list.length; i++) {
220 let unit = list.get_at(i);
221 if (!unit)
222 continue;
223 this._data[unit._id] = { value: unit.value, time: unit.time };
224 }
225 return this._data;
226 });
227 }
228 set(key, value, time) {
229 return __awaiter(this, void 0, void 0, function* () {
230 this._data[key] = { value: value, time: time };
231 this.keep.path.update(this.name, { _id: key }, { value: value, time: time }, true);
232 });
233 }
234 save() {
235 return __awaiter(this, void 0, void 0, function* () {
236 return;
237 });
238 }
239 del(key) {
240 return __awaiter(this, void 0, void 0, function* () {
241 if (!this._data.hasOwnProperty(key)) {
242 return;
243 }
244 delete this._data[key];
245 yield this.keep.path.del(this.name, { _id: key });
246 return true;
247 });
248 }
249}
250class Keep_File {
251 constructor(name, keep) {
252 this._data = {};
253 this._change = false;
254 this.keep = keep;
255 this.name = name;
256 }
257 load() {
258 return __awaiter(this, void 0, void 0, function* () {
259 if (!this.keep.path || typeof this.keep.path != 'string') {
260 return this._data;
261 }
262 let preID = cluster_1.default.isWorker ? cluster_1.default.worker.id.toString() : '';
263 try {
264 this._data = JSON.parse(fs_1.readFileSync(path_1.join(this.keep.path, this.name + '|' + preID + '.json')).toString() || "{}");
265 }
266 catch (e) {
267 }
268 return this._data;
269 });
270 }
271 save() {
272 return __awaiter(this, void 0, void 0, function* () {
273 if (!this._change)
274 return;
275 if (!fs_1.existsSync(this.keep.path))
276 fs_1.mkdirSync(this.keep.path, { recursive: true });
277 fs_1.writeFileSync(path_1.join(this.keep.path, this.name + '.json'), JSON.stringify(this._data, null, 4), { flag: 'w+' });
278 return;
279 });
280 }
281 set(key, value, time) {
282 return __awaiter(this, void 0, void 0, function* () {
283 this._data[key] = { value, time };
284 this._change = true;
285 });
286 }
287 del(key) {
288 return __awaiter(this, void 0, void 0, function* () {
289 if (!this._data.hasOwnProperty(key)) {
290 return;
291 }
292 this._change = true;
293 delete this._data[key];
294 return true;
295 });
296 }
297}