@less-is-more/less-js 1.5.0-1 → 1.5.0-3
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 +4 -4
- package/src/nas.js +41 -48
- package/test/test-nas.js +33 -35
package/package.json
CHANGED
package/src/cache.js
CHANGED
|
@@ -40,10 +40,10 @@ module.exports = class Cache {
|
|
|
40
40
|
* @param {*} args 直接传arguments,用于拼接缓存key
|
|
41
41
|
* @param {function} fn 没有缓存的实现
|
|
42
42
|
* @param {boolean} zip 是否压缩
|
|
43
|
-
* @param {boolean}
|
|
43
|
+
* @param {boolean} useNas 是否使用Nas缓存
|
|
44
44
|
* @returns 优先返回对象
|
|
45
45
|
*/
|
|
46
|
-
static async auto(keyPrefix, timeSecond, args, fn, zip = false,
|
|
46
|
+
static async auto(keyPrefix, timeSecond, args, fn, zip = false, useNas = false) {
|
|
47
47
|
let fullKey = keyPrefix;
|
|
48
48
|
for (let i = 0; i < args.length; i++) {
|
|
49
49
|
fullKey += ":" + args[i].toString();
|
|
@@ -52,7 +52,7 @@ module.exports = class Cache {
|
|
|
52
52
|
let savedData = Cache._getLocal(fullKey);
|
|
53
53
|
let hasLocal = false;
|
|
54
54
|
if (Param.isBlank(savedData)) {
|
|
55
|
-
if (
|
|
55
|
+
if (useNas) {
|
|
56
56
|
savedData = Nas.get(fullKey);
|
|
57
57
|
} else {
|
|
58
58
|
savedData = await Redis.exec("get", fullKey);
|
|
@@ -82,7 +82,7 @@ module.exports = class Cache {
|
|
|
82
82
|
if (Cache._needZip(redisContent, zip)) {
|
|
83
83
|
redisContent = Cache._zip(redisContent);
|
|
84
84
|
}
|
|
85
|
-
if (
|
|
85
|
+
if (useNas) {
|
|
86
86
|
Nas.set(fullKey, result, timeSecond);
|
|
87
87
|
} else {
|
|
88
88
|
await Redis.exec("setex", fullKey, timeSecond + "", redisContent);
|
package/src/nas.js
CHANGED
|
@@ -8,20 +8,23 @@ const os = require("os");
|
|
|
8
8
|
* 适用于多服务器共享NAS存储
|
|
9
9
|
*/
|
|
10
10
|
class Nas {
|
|
11
|
-
|
|
11
|
+
static _getCacheDir() {
|
|
12
|
+
let cacheDir = null;
|
|
13
|
+
|
|
12
14
|
// 如果提供了缓存目录参数,则使用该目录,否则使用默认目录
|
|
13
15
|
const defaultCacheDir = path.join(os.tmpdir(), "cache");
|
|
14
|
-
|
|
16
|
+
cacheDir =
|
|
15
17
|
cacheDir || (fs.existsSync("/cache") ? "/cache" : defaultCacheDir);
|
|
16
18
|
|
|
17
19
|
// 确保缓存目录存在
|
|
18
20
|
try {
|
|
19
|
-
if (!fs.existsSync(
|
|
20
|
-
fs.mkdirSync(
|
|
21
|
+
if (!fs.existsSync(cacheDir)) {
|
|
22
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
21
23
|
}
|
|
22
24
|
} catch (e) {
|
|
23
|
-
console.error("创建缓存目录失败:",
|
|
25
|
+
console.error("创建缓存目录失败:", cacheDir, e);
|
|
24
26
|
}
|
|
27
|
+
return cacheDir;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/**
|
|
@@ -29,8 +32,8 @@ class Nas {
|
|
|
29
32
|
* @param {string} key - 缓存键
|
|
30
33
|
* @returns {any} 缓存值,如果过期或不存在则返回null
|
|
31
34
|
*/
|
|
32
|
-
get(key) {
|
|
33
|
-
return
|
|
35
|
+
static get(key) {
|
|
36
|
+
return Nas._loadFromDisk(key);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
/**
|
|
@@ -39,8 +42,8 @@ class Nas {
|
|
|
39
42
|
* @param {any} defaultValue - 默认值
|
|
40
43
|
* @returns {any} 缓存值或默认值
|
|
41
44
|
*/
|
|
42
|
-
getOrDefault(key, defaultValue) {
|
|
43
|
-
const value =
|
|
45
|
+
static getOrDefault(key, defaultValue) {
|
|
46
|
+
const value = Nas.get(key);
|
|
44
47
|
return value !== null ? value : defaultValue;
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -50,9 +53,9 @@ class Nas {
|
|
|
50
53
|
* @param {any} value - 缓存值
|
|
51
54
|
* @param {number} timeout - 超时时间(秒),-1表示永不过期
|
|
52
55
|
*/
|
|
53
|
-
set(key, value, timeout = -1) {
|
|
56
|
+
static set(key, value, timeout = -1) {
|
|
54
57
|
const expireTime = timeout === -1 ? -1 : Date.now() + timeout * 1000;
|
|
55
|
-
|
|
58
|
+
Nas._saveToDisk(key, value, expireTime);
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
/**
|
|
@@ -60,24 +63,16 @@ class Nas {
|
|
|
60
63
|
* @param {string} key - 缓存键
|
|
61
64
|
* @returns {boolean} 是否存在且未过期
|
|
62
65
|
*/
|
|
63
|
-
exists(key) {
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* 获取缓存目录路径
|
|
69
|
-
* @returns {string} 缓存目录路径
|
|
70
|
-
*/
|
|
71
|
-
getCacheDir() {
|
|
72
|
-
return this.cacheDir;
|
|
66
|
+
static exists(key) {
|
|
67
|
+
return Nas.get(key) !== null;
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
/**
|
|
76
71
|
* 删除指定的缓存项
|
|
77
72
|
* @param {string} key - 缓存键
|
|
78
73
|
*/
|
|
79
|
-
del(key) {
|
|
80
|
-
|
|
74
|
+
static del(key) {
|
|
75
|
+
Nas._deleteCacheFile(key);
|
|
81
76
|
}
|
|
82
77
|
|
|
83
78
|
/**
|
|
@@ -85,8 +80,8 @@ class Nas {
|
|
|
85
80
|
* @param {string} key - 缓存键
|
|
86
81
|
* @returns {any} 缓存值,如果过期或不存在则返回null
|
|
87
82
|
*/
|
|
88
|
-
|
|
89
|
-
const filePath =
|
|
83
|
+
static _loadFromDisk(key) {
|
|
84
|
+
const filePath = Nas._getFilePath(key);
|
|
90
85
|
|
|
91
86
|
try {
|
|
92
87
|
if (!fs.existsSync(filePath)) {
|
|
@@ -109,7 +104,7 @@ class Nas {
|
|
|
109
104
|
return Buffer.from(value, "base64").toString("utf8");
|
|
110
105
|
} else {
|
|
111
106
|
// 文件已过期,删除文件
|
|
112
|
-
|
|
107
|
+
Nas._deleteCacheFile(key);
|
|
113
108
|
return null;
|
|
114
109
|
}
|
|
115
110
|
}
|
|
@@ -127,10 +122,10 @@ class Nas {
|
|
|
127
122
|
* @param {any} value - 缓存值
|
|
128
123
|
* @param {number} expireTime - 过期时间戳,-1表示永不过期
|
|
129
124
|
*/
|
|
130
|
-
|
|
125
|
+
static _saveToDisk(key, value, expireTime) {
|
|
131
126
|
// 将值转换为字符串,如果是对象则转换为JSON字符串
|
|
132
127
|
const content = Buffer.from(value, "utf8").toString("base64");
|
|
133
|
-
const filePath =
|
|
128
|
+
const filePath = Nas._getFilePath(key);
|
|
134
129
|
|
|
135
130
|
try {
|
|
136
131
|
// 写入过期时间戳和值,用换行符分隔
|
|
@@ -145,8 +140,8 @@ class Nas {
|
|
|
145
140
|
* 删除缓存文件
|
|
146
141
|
* @param {string} key - 缓存键
|
|
147
142
|
*/
|
|
148
|
-
|
|
149
|
-
const filePath =
|
|
143
|
+
static _deleteCacheFile(key) {
|
|
144
|
+
const filePath = Nas._getFilePath(key);
|
|
150
145
|
try {
|
|
151
146
|
if (fs.existsSync(filePath)) {
|
|
152
147
|
fs.unlinkSync(filePath);
|
|
@@ -161,25 +156,23 @@ class Nas {
|
|
|
161
156
|
* @param {string} key - 缓存键
|
|
162
157
|
* @returns {string} 文件路径
|
|
163
158
|
*/
|
|
164
|
-
|
|
159
|
+
static _getFilePath(key) {
|
|
165
160
|
// 为键生成安全的文件名
|
|
166
161
|
const safeKey = key.replace(/[^a-zA-Z0-9-_.]/g, "_");
|
|
167
|
-
return path.join(
|
|
162
|
+
return path.join(Nas._getCacheDir(), `${safeKey}.cache`);
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
/**
|
|
171
166
|
* 清空所有缓存
|
|
172
167
|
*/
|
|
173
|
-
flushAll() {
|
|
168
|
+
static flushAll() {
|
|
174
169
|
try {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
fs.
|
|
178
|
-
) {
|
|
179
|
-
const files = fs.readdirSync(this.cacheDir);
|
|
170
|
+
const cacheDir = Nas._getCacheDir();
|
|
171
|
+
if (fs.existsSync(cacheDir) && fs.statSync(cacheDir).isDirectory()) {
|
|
172
|
+
const files = fs.readdirSync(cacheDir);
|
|
180
173
|
for (const file of files) {
|
|
181
174
|
if (file.endsWith(".cache")) {
|
|
182
|
-
const filePath = path.join(
|
|
175
|
+
const filePath = path.join(cacheDir, file);
|
|
183
176
|
fs.unlinkSync(filePath);
|
|
184
177
|
}
|
|
185
178
|
}
|
|
@@ -194,11 +187,11 @@ class Nas {
|
|
|
194
187
|
* @param {string} key - 缓存键
|
|
195
188
|
* @param {number} second - 过期时间(秒)
|
|
196
189
|
*/
|
|
197
|
-
expire(key, second) {
|
|
198
|
-
const currentValue =
|
|
190
|
+
static expire(key, second) {
|
|
191
|
+
const currentValue = Nas.get(key);
|
|
199
192
|
if (currentValue !== null) {
|
|
200
193
|
const expireTime = Date.now() + second * 1000;
|
|
201
|
-
|
|
194
|
+
Nas._saveToDisk(key, currentValue, expireTime);
|
|
202
195
|
}
|
|
203
196
|
}
|
|
204
197
|
|
|
@@ -207,10 +200,10 @@ class Nas {
|
|
|
207
200
|
* @param {string} key - 缓存键
|
|
208
201
|
* @param {number} expireTime - 过期时间戳(毫秒)
|
|
209
202
|
*/
|
|
210
|
-
expireAt(key, expireTime) {
|
|
211
|
-
const currentValue =
|
|
203
|
+
static expireAt(key, expireTime) {
|
|
204
|
+
const currentValue = Nas.get(key);
|
|
212
205
|
if (currentValue !== null) {
|
|
213
|
-
|
|
206
|
+
Nas._saveToDisk(key, currentValue, expireTime);
|
|
214
207
|
}
|
|
215
208
|
}
|
|
216
209
|
|
|
@@ -219,8 +212,8 @@ class Nas {
|
|
|
219
212
|
* @param {string} key - 缓存键
|
|
220
213
|
* @returns {number} 剩余生存时间(秒),如果不存在或已过期则返回-1
|
|
221
214
|
*/
|
|
222
|
-
ttl(key) {
|
|
223
|
-
const filePath =
|
|
215
|
+
static ttl(key) {
|
|
216
|
+
const filePath = Nas._getFilePath(key);
|
|
224
217
|
|
|
225
218
|
try {
|
|
226
219
|
if (!fs.existsSync(filePath)) {
|
|
@@ -242,7 +235,7 @@ class Nas {
|
|
|
242
235
|
return Math.max(0, remainingTime); // 确保返回非负值
|
|
243
236
|
} else {
|
|
244
237
|
// 文件已过期,删除文件
|
|
245
|
-
|
|
238
|
+
Nas._deleteCacheFile(key);
|
|
246
239
|
return -1;
|
|
247
240
|
}
|
|
248
241
|
}
|
package/test/test-nas.js
CHANGED
|
@@ -2,100 +2,98 @@ const Nas = require("../src/nas");
|
|
|
2
2
|
const assert = require("assert");
|
|
3
3
|
|
|
4
4
|
describe("Nas Class Tests", function () {
|
|
5
|
-
let nas = new Nas();
|
|
6
|
-
|
|
7
5
|
it("should set and get a string value", function () {
|
|
8
|
-
|
|
9
|
-
const value =
|
|
6
|
+
Nas.set("testKey", "testValue");
|
|
7
|
+
const value = Nas.get("testKey");
|
|
10
8
|
assert.equal(value, "testValue");
|
|
11
9
|
});
|
|
12
10
|
|
|
13
11
|
it("should handle expiration correctly", function (done) {
|
|
14
|
-
|
|
12
|
+
Nas.set("expiringKey", "expiringValue", 1); // 1秒后过期
|
|
15
13
|
|
|
16
14
|
setTimeout(() => {
|
|
17
|
-
const expiredValue =
|
|
15
|
+
const expiredValue = Nas.get("expiringKey");
|
|
18
16
|
assert.equal(expiredValue, null);
|
|
19
17
|
done();
|
|
20
18
|
}, 1100);
|
|
21
19
|
});
|
|
22
20
|
|
|
23
21
|
it("should return null for expired keys", function () {
|
|
24
|
-
|
|
22
|
+
Nas.set("shortLivedKey", "value", 0.5); // 0.5秒后过期
|
|
25
23
|
setTimeout(() => {
|
|
26
|
-
const value =
|
|
24
|
+
const value = Nas.get("shortLivedKey");
|
|
27
25
|
assert.equal(value, null);
|
|
28
26
|
}, 1000);
|
|
29
27
|
});
|
|
30
28
|
|
|
31
29
|
it("should check if key exists", function () {
|
|
32
|
-
|
|
33
|
-
assert(
|
|
34
|
-
assert(
|
|
30
|
+
Nas.set("existKey", "value");
|
|
31
|
+
assert(Nas.exists("existKey"));
|
|
32
|
+
assert(Nas.exists("nonExistKey") == false);
|
|
35
33
|
});
|
|
36
34
|
|
|
37
35
|
it("should delete a key", function () {
|
|
38
|
-
|
|
39
|
-
assert(
|
|
40
|
-
|
|
41
|
-
assert(
|
|
36
|
+
Nas.set("deleteKey", "value");
|
|
37
|
+
assert(Nas.exists("deleteKey"));
|
|
38
|
+
Nas.del("deleteKey");
|
|
39
|
+
assert(Nas.exists("deleteKey") == false);
|
|
42
40
|
});
|
|
43
41
|
|
|
44
42
|
it("should return default value when key does not exist", function () {
|
|
45
|
-
const defaultValue =
|
|
43
|
+
const defaultValue = Nas.getOrDefault("nonExistingKey", "default");
|
|
46
44
|
assert.equal(defaultValue, "default");
|
|
47
45
|
});
|
|
48
46
|
|
|
49
47
|
it("should return actual value when key exists with getOrDefault", function () {
|
|
50
|
-
|
|
51
|
-
const value =
|
|
48
|
+
Nas.set("existingKey", "actualValue");
|
|
49
|
+
const value = Nas.getOrDefault("existingKey", "defaultValue");
|
|
52
50
|
assert.equal(value, "actualValue");
|
|
53
51
|
});
|
|
54
52
|
|
|
55
53
|
it("should handle expiration with expire method", function (done) {
|
|
56
|
-
|
|
57
|
-
const initialTtl =
|
|
54
|
+
Nas.set("expireTest", "value", 10); // 设置10秒后过期
|
|
55
|
+
const initialTtl = Nas.ttl("expireTest");
|
|
58
56
|
assert(initialTtl > 5); // 初始TTL应该大于5秒
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
const updatedTtl =
|
|
58
|
+
Nas.expire("expireTest", 1); // 重新设置为1秒后过期
|
|
59
|
+
const updatedTtl = Nas.ttl("expireTest");
|
|
62
60
|
assert(updatedTtl <= 1); // TTL应该小于等于1秒
|
|
63
61
|
|
|
64
62
|
setTimeout(() => {
|
|
65
|
-
const expiredTtl =
|
|
63
|
+
const expiredTtl = Nas.ttl("expireTest");
|
|
66
64
|
assert.equal(expiredTtl, -1); // 已过期,返回-1
|
|
67
65
|
done();
|
|
68
66
|
}, 1100);
|
|
69
67
|
});
|
|
70
68
|
|
|
71
69
|
it("should handle expiration with expireAt method", function (done) {
|
|
72
|
-
|
|
70
|
+
Nas.set("expireAtTest", "value");
|
|
73
71
|
const futureTime = Date.now() + 1000; // 1秒后
|
|
74
|
-
|
|
72
|
+
Nas.expireAt("expireAtTest", futureTime);
|
|
75
73
|
|
|
76
74
|
setTimeout(() => {
|
|
77
|
-
const expiredAtValue =
|
|
75
|
+
const expiredAtValue = Nas.get("expireAtTest");
|
|
78
76
|
assert(expiredAtValue == null); // 已过期,应该返回null
|
|
79
77
|
done();
|
|
80
78
|
}, 1100);
|
|
81
79
|
});
|
|
82
80
|
|
|
83
81
|
it("should flush all cache entries", function () {
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
Nas.set("flushTest1", "value1");
|
|
83
|
+
Nas.set("flushTest2", "value2");
|
|
86
84
|
|
|
87
|
-
assert.isTrue(
|
|
88
|
-
assert.isTrue(
|
|
85
|
+
assert.isTrue(Nas.exists("flushTest1"));
|
|
86
|
+
assert.isTrue(Nas.exists("flushTest2"));
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
Nas.flushAll();
|
|
91
89
|
|
|
92
|
-
assert.isFalse(
|
|
93
|
-
assert.isFalse(
|
|
90
|
+
assert.isFalse(Nas.exists("flushTest1"));
|
|
91
|
+
assert.isFalse(Nas.exists("flushTest2"));
|
|
94
92
|
});
|
|
95
93
|
|
|
96
94
|
it("should handle non-expiring keys (timeout = -1)", function () {
|
|
97
|
-
|
|
98
|
-
const value =
|
|
95
|
+
Nas.set("permanentKey", "permanentValue", -1);
|
|
96
|
+
const value = Nas.get("permanentKey");
|
|
99
97
|
assert.equal(value, "permanentValue");
|
|
100
98
|
});
|
|
101
99
|
});
|