@maiyunnet/kebab 4.0.0 → 4.0.2
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.d.ts +1 -1
- package/index.js +1 -1
- package/lib/kv.d.ts +26 -40
- package/lib/kv.js +249 -133
- package/package.json +1 -1
- package/www/example/ctr/test.js +11 -17
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '4.0.
|
|
9
|
+
export const VER = '4.0.2';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/kv.d.ts
CHANGED
|
@@ -4,19 +4,12 @@
|
|
|
4
4
|
* Last: 2020-3-28 18:54:04, 2022-09-12 23:24:45, 2022-09-22 01:06:22, 2024-2-21 13:32:56, 2024-8-21 16:59:57, 2025-11-6 14:56:45
|
|
5
5
|
*/
|
|
6
6
|
import * as redis from '@litert/redis';
|
|
7
|
+
import * as kebab from '#kebab/index.js';
|
|
7
8
|
import * as sCtr from '#kebab/sys/ctr.js';
|
|
8
9
|
export declare class Kv {
|
|
9
|
-
/** ---
|
|
10
|
-
private readonly
|
|
11
|
-
|
|
12
|
-
private readonly _index;
|
|
13
|
-
/** --- kv 连接对象 --- */
|
|
14
|
-
private readonly _link;
|
|
15
|
-
/** --- 获取之时是新 redis 链接还是老链接 --- */
|
|
16
|
-
private readonly _new;
|
|
17
|
-
constructor(ctr: sCtr.Ctr, etc?: IOptions);
|
|
18
|
-
/** --- 初始化连接 --- */
|
|
19
|
-
init(ctr: sCtr.Ctr, etc?: IOptions): Promise<boolean>;
|
|
10
|
+
/** --- 当前的 kv 连接信息 --- */
|
|
11
|
+
private readonly _etc;
|
|
12
|
+
constructor(etc: kebab.IConfigKv);
|
|
20
13
|
/**
|
|
21
14
|
* --- 设定一个值 ---
|
|
22
15
|
* @param key
|
|
@@ -77,12 +70,10 @@ export declare class Kv {
|
|
|
77
70
|
* --- 批量获取值 ---
|
|
78
71
|
* @param keys key 序列
|
|
79
72
|
*/
|
|
80
|
-
mGet(keys: string[]): Promise<Record<string, string | null
|
|
73
|
+
mGet(keys: string[]): Promise<Record<string, string | null> | false>;
|
|
81
74
|
/**
|
|
82
75
|
* --- 批量设置哈希值 ---
|
|
83
|
-
* @param key key 名
|
|
84
76
|
* @param rows key / val 数组
|
|
85
|
-
* @param etc
|
|
86
77
|
*/
|
|
87
78
|
mSet(rows: Record<string, string | Buffer>): Promise<boolean>;
|
|
88
79
|
/**
|
|
@@ -153,30 +144,30 @@ export declare class Kv {
|
|
|
153
144
|
* @param key
|
|
154
145
|
* @param field
|
|
155
146
|
*/
|
|
156
|
-
hGet(key: string, field: string): Promise<string | null>;
|
|
147
|
+
hGet(key: string, field: string): Promise<string | false | null>;
|
|
157
148
|
/**
|
|
158
149
|
* --- 获取哈希 json 对象 ---
|
|
159
150
|
* @param key
|
|
160
151
|
* @param field
|
|
161
152
|
*/
|
|
162
|
-
hGetJson(key: string, field: string): Promise<any | null>;
|
|
153
|
+
hGetJson(key: string, field: string): Promise<any | false | null>;
|
|
163
154
|
/**
|
|
164
155
|
* --- 批量获取哈希值 ---
|
|
165
156
|
* @param key
|
|
166
157
|
* @param fields
|
|
167
158
|
*/
|
|
168
|
-
hMGet(key: string, fields: string[]): Promise<Record<string, string | null
|
|
159
|
+
hMGet(key: string, fields: string[]): Promise<Record<string, string | null> | false>;
|
|
169
160
|
/**
|
|
170
161
|
* --- 批量获取哈希键值对 ---
|
|
171
162
|
* @param key
|
|
172
163
|
*/
|
|
173
|
-
hGetAll(key: string): Promise<Record<string, string | null> |
|
|
164
|
+
hGetAll(key: string): Promise<Record<string, string | null> | false>;
|
|
174
165
|
/**
|
|
175
166
|
* --- 删除哈希键 ---
|
|
176
167
|
* @param key
|
|
177
168
|
* @param fields 值序列
|
|
178
169
|
*/
|
|
179
|
-
hDel(key: string, fields: string | string[]): Promise<number>;
|
|
170
|
+
hDel(key: string, fields: string | string[]): Promise<number | false>;
|
|
180
171
|
/**
|
|
181
172
|
* --- 判断哈希字段是否存在 ---
|
|
182
173
|
* @param key
|
|
@@ -189,39 +180,34 @@ export declare class Kv {
|
|
|
189
180
|
* @param field 字段
|
|
190
181
|
* @param increment 正数或负数,整数或浮点
|
|
191
182
|
*/
|
|
192
|
-
hIncr(key: string, field: string, increment: number): Promise<number>;
|
|
183
|
+
hIncr(key: string, field: string, increment: number): Promise<number | false>;
|
|
193
184
|
/**
|
|
194
185
|
* --- 获取哈希所有字段 ---
|
|
195
186
|
* @param key
|
|
196
187
|
*/
|
|
197
|
-
hKeys(key: string): Promise<string[]>;
|
|
198
|
-
lPush(key: string, values: Array<string | Buffer>): Promise<number>;
|
|
199
|
-
rPush(key: string, values: Array<string | Buffer>): Promise<number>;
|
|
200
|
-
bLMove(sourceKey: string, destKey: string, soo: 'LEFT' | 'RIGHT', deo: 'LEFT' | 'RIGHT', timeout: number): Promise<string | null>;
|
|
201
|
-
lPop(key: string): Promise<string | null>;
|
|
202
|
-
rPop(key: string): Promise<string | null>;
|
|
203
|
-
bRPop(key: string | string[], timeout: number): Promise<Record<string, string
|
|
204
|
-
lRange(key: string, start: number, stop: number): Promise<string[]>;
|
|
205
|
-
lLen(key: string): Promise<number>;
|
|
188
|
+
hKeys(key: string): Promise<string[] | false>;
|
|
189
|
+
lPush(key: string, values: Array<string | Buffer>): Promise<number | false>;
|
|
190
|
+
rPush(key: string, values: Array<string | Buffer>): Promise<number | false>;
|
|
191
|
+
bLMove(sourceKey: string, destKey: string, soo: 'LEFT' | 'RIGHT', deo: 'LEFT' | 'RIGHT', timeout: number): Promise<string | null | false>;
|
|
192
|
+
lPop(key: string): Promise<string | null | false>;
|
|
193
|
+
rPop(key: string): Promise<string | null | false>;
|
|
194
|
+
bRPop(key: string | string[], timeout: number): Promise<Record<string, string> | false>;
|
|
195
|
+
lRange(key: string, start: number, stop: number): Promise<string[] | false>;
|
|
196
|
+
lLen(key: string): Promise<number | false>;
|
|
197
|
+
/**
|
|
198
|
+
* --- 从连接池中获取一个符合要求的连接 ---
|
|
199
|
+
*/
|
|
200
|
+
private _getConnection;
|
|
206
201
|
}
|
|
207
202
|
/**
|
|
208
203
|
* --- 获取 Kv 对象 ---
|
|
209
204
|
* @param etc 配置信息可留空
|
|
210
205
|
*/
|
|
211
|
-
export declare function get(
|
|
206
|
+
export declare function get(ctrEtc: sCtr.Ctr | kebab.IConfigKv): Kv;
|
|
212
207
|
/** --- 连接信息 --- */
|
|
213
208
|
export interface IConnectionInfo {
|
|
214
209
|
'host': string;
|
|
215
210
|
'port': number;
|
|
216
211
|
'index': number;
|
|
217
|
-
'
|
|
218
|
-
}
|
|
219
|
-
/** --- 选项 --- */
|
|
220
|
-
export interface IOptions {
|
|
221
|
-
'host'?: string;
|
|
222
|
-
'port'?: number;
|
|
223
|
-
'index'?: number;
|
|
224
|
-
'pre'?: string;
|
|
225
|
-
'user'?: string;
|
|
226
|
-
'pwd'?: string;
|
|
212
|
+
'conn': redis.ICommandClient;
|
|
227
213
|
}
|
package/lib/kv.js
CHANGED
|
@@ -5,65 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// --- 第三方 ---
|
|
7
7
|
import * as redis from '@litert/redis';
|
|
8
|
-
// --- 库和定义 ---
|
|
9
8
|
import * as lText from '#kebab/lib/text.js';
|
|
10
9
|
import * as lCore from '#kebab/lib/core.js';
|
|
10
|
+
import * as sCtr from '#kebab/sys/ctr.js';
|
|
11
11
|
/** --- 连接列表(同一个 host、port、index 只有一个连接) --- */
|
|
12
12
|
const connections = [];
|
|
13
13
|
export class Kv {
|
|
14
|
-
constructor(
|
|
15
|
-
|
|
16
|
-
const host = etc?.host ?? configKv.host;
|
|
17
|
-
const port = etc?.port ?? configKv.port;
|
|
18
|
-
this._index = etc?.index ?? configKv.index;
|
|
19
|
-
this._pre = etc?.pre ?? configKv.pre;
|
|
20
|
-
const item = connections.find(item => (item.host === host) && (item.port === port) && (item.index === this._index));
|
|
21
|
-
if (item) {
|
|
22
|
-
this._new = false;
|
|
23
|
-
this._link = item.link;
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
this._new = true;
|
|
27
|
-
this._link = redis.createCommandClient({
|
|
28
|
-
'host': host,
|
|
29
|
-
'port': port,
|
|
30
|
-
});
|
|
31
|
-
this._link.on('error', err => {
|
|
32
|
-
lCore.debug('[KV][constructor][error]', err);
|
|
33
|
-
}).on('end', () => {
|
|
34
|
-
// --- 连接断开,不过没关系,执行命令时会自动重连 ---
|
|
35
|
-
}).on('close', () => {
|
|
36
|
-
// --- 连接断开,不过没关系,执行命令时会自动重连 ---
|
|
37
|
-
});
|
|
38
|
-
connections.push({
|
|
39
|
-
'host': host,
|
|
40
|
-
'port': port,
|
|
41
|
-
'index': this._index,
|
|
42
|
-
'link': this._link,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
/** --- 初始化连接 --- */
|
|
46
|
-
async init(ctr, etc) {
|
|
47
|
-
try {
|
|
48
|
-
if (!this._new) {
|
|
49
|
-
// --- 不是新连接,不需要初始化 ---
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
const configKv = ctr.getPrototype('_config').kv;
|
|
53
|
-
const user = etc?.user ?? configKv.user;
|
|
54
|
-
const pwd = etc?.pwd ?? configKv.pwd;
|
|
55
|
-
await this._link.auth(pwd, user || undefined);
|
|
56
|
-
await this._link.select(this._index);
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// --- 初始化失败,移除 ---
|
|
61
|
-
const item = connections.findIndex(item => item.link === this._link);
|
|
62
|
-
if (item !== -1) {
|
|
63
|
-
connections.splice(item, 1);
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
14
|
+
constructor(etc) {
|
|
15
|
+
this._etc = etc;
|
|
67
16
|
}
|
|
68
17
|
/**
|
|
69
18
|
* --- 设定一个值 ---
|
|
@@ -73,19 +22,23 @@ export class Kv {
|
|
|
73
22
|
* @param mod 设置模式: 空,nx(key不存在才建立),xx(key存在才修改)
|
|
74
23
|
*/
|
|
75
24
|
async set(key, val, ttl = 0, mod = '') {
|
|
25
|
+
const conn = await this._getConnection();
|
|
26
|
+
if (!conn) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
76
29
|
if (typeof val !== 'string') {
|
|
77
30
|
val = lText.stringifyJson(val);
|
|
78
31
|
}
|
|
79
32
|
try {
|
|
80
33
|
switch (mod) {
|
|
81
34
|
case '': {
|
|
82
|
-
return await
|
|
35
|
+
return await conn.set(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
83
36
|
}
|
|
84
37
|
case 'nx': {
|
|
85
|
-
return await
|
|
38
|
+
return await conn.setNX(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
86
39
|
}
|
|
87
40
|
case 'xx': {
|
|
88
|
-
return await
|
|
41
|
+
return await conn.replace(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
89
42
|
}
|
|
90
43
|
}
|
|
91
44
|
}
|
|
@@ -118,8 +71,12 @@ export class Kv {
|
|
|
118
71
|
* @param val
|
|
119
72
|
*/
|
|
120
73
|
async append(key, val) {
|
|
74
|
+
const conn = await this._getConnection();
|
|
75
|
+
if (!conn) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
121
78
|
try {
|
|
122
|
-
return await
|
|
79
|
+
return await conn.append(this._etc.pre + key, val) > 0 ? true : false;
|
|
123
80
|
}
|
|
124
81
|
catch {
|
|
125
82
|
return false;
|
|
@@ -131,6 +88,10 @@ export class Kv {
|
|
|
131
88
|
* @param val
|
|
132
89
|
*/
|
|
133
90
|
async prepend(key, val) {
|
|
91
|
+
const conn = await this._getConnection();
|
|
92
|
+
if (!conn) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
134
95
|
try {
|
|
135
96
|
const script = `local val = redis.call('GET', KEYS[1])
|
|
136
97
|
if (val == false) then
|
|
@@ -142,11 +103,11 @@ if (r) then
|
|
|
142
103
|
else
|
|
143
104
|
return 0
|
|
144
105
|
end`;
|
|
145
|
-
let r = await
|
|
106
|
+
let r = await conn.evalSHA('ea360f3f6508a243824ecda6be15db56df217873', [this._etc.pre + key], [val]);
|
|
146
107
|
r = parseInt(r);
|
|
147
108
|
if (r <= 0) {
|
|
148
|
-
await
|
|
149
|
-
r = await
|
|
109
|
+
await conn.scriptLoad(script);
|
|
110
|
+
r = await conn.evalSHA('ea360f3f6508a243824ecda6be15db56df217873', [this._etc.pre + key], [val]);
|
|
150
111
|
r = parseInt(r);
|
|
151
112
|
}
|
|
152
113
|
return r > 0 ? true : false;
|
|
@@ -160,14 +121,18 @@ end`;
|
|
|
160
121
|
* @param keys 单个或序列
|
|
161
122
|
*/
|
|
162
123
|
async exists(keys) {
|
|
124
|
+
const conn = await this._getConnection();
|
|
125
|
+
if (!conn) {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
163
128
|
try {
|
|
164
129
|
if (typeof keys === 'string') {
|
|
165
130
|
keys = [keys];
|
|
166
131
|
}
|
|
167
132
|
for (let k = 0; k < keys.length; ++k) {
|
|
168
|
-
keys[k] = this.
|
|
133
|
+
keys[k] = this._etc.pre + keys[k];
|
|
169
134
|
}
|
|
170
|
-
return await
|
|
135
|
+
return await conn.mExists(keys);
|
|
171
136
|
}
|
|
172
137
|
catch {
|
|
173
138
|
return 0;
|
|
@@ -179,8 +144,12 @@ end`;
|
|
|
179
144
|
* @returns 字符串 / false / null(即使存入时是 number,这个方法也只会返回字符串)
|
|
180
145
|
*/
|
|
181
146
|
async get(key) {
|
|
147
|
+
const conn = await this._getConnection();
|
|
148
|
+
if (!conn) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
182
151
|
try {
|
|
183
|
-
return await
|
|
152
|
+
return await conn.get(this._etc.pre + key);
|
|
184
153
|
}
|
|
185
154
|
catch {
|
|
186
155
|
return false;
|
|
@@ -191,8 +160,12 @@ end`;
|
|
|
191
160
|
* @param key
|
|
192
161
|
*/
|
|
193
162
|
async ttl(key) {
|
|
163
|
+
const conn = await this._getConnection();
|
|
164
|
+
if (!conn) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
194
167
|
try {
|
|
195
|
-
return await
|
|
168
|
+
return await conn.ttl(this._etc.pre + key);
|
|
196
169
|
}
|
|
197
170
|
catch {
|
|
198
171
|
return null;
|
|
@@ -203,8 +176,12 @@ end`;
|
|
|
203
176
|
* @param key
|
|
204
177
|
*/
|
|
205
178
|
async pttl(key) {
|
|
179
|
+
const conn = await this._getConnection();
|
|
180
|
+
if (!conn) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
206
183
|
try {
|
|
207
|
-
return await
|
|
184
|
+
return await conn.pTTL(this._etc.pre + key);
|
|
208
185
|
}
|
|
209
186
|
catch {
|
|
210
187
|
return null;
|
|
@@ -215,13 +192,17 @@ end`;
|
|
|
215
192
|
* @param keys key 序列
|
|
216
193
|
*/
|
|
217
194
|
async mGet(keys) {
|
|
195
|
+
const conn = await this._getConnection();
|
|
196
|
+
if (!conn) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
218
199
|
for (let k = 0; k < keys.length; ++k) {
|
|
219
|
-
keys[k] = this.
|
|
200
|
+
keys[k] = this._etc.pre + keys[k];
|
|
220
201
|
}
|
|
221
202
|
const rtn = {};
|
|
222
203
|
try {
|
|
223
|
-
const pl = this.
|
|
224
|
-
const r = await
|
|
204
|
+
const pl = this._etc.pre.length;
|
|
205
|
+
const r = await conn.mGet(keys);
|
|
225
206
|
if (pl === 0) {
|
|
226
207
|
return r;
|
|
227
208
|
}
|
|
@@ -230,25 +211,25 @@ end`;
|
|
|
230
211
|
}
|
|
231
212
|
}
|
|
232
213
|
catch {
|
|
233
|
-
|
|
234
|
-
rtn[key] = null;
|
|
235
|
-
}
|
|
214
|
+
return false;
|
|
236
215
|
}
|
|
237
216
|
return rtn;
|
|
238
217
|
}
|
|
239
218
|
/**
|
|
240
219
|
* --- 批量设置哈希值 ---
|
|
241
|
-
* @param key key 名
|
|
242
220
|
* @param rows key / val 数组
|
|
243
|
-
* @param etc
|
|
244
221
|
*/
|
|
245
222
|
async mSet(rows) {
|
|
223
|
+
const conn = await this._getConnection();
|
|
224
|
+
if (!conn) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
246
227
|
try {
|
|
247
228
|
const rtn = {};
|
|
248
229
|
for (const key in rows) {
|
|
249
|
-
rtn[this.
|
|
230
|
+
rtn[this._etc.pre + key] = rows[key];
|
|
250
231
|
}
|
|
251
|
-
await
|
|
232
|
+
await conn.mSet(rtn);
|
|
252
233
|
return true;
|
|
253
234
|
}
|
|
254
235
|
catch {
|
|
@@ -272,14 +253,18 @@ end`;
|
|
|
272
253
|
* @param keys
|
|
273
254
|
*/
|
|
274
255
|
async del(keys) {
|
|
256
|
+
const conn = await this._getConnection();
|
|
257
|
+
if (!conn) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
275
260
|
if (typeof keys === 'string') {
|
|
276
261
|
keys = [keys];
|
|
277
262
|
}
|
|
278
263
|
for (let k = 0; k < keys.length; ++k) {
|
|
279
|
-
keys[k] = this.
|
|
264
|
+
keys[k] = this._etc.pre + keys[k];
|
|
280
265
|
}
|
|
281
266
|
try {
|
|
282
|
-
return await
|
|
267
|
+
return await conn.del(keys) > 0 ? true : false;
|
|
283
268
|
}
|
|
284
269
|
catch {
|
|
285
270
|
return false;
|
|
@@ -291,17 +276,21 @@ end`;
|
|
|
291
276
|
* @param num 整数或浮点正数
|
|
292
277
|
*/
|
|
293
278
|
async incr(key, num = 1) {
|
|
279
|
+
const conn = await this._getConnection();
|
|
280
|
+
if (!conn) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
294
283
|
try {
|
|
295
284
|
if (Number.isInteger(num)) {
|
|
296
285
|
if (num === 1) {
|
|
297
|
-
return await
|
|
286
|
+
return await conn.incr(this._etc.pre + key);
|
|
298
287
|
}
|
|
299
288
|
else {
|
|
300
|
-
return await
|
|
289
|
+
return await conn.incr(this._etc.pre + key, num);
|
|
301
290
|
}
|
|
302
291
|
}
|
|
303
292
|
else {
|
|
304
|
-
return await
|
|
293
|
+
return await conn.incrByFloat(this._etc.pre + key, num);
|
|
305
294
|
}
|
|
306
295
|
}
|
|
307
296
|
catch {
|
|
@@ -314,17 +303,21 @@ end`;
|
|
|
314
303
|
* @param num 整数或浮点正数
|
|
315
304
|
*/
|
|
316
305
|
async decr(key, num = 1) {
|
|
306
|
+
const conn = await this._getConnection();
|
|
307
|
+
if (!conn) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
317
310
|
try {
|
|
318
311
|
if (Number.isInteger(num)) {
|
|
319
312
|
if (num === 1) {
|
|
320
|
-
return await
|
|
313
|
+
return await conn.decr(this._etc.pre + key);
|
|
321
314
|
}
|
|
322
315
|
else {
|
|
323
|
-
return await
|
|
316
|
+
return await conn.decr(this._etc.pre + key, num);
|
|
324
317
|
}
|
|
325
318
|
}
|
|
326
319
|
else {
|
|
327
|
-
return await
|
|
320
|
+
return await conn.incrByFloat(this._etc.pre + key, -num);
|
|
328
321
|
}
|
|
329
322
|
}
|
|
330
323
|
catch {
|
|
@@ -337,8 +330,12 @@ end`;
|
|
|
337
330
|
* @param ttl
|
|
338
331
|
*/
|
|
339
332
|
async expire(key, ttl) {
|
|
333
|
+
const conn = await this._getConnection();
|
|
334
|
+
if (!conn) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
340
337
|
try {
|
|
341
|
-
return await
|
|
338
|
+
return await conn.expire(this._etc.pre + key, ttl);
|
|
342
339
|
}
|
|
343
340
|
catch {
|
|
344
341
|
return false;
|
|
@@ -349,9 +346,13 @@ end`;
|
|
|
349
346
|
* @param pattern
|
|
350
347
|
*/
|
|
351
348
|
async keys(pattern) {
|
|
349
|
+
const conn = await this._getConnection();
|
|
350
|
+
if (!conn) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
352
353
|
try {
|
|
353
|
-
const r = await
|
|
354
|
-
const pl = this.
|
|
354
|
+
const r = await conn.keys(this._etc.pre + pattern);
|
|
355
|
+
const pl = this._etc.pre.length;
|
|
355
356
|
if (pl > 0) {
|
|
356
357
|
for (let k = 0; k < r.length; ++k) {
|
|
357
358
|
r[k] = r[k].slice(pl);
|
|
@@ -370,10 +371,14 @@ end`;
|
|
|
370
371
|
* @param count 获取的条数
|
|
371
372
|
*/
|
|
372
373
|
async scan(cursor = 0, pattern = '*', count = 10) {
|
|
374
|
+
const conn = await this._getConnection();
|
|
375
|
+
if (!conn) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
373
378
|
try {
|
|
374
|
-
const r = await
|
|
379
|
+
const r = await conn.scan(cursor, this._etc.pre + pattern, count);
|
|
375
380
|
for (let i = 0; i < r.items.length; ++i) {
|
|
376
|
-
r.items[i] = r.items[i].slice(this.
|
|
381
|
+
r.items[i] = r.items[i].slice(this._etc.pre.length);
|
|
377
382
|
}
|
|
378
383
|
return r;
|
|
379
384
|
}
|
|
@@ -385,8 +390,12 @@ end`;
|
|
|
385
390
|
* --- 清除当前所选数据库的所有内容 ---
|
|
386
391
|
*/
|
|
387
392
|
async flushDb() {
|
|
393
|
+
const conn = await this._getConnection();
|
|
394
|
+
if (!conn) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
388
397
|
try {
|
|
389
|
-
await
|
|
398
|
+
await conn.flushDb();
|
|
390
399
|
return true;
|
|
391
400
|
}
|
|
392
401
|
catch {
|
|
@@ -398,8 +407,12 @@ end`;
|
|
|
398
407
|
* @param last 是否刷新最后使用时间(默认刷新)
|
|
399
408
|
*/
|
|
400
409
|
async ping() {
|
|
410
|
+
const conn = await this._getConnection();
|
|
411
|
+
if (!conn) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
401
414
|
try {
|
|
402
|
-
return (await
|
|
415
|
+
return (await conn.ping()) === 'PONG' ? 'PONG' : false;
|
|
403
416
|
}
|
|
404
417
|
catch {
|
|
405
418
|
return false;
|
|
@@ -413,15 +426,19 @@ end`;
|
|
|
413
426
|
* @param mod 空,nx(key不存在才建立)
|
|
414
427
|
*/
|
|
415
428
|
async hSet(key, field, val, mod = '') {
|
|
429
|
+
const conn = await this._getConnection();
|
|
430
|
+
if (!conn) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
416
433
|
try {
|
|
417
434
|
if (typeof val !== 'string') {
|
|
418
435
|
val = lText.stringifyJson(val);
|
|
419
436
|
}
|
|
420
437
|
if (mod === 'nx') {
|
|
421
|
-
return await
|
|
438
|
+
return await conn.hSetNX(this._etc.pre + key, field, val);
|
|
422
439
|
}
|
|
423
440
|
else {
|
|
424
|
-
return await
|
|
441
|
+
return await conn.hSet(this._etc.pre + key, field, val);
|
|
425
442
|
}
|
|
426
443
|
}
|
|
427
444
|
catch {
|
|
@@ -434,6 +451,10 @@ end`;
|
|
|
434
451
|
* @param rows key / val 数组
|
|
435
452
|
*/
|
|
436
453
|
async hMSet(key, rows) {
|
|
454
|
+
const conn = await this._getConnection();
|
|
455
|
+
if (!conn) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
437
458
|
try {
|
|
438
459
|
for (const i in rows) {
|
|
439
460
|
const val = rows[i];
|
|
@@ -441,7 +462,7 @@ end`;
|
|
|
441
462
|
rows[i] = lText.stringifyJson(val);
|
|
442
463
|
}
|
|
443
464
|
}
|
|
444
|
-
await
|
|
465
|
+
await conn.hMSet(this._etc.pre + key, rows);
|
|
445
466
|
return true;
|
|
446
467
|
}
|
|
447
468
|
catch {
|
|
@@ -454,11 +475,15 @@ end`;
|
|
|
454
475
|
* @param field
|
|
455
476
|
*/
|
|
456
477
|
async hGet(key, field) {
|
|
478
|
+
const conn = await this._getConnection();
|
|
479
|
+
if (!conn) {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
457
482
|
try {
|
|
458
|
-
return await
|
|
483
|
+
return await conn.hGet(this._etc.pre + key, field);
|
|
459
484
|
}
|
|
460
485
|
catch {
|
|
461
|
-
return
|
|
486
|
+
return false;
|
|
462
487
|
}
|
|
463
488
|
}
|
|
464
489
|
/**
|
|
@@ -468,6 +493,9 @@ end`;
|
|
|
468
493
|
*/
|
|
469
494
|
async hGetJson(key, field) {
|
|
470
495
|
const v = await this.hGet(key, field);
|
|
496
|
+
if (v === false) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
471
499
|
if (v === null) {
|
|
472
500
|
return null;
|
|
473
501
|
}
|
|
@@ -480,15 +508,15 @@ end`;
|
|
|
480
508
|
* @param fields
|
|
481
509
|
*/
|
|
482
510
|
async hMGet(key, fields) {
|
|
511
|
+
const conn = await this._getConnection();
|
|
512
|
+
if (!conn) {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
483
515
|
try {
|
|
484
|
-
return await
|
|
516
|
+
return await conn.hMGet(this._etc.pre + key, fields);
|
|
485
517
|
}
|
|
486
518
|
catch {
|
|
487
|
-
|
|
488
|
-
for (const field of fields) {
|
|
489
|
-
rtn[field] = null;
|
|
490
|
-
}
|
|
491
|
-
return rtn;
|
|
519
|
+
return false;
|
|
492
520
|
}
|
|
493
521
|
}
|
|
494
522
|
/**
|
|
@@ -496,11 +524,15 @@ end`;
|
|
|
496
524
|
* @param key
|
|
497
525
|
*/
|
|
498
526
|
async hGetAll(key) {
|
|
527
|
+
const conn = await this._getConnection();
|
|
528
|
+
if (!conn) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
499
531
|
try {
|
|
500
|
-
return await
|
|
532
|
+
return await conn.hGetAll(this._etc.pre + key);
|
|
501
533
|
}
|
|
502
534
|
catch {
|
|
503
|
-
return
|
|
535
|
+
return false;
|
|
504
536
|
}
|
|
505
537
|
}
|
|
506
538
|
/**
|
|
@@ -509,11 +541,15 @@ end`;
|
|
|
509
541
|
* @param fields 值序列
|
|
510
542
|
*/
|
|
511
543
|
async hDel(key, fields) {
|
|
544
|
+
const conn = await this._getConnection();
|
|
545
|
+
if (!conn) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
512
548
|
try {
|
|
513
|
-
return await
|
|
549
|
+
return await conn.hDel(this._etc.pre + key, fields);
|
|
514
550
|
}
|
|
515
551
|
catch {
|
|
516
|
-
return
|
|
552
|
+
return false;
|
|
517
553
|
}
|
|
518
554
|
}
|
|
519
555
|
/**
|
|
@@ -522,8 +558,12 @@ end`;
|
|
|
522
558
|
* @param field
|
|
523
559
|
*/
|
|
524
560
|
async hExists(key, field) {
|
|
561
|
+
const conn = await this._getConnection();
|
|
562
|
+
if (!conn) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
525
565
|
try {
|
|
526
|
-
return await
|
|
566
|
+
return await conn.hExists(this._etc.pre + key, field);
|
|
527
567
|
}
|
|
528
568
|
catch {
|
|
529
569
|
return false;
|
|
@@ -536,16 +576,20 @@ end`;
|
|
|
536
576
|
* @param increment 正数或负数,整数或浮点
|
|
537
577
|
*/
|
|
538
578
|
async hIncr(key, field, increment) {
|
|
579
|
+
const conn = await this._getConnection();
|
|
580
|
+
if (!conn) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
539
583
|
try {
|
|
540
584
|
if (Number.isInteger(increment)) {
|
|
541
|
-
return await
|
|
585
|
+
return await conn.hIncr(this._etc.pre + key, field, increment);
|
|
542
586
|
}
|
|
543
587
|
else {
|
|
544
|
-
return await
|
|
588
|
+
return await conn.hIncrByFloat(this._etc.pre + key, field, increment);
|
|
545
589
|
}
|
|
546
590
|
}
|
|
547
591
|
catch {
|
|
548
|
-
return
|
|
592
|
+
return false;
|
|
549
593
|
}
|
|
550
594
|
}
|
|
551
595
|
/**
|
|
@@ -553,78 +597,152 @@ end`;
|
|
|
553
597
|
* @param key
|
|
554
598
|
*/
|
|
555
599
|
async hKeys(key) {
|
|
600
|
+
const conn = await this._getConnection();
|
|
601
|
+
if (!conn) {
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
556
604
|
try {
|
|
557
|
-
return await
|
|
605
|
+
return await conn.hKeys(this._etc.pre + key);
|
|
558
606
|
}
|
|
559
607
|
catch {
|
|
560
|
-
return
|
|
608
|
+
return false;
|
|
561
609
|
}
|
|
562
610
|
}
|
|
563
611
|
async lPush(key, values) {
|
|
612
|
+
const conn = await this._getConnection();
|
|
613
|
+
if (!conn) {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
564
616
|
try {
|
|
565
|
-
return await
|
|
617
|
+
return await conn.lPush(this._etc.pre + key, values);
|
|
566
618
|
}
|
|
567
619
|
catch {
|
|
568
|
-
return
|
|
620
|
+
return false;
|
|
569
621
|
}
|
|
570
622
|
}
|
|
571
623
|
async rPush(key, values) {
|
|
624
|
+
const conn = await this._getConnection();
|
|
625
|
+
if (!conn) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
572
628
|
try {
|
|
573
|
-
return await
|
|
629
|
+
return await conn.rPush(this._etc.pre + key, values);
|
|
574
630
|
}
|
|
575
631
|
catch {
|
|
576
|
-
return
|
|
632
|
+
return false;
|
|
577
633
|
}
|
|
578
634
|
}
|
|
579
635
|
async bLMove(sourceKey, destKey, soo, deo, timeout) {
|
|
636
|
+
const conn = await this._getConnection();
|
|
637
|
+
if (!conn) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
580
640
|
try {
|
|
581
|
-
return await
|
|
641
|
+
return await conn.bLMove(this._etc.pre + sourceKey, this._etc.pre + destKey, soo, deo, timeout);
|
|
582
642
|
}
|
|
583
643
|
catch {
|
|
584
|
-
return
|
|
644
|
+
return false;
|
|
585
645
|
}
|
|
586
646
|
}
|
|
587
647
|
async lPop(key) {
|
|
648
|
+
const conn = await this._getConnection();
|
|
649
|
+
if (!conn) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
588
652
|
try {
|
|
589
|
-
return await
|
|
653
|
+
return await conn.lPop(this._etc.pre + key);
|
|
590
654
|
}
|
|
591
655
|
catch {
|
|
592
|
-
return
|
|
656
|
+
return false;
|
|
593
657
|
}
|
|
594
658
|
}
|
|
595
659
|
async rPop(key) {
|
|
660
|
+
const conn = await this._getConnection();
|
|
661
|
+
if (!conn) {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
596
664
|
try {
|
|
597
|
-
return await
|
|
665
|
+
return await conn.rPop(this._etc.pre + key);
|
|
598
666
|
}
|
|
599
667
|
catch {
|
|
600
|
-
return
|
|
668
|
+
return false;
|
|
601
669
|
}
|
|
602
670
|
}
|
|
603
671
|
async bRPop(key, timeout) {
|
|
672
|
+
const conn = await this._getConnection();
|
|
673
|
+
if (!conn) {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
604
676
|
try {
|
|
605
677
|
if (typeof key === 'string') {
|
|
606
678
|
key = [key];
|
|
607
679
|
}
|
|
608
|
-
return await
|
|
680
|
+
return await conn.bRPop(key.map(item => this._etc.pre + item), timeout);
|
|
609
681
|
}
|
|
610
682
|
catch {
|
|
611
|
-
return
|
|
683
|
+
return false;
|
|
612
684
|
}
|
|
613
685
|
}
|
|
614
686
|
async lRange(key, start, stop) {
|
|
687
|
+
const conn = await this._getConnection();
|
|
688
|
+
if (!conn) {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
615
691
|
try {
|
|
616
|
-
return await
|
|
692
|
+
return await conn.lRange(this._etc.pre + key, start, stop);
|
|
617
693
|
}
|
|
618
694
|
catch {
|
|
619
|
-
return
|
|
695
|
+
return false;
|
|
620
696
|
}
|
|
621
697
|
}
|
|
622
698
|
async lLen(key) {
|
|
699
|
+
const conn = await this._getConnection();
|
|
700
|
+
if (!conn) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
623
703
|
try {
|
|
624
|
-
return await
|
|
704
|
+
return await conn.lLen(this._etc.pre + key);
|
|
625
705
|
}
|
|
626
706
|
catch {
|
|
627
|
-
return
|
|
707
|
+
return false;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* --- 从连接池中获取一个符合要求的连接 ---
|
|
712
|
+
*/
|
|
713
|
+
async _getConnection() {
|
|
714
|
+
const item = connections.find(item => (item.host === this._etc.host) && (item.port === this._etc.port) && (item.index === this._etc.index));
|
|
715
|
+
if (item) {
|
|
716
|
+
return item.conn;
|
|
717
|
+
}
|
|
718
|
+
// --- 没有找到合适的连接,创建一个 ---
|
|
719
|
+
try {
|
|
720
|
+
const conn = redis.createCommandClient({
|
|
721
|
+
'host': this._etc.host,
|
|
722
|
+
'port': this._etc.port,
|
|
723
|
+
});
|
|
724
|
+
// --- 认证 ---
|
|
725
|
+
if (this._etc.pwd) {
|
|
726
|
+
await conn.auth(this._etc.pwd, this._etc.user || undefined);
|
|
727
|
+
}
|
|
728
|
+
await conn.select(this._etc.index);
|
|
729
|
+
conn.on('error', function (err) {
|
|
730
|
+
lCore.debug('[KV][_getConnection][error]', err);
|
|
731
|
+
}).on('end', () => {
|
|
732
|
+
// --- 断线,不重要,会自动重连 ---
|
|
733
|
+
}).on('close', () => {
|
|
734
|
+
// --- 断线,不重要,会自动重连 ---
|
|
735
|
+
});
|
|
736
|
+
connections.push({
|
|
737
|
+
'host': this._etc.host,
|
|
738
|
+
'port': this._etc.port,
|
|
739
|
+
'index': this._etc.index,
|
|
740
|
+
'conn': conn,
|
|
741
|
+
});
|
|
742
|
+
return conn;
|
|
743
|
+
}
|
|
744
|
+
catch {
|
|
745
|
+
return null;
|
|
628
746
|
}
|
|
629
747
|
}
|
|
630
748
|
}
|
|
@@ -632,9 +750,7 @@ end`;
|
|
|
632
750
|
* --- 获取 Kv 对象 ---
|
|
633
751
|
* @param etc 配置信息可留空
|
|
634
752
|
*/
|
|
635
|
-
export
|
|
636
|
-
etc
|
|
637
|
-
|
|
638
|
-
const r = await kv.init(ctr, etc);
|
|
639
|
-
return r ? kv : false;
|
|
753
|
+
export function get(ctrEtc) {
|
|
754
|
+
const etc = ctrEtc instanceof sCtr.Ctr ? ctrEtc.getPrototype('_config').kv : ctrEtc;
|
|
755
|
+
return new Kv(etc);
|
|
640
756
|
}
|
package/package.json
CHANGED
package/www/example/ctr/test.js
CHANGED
|
@@ -1357,16 +1357,10 @@ exec: ${JSON.stringify(exec)}<br><br>`);
|
|
|
1357
1357
|
return echo.join('') + '<br>' + this._getEnd();
|
|
1358
1358
|
}
|
|
1359
1359
|
async kv() {
|
|
1360
|
-
const kv =
|
|
1361
|
-
if (!kv) {
|
|
1362
|
-
return [0, 'Failed.'];
|
|
1363
|
-
}
|
|
1360
|
+
const kv = lKv.get(this);
|
|
1364
1361
|
const value = this._get['value'] ?? '';
|
|
1365
1362
|
const ac = this._get['ac'] ?? '';
|
|
1366
|
-
const echo = [`<pre>const kv =
|
|
1367
|
-
if (!kv) {
|
|
1368
|
-
return [0, 'Failed.'];
|
|
1369
|
-
}
|
|
1363
|
+
const echo = [`<pre>const kv = lKv.get(this);
|
|
1370
1364
|
JSON.stringify(await kv.ping());</pre>${JSON.stringify(await kv.ping())}`];
|
|
1371
1365
|
if (ac == 'delete') {
|
|
1372
1366
|
echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
|
|
@@ -2103,7 +2097,10 @@ function confirm() {
|
|
|
2103
2097
|
link = db;
|
|
2104
2098
|
}
|
|
2105
2099
|
else {
|
|
2106
|
-
const kv =
|
|
2100
|
+
const kv = lKv.get(this);
|
|
2101
|
+
if (!await kv.ping()) {
|
|
2102
|
+
return false;
|
|
2103
|
+
}
|
|
2107
2104
|
if (!kv) {
|
|
2108
2105
|
return false;
|
|
2109
2106
|
}
|
|
@@ -2127,11 +2124,11 @@ function confirm() {
|
|
|
2127
2124
|
echo.push('link = lDb.get(this);\n');
|
|
2128
2125
|
}
|
|
2129
2126
|
else {
|
|
2130
|
-
link =
|
|
2131
|
-
if (!link) {
|
|
2127
|
+
link = lKv.get(this);
|
|
2128
|
+
if (!await link.ping()) {
|
|
2132
2129
|
return [0, 'Failed, Redis can not be connected.'];
|
|
2133
2130
|
}
|
|
2134
|
-
echo.push('link =
|
|
2131
|
+
echo.push('link = lKv.get(this);\n');
|
|
2135
2132
|
}
|
|
2136
2133
|
if (this._get['auth'] === '') {
|
|
2137
2134
|
const r = await this._startSession(link, false, { 'ttl': 60 });
|
|
@@ -2181,11 +2178,8 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2181
2178
|
const echo = ['<pre>'];
|
|
2182
2179
|
let link = undefined;
|
|
2183
2180
|
if (this._get['type'] === 'kv') {
|
|
2184
|
-
link =
|
|
2185
|
-
|
|
2186
|
-
return [0, 'Failed, Redis can not be connected.'];
|
|
2187
|
-
}
|
|
2188
|
-
echo.push('link = await lKv.get(this);\n');
|
|
2181
|
+
link = lKv.get(this);
|
|
2182
|
+
echo.push('link = lKv.get(this);\n');
|
|
2189
2183
|
}
|
|
2190
2184
|
const origin = lJwt.getOrigin(this);
|
|
2191
2185
|
echo.push(`const origin = lJwt.getOrigin(this);
|