@less-is-more/less-js 1.4.42 → 1.5.0-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cache.js +30 -12
- package/src/index.js +2 -0
- package/src/nas.js +293 -0
- package/test/test-nas.js +122 -0
package/package.json
CHANGED
package/src/cache.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const Redis = require("./redis");
|
|
2
2
|
const Param = require("./param");
|
|
3
3
|
const zlib = require("zlib");
|
|
4
|
+
const Nas = require("./nas");
|
|
4
5
|
|
|
5
6
|
module.exports = class Cache {
|
|
6
7
|
/**
|
|
@@ -39,9 +40,17 @@ module.exports = class Cache {
|
|
|
39
40
|
* @param {*} args 直接传arguments,用于拼接缓存key
|
|
40
41
|
* @param {function} fn 没有缓存的实现
|
|
41
42
|
* @param {boolean} zip 是否压缩
|
|
43
|
+
* @param {boolean} useNas 是否使用Nas缓存
|
|
42
44
|
* @returns 优先返回对象
|
|
43
45
|
*/
|
|
44
|
-
static async auto(
|
|
46
|
+
static async auto(
|
|
47
|
+
keyPrefix,
|
|
48
|
+
timeSecond,
|
|
49
|
+
args,
|
|
50
|
+
fn,
|
|
51
|
+
zip = false,
|
|
52
|
+
useNas = false
|
|
53
|
+
) {
|
|
45
54
|
let fullKey = keyPrefix;
|
|
46
55
|
for (let i = 0; i < args.length; i++) {
|
|
47
56
|
fullKey += ":" + args[i].toString();
|
|
@@ -50,7 +59,11 @@ module.exports = class Cache {
|
|
|
50
59
|
let savedData = Cache._getLocal(fullKey);
|
|
51
60
|
let hasLocal = false;
|
|
52
61
|
if (Param.isBlank(savedData)) {
|
|
53
|
-
|
|
62
|
+
if (useNas) {
|
|
63
|
+
savedData = Nas.get(fullKey);
|
|
64
|
+
} else {
|
|
65
|
+
savedData = await Redis.exec("get", fullKey);
|
|
66
|
+
}
|
|
54
67
|
if (!Param.isBlank(savedData)) {
|
|
55
68
|
// 本地缓存1分钟
|
|
56
69
|
Cache._setLocal(fullKey, savedData, 60000);
|
|
@@ -61,24 +74,29 @@ module.exports = class Cache {
|
|
|
61
74
|
if (savedData == null) {
|
|
62
75
|
let result = await fn();
|
|
63
76
|
if (!Param.isBlank(result)) {
|
|
64
|
-
let
|
|
77
|
+
let saveContent = "";
|
|
65
78
|
// 处理JSON
|
|
66
79
|
if (result instanceof Object) {
|
|
67
80
|
if (result.success === false) {
|
|
68
81
|
console.log("Do not cache fail result");
|
|
69
82
|
} else {
|
|
70
|
-
|
|
83
|
+
saveContent = JSON.stringify(result);
|
|
71
84
|
}
|
|
72
85
|
} else {
|
|
73
|
-
|
|
86
|
+
saveContent = result.toString();
|
|
74
87
|
}
|
|
75
|
-
if (
|
|
76
|
-
if (Cache._needZip(
|
|
77
|
-
|
|
88
|
+
if (saveContent != "") {
|
|
89
|
+
if (Cache._needZip(saveContent, zip)) {
|
|
90
|
+
saveContent = Cache._zip(saveContent);
|
|
91
|
+
}
|
|
92
|
+
if (useNas) {
|
|
93
|
+
Nas.set(fullKey, saveContent, timeSecond);
|
|
94
|
+
} else {
|
|
95
|
+
await Redis.exec("setex", fullKey, timeSecond + "", saveContent);
|
|
78
96
|
}
|
|
79
|
-
|
|
97
|
+
|
|
80
98
|
// 本地缓存1分钟
|
|
81
|
-
Cache._setLocal(fullKey,
|
|
99
|
+
Cache._setLocal(fullKey, saveContent, 60000);
|
|
82
100
|
}
|
|
83
101
|
return result;
|
|
84
102
|
}
|
|
@@ -86,9 +104,9 @@ module.exports = class Cache {
|
|
|
86
104
|
console.log("Found cache" + (hasLocal ? " local" : ""), fullKey);
|
|
87
105
|
savedData = Cache._unzip(savedData);
|
|
88
106
|
// 优先转成json
|
|
89
|
-
|
|
107
|
+
try {
|
|
90
108
|
return JSON.parse(savedData);
|
|
91
|
-
}
|
|
109
|
+
} catch (e) {
|
|
92
110
|
return savedData;
|
|
93
111
|
}
|
|
94
112
|
}
|
package/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var Service = require("./service.js");
|
|
|
9
9
|
var Oss = require("./oss.js");
|
|
10
10
|
var GroupMessage = require("./group-message.js");
|
|
11
11
|
var JsonKit = require("./json-kit.js");
|
|
12
|
+
var Nas = require("./nas.js");
|
|
12
13
|
module.exports = {
|
|
13
14
|
Ret,
|
|
14
15
|
Router,
|
|
@@ -21,4 +22,5 @@ module.exports = {
|
|
|
21
22
|
Oss,
|
|
22
23
|
GroupMessage,
|
|
23
24
|
JsonKit,
|
|
25
|
+
Nas,
|
|
24
26
|
};
|
package/src/nas.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const os = require("os");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 本地硬盘缓存实现类
|
|
7
|
+
* 提供类似Redis的缓存功能,支持超时时间
|
|
8
|
+
* 适用于多服务器共享NAS存储
|
|
9
|
+
*/
|
|
10
|
+
class Nas {
|
|
11
|
+
static _getCacheDir() {
|
|
12
|
+
let cacheDir = null;
|
|
13
|
+
|
|
14
|
+
// 如果提供了缓存目录参数,则使用该目录,否则使用默认目录
|
|
15
|
+
const defaultCacheDir = path.join(os.tmpdir(), "cache");
|
|
16
|
+
cacheDir =
|
|
17
|
+
cacheDir || (fs.existsSync("/cache") ? "/cache" : defaultCacheDir);
|
|
18
|
+
|
|
19
|
+
// 确保缓存目录存在
|
|
20
|
+
try {
|
|
21
|
+
if (!fs.existsSync(cacheDir)) {
|
|
22
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.error("创建缓存目录失败:", cacheDir, e);
|
|
26
|
+
}
|
|
27
|
+
return cacheDir;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 获取缓存值
|
|
32
|
+
* @param {string} key - 缓存键
|
|
33
|
+
* @returns {any} 缓存值,如果过期或不存在则返回null
|
|
34
|
+
*/
|
|
35
|
+
static get(key) {
|
|
36
|
+
return Nas._loadFromDisk(key);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 获取缓存值,如果不存在则返回默认值
|
|
41
|
+
* @param {string} key - 缓存键
|
|
42
|
+
* @param {any} defaultValue - 默认值
|
|
43
|
+
* @returns {any} 缓存值或默认值
|
|
44
|
+
*/
|
|
45
|
+
static getOrDefault(key, defaultValue) {
|
|
46
|
+
const value = Nas.get(key);
|
|
47
|
+
return value !== null ? value : defaultValue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 设置缓存值
|
|
52
|
+
* @param {string} key - 缓存键
|
|
53
|
+
* @param {any} value - 缓存值
|
|
54
|
+
* @param {number} timeout - 超时时间(秒),-1表示永不过期
|
|
55
|
+
*/
|
|
56
|
+
static set(key, value, timeout = -1) {
|
|
57
|
+
const expireTime = timeout === -1 ? -1 : Date.now() + timeout * 1000;
|
|
58
|
+
Nas._saveToDisk(key, value, expireTime);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 检查缓存是否存在且未过期
|
|
63
|
+
* @param {string} key - 缓存键
|
|
64
|
+
* @returns {boolean} 是否存在且未过期
|
|
65
|
+
*/
|
|
66
|
+
static exists(key) {
|
|
67
|
+
return Nas.get(key) !== null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 删除指定的缓存项
|
|
72
|
+
* @param {string} key - 缓存键
|
|
73
|
+
*/
|
|
74
|
+
static del(key) {
|
|
75
|
+
Nas._deleteCacheFile(key);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 从硬盘加载缓存值
|
|
80
|
+
* @param {string} key - 缓存键
|
|
81
|
+
* @returns {any} 缓存值,如果过期或不存在则返回null
|
|
82
|
+
*/
|
|
83
|
+
static _loadFromDisk(key) {
|
|
84
|
+
const filePath = Nas._getFilePath(key);
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
if (!fs.existsSync(filePath)) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 读取缓存文件
|
|
92
|
+
let content;
|
|
93
|
+
try {
|
|
94
|
+
content = fs.readFileSync(filePath, "utf8");
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.warn("读取缓存文件失败:", filePath, e);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const lines = content.split("\n");
|
|
100
|
+
|
|
101
|
+
if (lines.length >= 2) {
|
|
102
|
+
const expireTimeString = lines[0];
|
|
103
|
+
const value = lines.slice(1).join("\n"); // 处理值中可能包含换行符的情况
|
|
104
|
+
|
|
105
|
+
const expireTime = parseInt(expireTimeString);
|
|
106
|
+
|
|
107
|
+
if (!isNaN(expireTime)) {
|
|
108
|
+
if (expireTime === -1 || Date.now() < expireTime) {
|
|
109
|
+
// 文件未过期,返回值
|
|
110
|
+
let valueStr = Buffer.from(value, "base64").toString("utf8");
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(valueStr);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// 如果解析JSON失败,则返回原始字符串
|
|
115
|
+
return valueStr;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
console.warn("读取缓存文件失败:", filePath, e);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 保存缓存值到硬盘
|
|
131
|
+
* @param {string} key - 缓存键
|
|
132
|
+
* @param {any} value - 缓存值
|
|
133
|
+
* @param {number} expireTime - 过期时间戳,-1表示永不过期
|
|
134
|
+
*/
|
|
135
|
+
static _saveToDisk(key, value, expireTime) {
|
|
136
|
+
// 将值转换为字符串,如果是对象则转换为JSON字符串
|
|
137
|
+
const valueStr = typeof value === "object" ? JSON.stringify(value) : value;
|
|
138
|
+
const content = Buffer.from(valueStr, "utf8").toString("base64");
|
|
139
|
+
const filePath = Nas._getFilePath(key);
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// 创建临时文件名,避免写入过程中的并发问题
|
|
143
|
+
const tempFilePath = filePath + ".tmp";
|
|
144
|
+
// 写入过期时间戳和值,用换行符分隔
|
|
145
|
+
const fileContent = `${expireTime}\n${content}`;
|
|
146
|
+
fs.writeFileSync(tempFilePath, fileContent, "utf8");
|
|
147
|
+
// 原子性地替换原文件
|
|
148
|
+
fs.renameSync(tempFilePath, filePath);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.error("保存缓存文件失败:", filePath, e);
|
|
151
|
+
// 如果临时文件创建失败,清理临时文件
|
|
152
|
+
try {
|
|
153
|
+
fs.unlinkSync(filePath + ".tmp");
|
|
154
|
+
} catch (cleanupError) {
|
|
155
|
+
// 忽略清理错误
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 删除缓存文件
|
|
162
|
+
* @param {string} key - 缓存键
|
|
163
|
+
*/
|
|
164
|
+
static _deleteCacheFile(key) {
|
|
165
|
+
const filePath = Nas._getFilePath(key);
|
|
166
|
+
try {
|
|
167
|
+
if (fs.existsSync(filePath)) {
|
|
168
|
+
fs.unlinkSync(filePath);
|
|
169
|
+
}
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.warn("删除缓存文件失败:", filePath, e);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 获取缓存文件路径
|
|
177
|
+
* @param {string} key - 缓存键
|
|
178
|
+
* @returns {string} 文件路径
|
|
179
|
+
*/
|
|
180
|
+
static _getFilePath(key) {
|
|
181
|
+
// 为键生成安全的文件名
|
|
182
|
+
const safeKey = key.replace(/[^a-zA-Z0-9-_.]/g, "_");
|
|
183
|
+
return path.join(Nas._getCacheDir(), `${safeKey}.cache`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 清空所有过期缓存
|
|
188
|
+
*/
|
|
189
|
+
static flushAll() {
|
|
190
|
+
try {
|
|
191
|
+
const cacheDir = Nas._getCacheDir();
|
|
192
|
+
if (fs.existsSync(cacheDir) && fs.statSync(cacheDir).isDirectory()) {
|
|
193
|
+
const files = fs.readdirSync(cacheDir);
|
|
194
|
+
for (const file of files) {
|
|
195
|
+
if (file.endsWith(".cache")) {
|
|
196
|
+
const filePath = path.join(cacheDir, file);
|
|
197
|
+
// 检查文件是否过期超过一分钟,如果超过则删除
|
|
198
|
+
try {
|
|
199
|
+
if (fs.existsSync(filePath)) {
|
|
200
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
201
|
+
const lines = content.split("\n");
|
|
202
|
+
|
|
203
|
+
if (lines.length >= 1) {
|
|
204
|
+
const expireTimeString = lines[0];
|
|
205
|
+
const expireTime = parseInt(expireTimeString);
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
!isNaN(expireTime) &&
|
|
209
|
+
expireTime !== -1 &&
|
|
210
|
+
// 仅删除过期超过一分钟的文件
|
|
211
|
+
Date.now() > expireTime + 60 * 1000
|
|
212
|
+
) {
|
|
213
|
+
console.log("删除过期缓存文件:", filePath);
|
|
214
|
+
fs.unlinkSync(filePath);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} catch (e) {
|
|
219
|
+
console.warn("检查缓存文件过期时间失败:", filePath, e);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
} catch (e) {
|
|
225
|
+
console.error("清空缓存失败", e);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* 设置指定键的过期时间
|
|
231
|
+
* @param {string} key - 缓存键
|
|
232
|
+
* @param {number} second - 过期时间(秒)
|
|
233
|
+
*/
|
|
234
|
+
static expire(key, second) {
|
|
235
|
+
const currentValue = Nas.get(key);
|
|
236
|
+
if (currentValue !== null) {
|
|
237
|
+
const expireTime = Date.now() + second * 1000;
|
|
238
|
+
Nas._saveToDisk(key, currentValue, expireTime);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* 设置指定键的过期时间戳
|
|
244
|
+
* @param {string} key - 缓存键
|
|
245
|
+
* @param {number} expireTime - 过期时间戳(毫秒)
|
|
246
|
+
*/
|
|
247
|
+
static expireAt(key, expireTime) {
|
|
248
|
+
const currentValue = Nas.get(key);
|
|
249
|
+
if (currentValue !== null) {
|
|
250
|
+
Nas._saveToDisk(key, currentValue, expireTime);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 获取指定键的剩余生存时间
|
|
256
|
+
* @param {string} key - 缓存键
|
|
257
|
+
* @returns {number} 剩余生存时间(秒),如果不存在或已过期则返回-1
|
|
258
|
+
*/
|
|
259
|
+
static ttl(key) {
|
|
260
|
+
const filePath = Nas._getFilePath(key);
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
if (!fs.existsSync(filePath)) {
|
|
264
|
+
return -1;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// 读取缓存文件
|
|
268
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
269
|
+
const lines = content.split("\n");
|
|
270
|
+
|
|
271
|
+
if (lines.length >= 1) {
|
|
272
|
+
const expireTimeString = lines[0];
|
|
273
|
+
const expireTime = parseInt(expireTimeString);
|
|
274
|
+
|
|
275
|
+
if (!isNaN(expireTime)) {
|
|
276
|
+
if (Date.now() < expireTime) {
|
|
277
|
+
// 文件未过期,计算剩余时间
|
|
278
|
+
const remainingTime = Math.floor((expireTime - Date.now()) / 1000);
|
|
279
|
+
return Math.max(0, remainingTime); // 确保返回非负值
|
|
280
|
+
} else {
|
|
281
|
+
return -1;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
} catch (e) {
|
|
286
|
+
console.warn("读取缓存文件失败:", filePath, e);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return -1;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
module.exports = Nas;
|
package/test/test-nas.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const Nas = require("../src/nas");
|
|
2
|
+
const assert = require("assert");
|
|
3
|
+
|
|
4
|
+
describe("Nas Class Tests", function () {
|
|
5
|
+
it("should set and get a string value", function () {
|
|
6
|
+
Nas.set("testKey", "testValue");
|
|
7
|
+
const value = Nas.get("testKey");
|
|
8
|
+
assert.equal(value, "testValue");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should set and get a string object", function () {
|
|
12
|
+
const target = [
|
|
13
|
+
{
|
|
14
|
+
id: 128910,
|
|
15
|
+
supplierCode: "9c6d1ab7ff7a440eba1516b164c06632",
|
|
16
|
+
status: 1,
|
|
17
|
+
city: "",
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
Nas.set("testObject", target);
|
|
21
|
+
const value = Nas.get("testObject");
|
|
22
|
+
assert.deepStrictEqual(value, target);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should handle expiration correctly", function (done) {
|
|
26
|
+
Nas.set("expiringKey", "expiringValue", 1); // 1秒后过期
|
|
27
|
+
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
const expiredValue = Nas.get("expiringKey");
|
|
30
|
+
assert.equal(expiredValue, null);
|
|
31
|
+
done();
|
|
32
|
+
}, 1100);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should return null for expired keys", function () {
|
|
36
|
+
Nas.set("shortLivedKey", "value", 0.5); // 0.5秒后过期
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
const value = Nas.get("shortLivedKey");
|
|
39
|
+
assert.equal(value, null);
|
|
40
|
+
}, 1000);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should check if key exists", function () {
|
|
44
|
+
Nas.set("existKey", "value");
|
|
45
|
+
assert(Nas.exists("existKey"));
|
|
46
|
+
assert(Nas.exists("nonExistKey") == false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should delete a key", function () {
|
|
50
|
+
Nas.set("deleteKey", "value");
|
|
51
|
+
assert(Nas.exists("deleteKey"));
|
|
52
|
+
Nas.del("deleteKey");
|
|
53
|
+
assert(Nas.exists("deleteKey") == false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should return default value when key does not exist", function () {
|
|
57
|
+
const defaultValue = Nas.getOrDefault("nonExistingKey", "default");
|
|
58
|
+
assert.equal(defaultValue, "default");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should return actual value when key exists with getOrDefault", function () {
|
|
62
|
+
Nas.set("existingKey", "actualValue");
|
|
63
|
+
const value = Nas.getOrDefault("existingKey", "defaultValue");
|
|
64
|
+
assert.equal(value, "actualValue");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should handle expiration with expire method", function (done) {
|
|
68
|
+
Nas.set("expireTest", "value", 10); // 设置10秒后过期
|
|
69
|
+
const initialTtl = Nas.ttl("expireTest");
|
|
70
|
+
assert(initialTtl > 5); // 初始TTL应该大于5秒
|
|
71
|
+
|
|
72
|
+
Nas.expire("expireTest", 1); // 重新设置为1秒后过期
|
|
73
|
+
const updatedTtl = Nas.ttl("expireTest");
|
|
74
|
+
assert(updatedTtl <= 1); // TTL应该小于等于1秒
|
|
75
|
+
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
const expiredTtl = Nas.ttl("expireTest");
|
|
78
|
+
assert.equal(expiredTtl, -1); // 已过期,返回-1
|
|
79
|
+
done();
|
|
80
|
+
}, 1100);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should handle expiration with expireAt method", function (done) {
|
|
84
|
+
Nas.set("expireAtTest", "value");
|
|
85
|
+
const futureTime = Date.now() + 1000; // 1秒后
|
|
86
|
+
Nas.expireAt("expireAtTest", futureTime);
|
|
87
|
+
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
const expiredAtValue = Nas.get("expireAtTest");
|
|
90
|
+
assert(expiredAtValue == null); // 已过期,应该返回null
|
|
91
|
+
done();
|
|
92
|
+
}, 1100);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("should flush only expired cache entries", function (done) {
|
|
96
|
+
// 设置一个永不过期的键
|
|
97
|
+
Nas.set("permanentKey", "permanentValue", -1);
|
|
98
|
+
// 设置一个会过期的键
|
|
99
|
+
Nas.set("expiringKey", "expiringValue", 0.5); // 0.5秒后过期
|
|
100
|
+
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
// 此时expiringKey已经过期,但是permanentKey仍然有效
|
|
103
|
+
Nas.flushAll(); // 应该只清除过期的键
|
|
104
|
+
|
|
105
|
+
// 永不过期的键应该仍然存在
|
|
106
|
+
assert(Nas.get("permanentKey") == "permanentValue");
|
|
107
|
+
// 过期的键应该已经被清除
|
|
108
|
+
assert(Nas.get("expiringKey") == null);
|
|
109
|
+
assert(Nas.exists("expiringKey") == false);
|
|
110
|
+
|
|
111
|
+
// 清理测试数据
|
|
112
|
+
Nas.del("permanentKey");
|
|
113
|
+
done();
|
|
114
|
+
}, 1000); // 等待expiringKey过期后再测试
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("should handle non-expiring keys (timeout = -1)", function () {
|
|
118
|
+
Nas.set("permanentKey", "permanentValue", -1);
|
|
119
|
+
const value = Nas.get("permanentKey");
|
|
120
|
+
assert.equal(value, "permanentValue");
|
|
121
|
+
});
|
|
122
|
+
});
|