mm_cachebase 2.0.2 → 2.0.4
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/index.js +18 -3
- package/package.json +2 -2
- package/test.js +36 -37
package/index.js
CHANGED
|
@@ -1925,6 +1925,12 @@ CacheBase.prototype.add = async function (key, value, seconds = 0) {
|
|
|
1925
1925
|
* @returns {Promise<Boolean>} 成功返回true,失败返回false
|
|
1926
1926
|
*/
|
|
1927
1927
|
CacheBase.prototype.mset = async function (obj, seconds = 0) {
|
|
1928
|
+
// 检查服务状态
|
|
1929
|
+
if (!this.is_inited || this.is_destroyed) {
|
|
1930
|
+
this.log('error', 'Service is not initialized or has been destroyed');
|
|
1931
|
+
return false;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1928
1934
|
try {
|
|
1929
1935
|
// 参数验证:必须是对象
|
|
1930
1936
|
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
@@ -1949,12 +1955,16 @@ CacheBase.prototype.mset = async function (obj, seconds = 0) {
|
|
|
1949
1955
|
seconds: finalSeconds
|
|
1950
1956
|
} = ctx;
|
|
1951
1957
|
|
|
1952
|
-
//
|
|
1953
|
-
|
|
1958
|
+
// 先校验所有键的合法性,避免批量写入中途失败导致部分写入(保证原子性)
|
|
1959
|
+
const entries = Object.entries(finalKeyValuePairs);
|
|
1960
|
+
for (const [key] of entries) {
|
|
1954
1961
|
if (typeof key !== 'string' || !key) {
|
|
1955
1962
|
throw new TypeError('键必须是非空字符串');
|
|
1956
1963
|
}
|
|
1964
|
+
}
|
|
1957
1965
|
|
|
1966
|
+
// 批量设置键值对
|
|
1967
|
+
for (const [key, value] of entries) {
|
|
1958
1968
|
// 检查键是否过期
|
|
1959
1969
|
if (this._isExpired(key)) {
|
|
1960
1970
|
await this.del(key);
|
|
@@ -1979,7 +1989,12 @@ CacheBase.prototype.mset = async function (obj, seconds = 0) {
|
|
|
1979
1989
|
return true;
|
|
1980
1990
|
} catch (error) {
|
|
1981
1991
|
this.emit('mset:error', { keyValuePairs: obj, error });
|
|
1982
|
-
|
|
1992
|
+
// 参数校验类错误属预期内,用 debug 级别避免误导;运行时错误保留 error 级别
|
|
1993
|
+
if (error instanceof TypeError) {
|
|
1994
|
+
this.log('debug', `[mset] 参数错误: ${error.message}`);
|
|
1995
|
+
} else {
|
|
1996
|
+
this.log('error', 'Failed to mset:', error);
|
|
1997
|
+
}
|
|
1983
1998
|
return false;
|
|
1984
1999
|
}
|
|
1985
2000
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_cachebase",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "一个轻量级的本地缓存类库,接口与 mm_redis 完全对齐:全异步API、冒号风格事件、统一签名与返回值,支持字符串、哈希、列表、集合、有序集合、发布订阅。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -39,6 +39,6 @@
|
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://gitee.com/qiuwenwu91/mm_cachebase#readme",
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"mm_expand": "^2.5.
|
|
42
|
+
"mm_expand": "^2.5.4"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/test.js
CHANGED
|
@@ -618,55 +618,54 @@ async function test() {
|
|
|
618
618
|
const eventCache = new CacheBase({ scope: 'test_event' });
|
|
619
619
|
|
|
620
620
|
await runner.runTest('set事件触发(冒号风格)', async () => {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
setTimeout(() => {
|
|
636
|
-
if (beforeTriggered && afterTriggered) {
|
|
637
|
-
resolve();
|
|
638
|
-
} else {
|
|
639
|
-
reject(new Error('set事件未全部触发'));
|
|
640
|
-
}
|
|
641
|
-
}, 10);
|
|
642
|
-
}
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
await eventCache.set('event_key', 'event_value');
|
|
621
|
+
let beforeTriggered = false;
|
|
622
|
+
let afterTriggered = false;
|
|
623
|
+
|
|
624
|
+
// 事件名改为冒号风格,对齐 mm_redis
|
|
625
|
+
eventCache.once('set:before', (data) => {
|
|
626
|
+
if (data.key === 'event_key' && data.value === 'event_value') {
|
|
627
|
+
beforeTriggered = true;
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
eventCache.once('set:after', (data) => {
|
|
632
|
+
if (data.key === 'event_key' && data.value === 'event_value' && data.success === true) {
|
|
633
|
+
afterTriggered = true;
|
|
634
|
+
}
|
|
646
635
|
});
|
|
636
|
+
|
|
637
|
+
await eventCache.set('event_key', 'event_value');
|
|
638
|
+
|
|
639
|
+
// 事件为同步触发,等待一个宏任务后校验两个事件均已触发
|
|
640
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
641
|
+
if (!beforeTriggered || !afterTriggered) {
|
|
642
|
+
throw new Error('set事件未全部触发');
|
|
643
|
+
}
|
|
647
644
|
});
|
|
648
645
|
|
|
649
646
|
await runner.runTest('error事件触发(冒号风格)', async () => {
|
|
650
|
-
|
|
651
|
-
|
|
647
|
+
// 事件名改为冒号风格
|
|
648
|
+
const errorPromise = new Promise((resolve, reject) => {
|
|
649
|
+
// 超时保护,若事件未触发则失败
|
|
650
|
+
const timer = setTimeout(() => reject(new Error('mset:error事件未触发')), 100);
|
|
652
651
|
eventCache.once('mset:error', (data) => {
|
|
652
|
+
clearTimeout(timer);
|
|
653
653
|
if (data.error) {
|
|
654
654
|
resolve();
|
|
655
655
|
} else {
|
|
656
656
|
reject(new Error('mset:error事件触发但数据不正确'));
|
|
657
657
|
}
|
|
658
658
|
});
|
|
659
|
-
|
|
660
|
-
// 传入非法参数触发错误,mset 内部 catch 后返回 false 并触发 mset:error 事件
|
|
661
|
-
const result = await eventCache.mset(null);
|
|
662
|
-
if (result !== false) {
|
|
663
|
-
reject(new Error(`mset应返回false但返回: ${result}`));
|
|
664
|
-
}
|
|
665
|
-
// 超时保护,若事件未触发则失败
|
|
666
|
-
setTimeout(() => {
|
|
667
|
-
reject(new Error('mset:error事件未触发'));
|
|
668
|
-
}, 100);
|
|
669
659
|
});
|
|
660
|
+
|
|
661
|
+
// 传入非法参数触发错误,mset 内部 catch 后返回 false 并触发 mset:error 事件
|
|
662
|
+
const result = await eventCache.mset(null);
|
|
663
|
+
if (result !== false) {
|
|
664
|
+
throw new Error(`mset应返回false但返回: ${result}`);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// 等待 mset:error 事件触发
|
|
668
|
+
await errorPromise;
|
|
670
669
|
});
|
|
671
670
|
|
|
672
671
|
// 测试管理功能
|