@maiyunnet/kebab 4.0.1 → 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 -136
- 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,68 +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
|
-
if (pwd) {
|
|
56
|
-
await this._link.auth(pwd, user || undefined);
|
|
57
|
-
}
|
|
58
|
-
await this._link.select(this._index);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
catch (e) {
|
|
62
|
-
// --- 初始化失败,移除 ---
|
|
63
|
-
lCore.debug('[KV][init][error]', e);
|
|
64
|
-
const item = connections.findIndex(item => item.link === this._link);
|
|
65
|
-
if (item !== -1) {
|
|
66
|
-
connections.splice(item, 1);
|
|
67
|
-
}
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
14
|
+
constructor(etc) {
|
|
15
|
+
this._etc = etc;
|
|
70
16
|
}
|
|
71
17
|
/**
|
|
72
18
|
* --- 设定一个值 ---
|
|
@@ -76,19 +22,23 @@ export class Kv {
|
|
|
76
22
|
* @param mod 设置模式: 空,nx(key不存在才建立),xx(key存在才修改)
|
|
77
23
|
*/
|
|
78
24
|
async set(key, val, ttl = 0, mod = '') {
|
|
25
|
+
const conn = await this._getConnection();
|
|
26
|
+
if (!conn) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
79
29
|
if (typeof val !== 'string') {
|
|
80
30
|
val = lText.stringifyJson(val);
|
|
81
31
|
}
|
|
82
32
|
try {
|
|
83
33
|
switch (mod) {
|
|
84
34
|
case '': {
|
|
85
|
-
return await
|
|
35
|
+
return await conn.set(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
86
36
|
}
|
|
87
37
|
case 'nx': {
|
|
88
|
-
return await
|
|
38
|
+
return await conn.setNX(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
89
39
|
}
|
|
90
40
|
case 'xx': {
|
|
91
|
-
return await
|
|
41
|
+
return await conn.replace(this._etc.pre + key, val, ttl === 0 ? undefined : ttl);
|
|
92
42
|
}
|
|
93
43
|
}
|
|
94
44
|
}
|
|
@@ -121,8 +71,12 @@ export class Kv {
|
|
|
121
71
|
* @param val
|
|
122
72
|
*/
|
|
123
73
|
async append(key, val) {
|
|
74
|
+
const conn = await this._getConnection();
|
|
75
|
+
if (!conn) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
124
78
|
try {
|
|
125
|
-
return await
|
|
79
|
+
return await conn.append(this._etc.pre + key, val) > 0 ? true : false;
|
|
126
80
|
}
|
|
127
81
|
catch {
|
|
128
82
|
return false;
|
|
@@ -134,6 +88,10 @@ export class Kv {
|
|
|
134
88
|
* @param val
|
|
135
89
|
*/
|
|
136
90
|
async prepend(key, val) {
|
|
91
|
+
const conn = await this._getConnection();
|
|
92
|
+
if (!conn) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
137
95
|
try {
|
|
138
96
|
const script = `local val = redis.call('GET', KEYS[1])
|
|
139
97
|
if (val == false) then
|
|
@@ -145,11 +103,11 @@ if (r) then
|
|
|
145
103
|
else
|
|
146
104
|
return 0
|
|
147
105
|
end`;
|
|
148
|
-
let r = await
|
|
106
|
+
let r = await conn.evalSHA('ea360f3f6508a243824ecda6be15db56df217873', [this._etc.pre + key], [val]);
|
|
149
107
|
r = parseInt(r);
|
|
150
108
|
if (r <= 0) {
|
|
151
|
-
await
|
|
152
|
-
r = await
|
|
109
|
+
await conn.scriptLoad(script);
|
|
110
|
+
r = await conn.evalSHA('ea360f3f6508a243824ecda6be15db56df217873', [this._etc.pre + key], [val]);
|
|
153
111
|
r = parseInt(r);
|
|
154
112
|
}
|
|
155
113
|
return r > 0 ? true : false;
|
|
@@ -163,14 +121,18 @@ end`;
|
|
|
163
121
|
* @param keys 单个或序列
|
|
164
122
|
*/
|
|
165
123
|
async exists(keys) {
|
|
124
|
+
const conn = await this._getConnection();
|
|
125
|
+
if (!conn) {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
166
128
|
try {
|
|
167
129
|
if (typeof keys === 'string') {
|
|
168
130
|
keys = [keys];
|
|
169
131
|
}
|
|
170
132
|
for (let k = 0; k < keys.length; ++k) {
|
|
171
|
-
keys[k] = this.
|
|
133
|
+
keys[k] = this._etc.pre + keys[k];
|
|
172
134
|
}
|
|
173
|
-
return await
|
|
135
|
+
return await conn.mExists(keys);
|
|
174
136
|
}
|
|
175
137
|
catch {
|
|
176
138
|
return 0;
|
|
@@ -182,8 +144,12 @@ end`;
|
|
|
182
144
|
* @returns 字符串 / false / null(即使存入时是 number,这个方法也只会返回字符串)
|
|
183
145
|
*/
|
|
184
146
|
async get(key) {
|
|
147
|
+
const conn = await this._getConnection();
|
|
148
|
+
if (!conn) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
185
151
|
try {
|
|
186
|
-
return await
|
|
152
|
+
return await conn.get(this._etc.pre + key);
|
|
187
153
|
}
|
|
188
154
|
catch {
|
|
189
155
|
return false;
|
|
@@ -194,8 +160,12 @@ end`;
|
|
|
194
160
|
* @param key
|
|
195
161
|
*/
|
|
196
162
|
async ttl(key) {
|
|
163
|
+
const conn = await this._getConnection();
|
|
164
|
+
if (!conn) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
197
167
|
try {
|
|
198
|
-
return await
|
|
168
|
+
return await conn.ttl(this._etc.pre + key);
|
|
199
169
|
}
|
|
200
170
|
catch {
|
|
201
171
|
return null;
|
|
@@ -206,8 +176,12 @@ end`;
|
|
|
206
176
|
* @param key
|
|
207
177
|
*/
|
|
208
178
|
async pttl(key) {
|
|
179
|
+
const conn = await this._getConnection();
|
|
180
|
+
if (!conn) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
209
183
|
try {
|
|
210
|
-
return await
|
|
184
|
+
return await conn.pTTL(this._etc.pre + key);
|
|
211
185
|
}
|
|
212
186
|
catch {
|
|
213
187
|
return null;
|
|
@@ -218,13 +192,17 @@ end`;
|
|
|
218
192
|
* @param keys key 序列
|
|
219
193
|
*/
|
|
220
194
|
async mGet(keys) {
|
|
195
|
+
const conn = await this._getConnection();
|
|
196
|
+
if (!conn) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
221
199
|
for (let k = 0; k < keys.length; ++k) {
|
|
222
|
-
keys[k] = this.
|
|
200
|
+
keys[k] = this._etc.pre + keys[k];
|
|
223
201
|
}
|
|
224
202
|
const rtn = {};
|
|
225
203
|
try {
|
|
226
|
-
const pl = this.
|
|
227
|
-
const r = await
|
|
204
|
+
const pl = this._etc.pre.length;
|
|
205
|
+
const r = await conn.mGet(keys);
|
|
228
206
|
if (pl === 0) {
|
|
229
207
|
return r;
|
|
230
208
|
}
|
|
@@ -233,25 +211,25 @@ end`;
|
|
|
233
211
|
}
|
|
234
212
|
}
|
|
235
213
|
catch {
|
|
236
|
-
|
|
237
|
-
rtn[key] = null;
|
|
238
|
-
}
|
|
214
|
+
return false;
|
|
239
215
|
}
|
|
240
216
|
return rtn;
|
|
241
217
|
}
|
|
242
218
|
/**
|
|
243
219
|
* --- 批量设置哈希值 ---
|
|
244
|
-
* @param key key 名
|
|
245
220
|
* @param rows key / val 数组
|
|
246
|
-
* @param etc
|
|
247
221
|
*/
|
|
248
222
|
async mSet(rows) {
|
|
223
|
+
const conn = await this._getConnection();
|
|
224
|
+
if (!conn) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
249
227
|
try {
|
|
250
228
|
const rtn = {};
|
|
251
229
|
for (const key in rows) {
|
|
252
|
-
rtn[this.
|
|
230
|
+
rtn[this._etc.pre + key] = rows[key];
|
|
253
231
|
}
|
|
254
|
-
await
|
|
232
|
+
await conn.mSet(rtn);
|
|
255
233
|
return true;
|
|
256
234
|
}
|
|
257
235
|
catch {
|
|
@@ -275,14 +253,18 @@ end`;
|
|
|
275
253
|
* @param keys
|
|
276
254
|
*/
|
|
277
255
|
async del(keys) {
|
|
256
|
+
const conn = await this._getConnection();
|
|
257
|
+
if (!conn) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
278
260
|
if (typeof keys === 'string') {
|
|
279
261
|
keys = [keys];
|
|
280
262
|
}
|
|
281
263
|
for (let k = 0; k < keys.length; ++k) {
|
|
282
|
-
keys[k] = this.
|
|
264
|
+
keys[k] = this._etc.pre + keys[k];
|
|
283
265
|
}
|
|
284
266
|
try {
|
|
285
|
-
return await
|
|
267
|
+
return await conn.del(keys) > 0 ? true : false;
|
|
286
268
|
}
|
|
287
269
|
catch {
|
|
288
270
|
return false;
|
|
@@ -294,17 +276,21 @@ end`;
|
|
|
294
276
|
* @param num 整数或浮点正数
|
|
295
277
|
*/
|
|
296
278
|
async incr(key, num = 1) {
|
|
279
|
+
const conn = await this._getConnection();
|
|
280
|
+
if (!conn) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
297
283
|
try {
|
|
298
284
|
if (Number.isInteger(num)) {
|
|
299
285
|
if (num === 1) {
|
|
300
|
-
return await
|
|
286
|
+
return await conn.incr(this._etc.pre + key);
|
|
301
287
|
}
|
|
302
288
|
else {
|
|
303
|
-
return await
|
|
289
|
+
return await conn.incr(this._etc.pre + key, num);
|
|
304
290
|
}
|
|
305
291
|
}
|
|
306
292
|
else {
|
|
307
|
-
return await
|
|
293
|
+
return await conn.incrByFloat(this._etc.pre + key, num);
|
|
308
294
|
}
|
|
309
295
|
}
|
|
310
296
|
catch {
|
|
@@ -317,17 +303,21 @@ end`;
|
|
|
317
303
|
* @param num 整数或浮点正数
|
|
318
304
|
*/
|
|
319
305
|
async decr(key, num = 1) {
|
|
306
|
+
const conn = await this._getConnection();
|
|
307
|
+
if (!conn) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
320
310
|
try {
|
|
321
311
|
if (Number.isInteger(num)) {
|
|
322
312
|
if (num === 1) {
|
|
323
|
-
return await
|
|
313
|
+
return await conn.decr(this._etc.pre + key);
|
|
324
314
|
}
|
|
325
315
|
else {
|
|
326
|
-
return await
|
|
316
|
+
return await conn.decr(this._etc.pre + key, num);
|
|
327
317
|
}
|
|
328
318
|
}
|
|
329
319
|
else {
|
|
330
|
-
return await
|
|
320
|
+
return await conn.incrByFloat(this._etc.pre + key, -num);
|
|
331
321
|
}
|
|
332
322
|
}
|
|
333
323
|
catch {
|
|
@@ -340,8 +330,12 @@ end`;
|
|
|
340
330
|
* @param ttl
|
|
341
331
|
*/
|
|
342
332
|
async expire(key, ttl) {
|
|
333
|
+
const conn = await this._getConnection();
|
|
334
|
+
if (!conn) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
343
337
|
try {
|
|
344
|
-
return await
|
|
338
|
+
return await conn.expire(this._etc.pre + key, ttl);
|
|
345
339
|
}
|
|
346
340
|
catch {
|
|
347
341
|
return false;
|
|
@@ -352,9 +346,13 @@ end`;
|
|
|
352
346
|
* @param pattern
|
|
353
347
|
*/
|
|
354
348
|
async keys(pattern) {
|
|
349
|
+
const conn = await this._getConnection();
|
|
350
|
+
if (!conn) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
355
353
|
try {
|
|
356
|
-
const r = await
|
|
357
|
-
const pl = this.
|
|
354
|
+
const r = await conn.keys(this._etc.pre + pattern);
|
|
355
|
+
const pl = this._etc.pre.length;
|
|
358
356
|
if (pl > 0) {
|
|
359
357
|
for (let k = 0; k < r.length; ++k) {
|
|
360
358
|
r[k] = r[k].slice(pl);
|
|
@@ -373,10 +371,14 @@ end`;
|
|
|
373
371
|
* @param count 获取的条数
|
|
374
372
|
*/
|
|
375
373
|
async scan(cursor = 0, pattern = '*', count = 10) {
|
|
374
|
+
const conn = await this._getConnection();
|
|
375
|
+
if (!conn) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
376
378
|
try {
|
|
377
|
-
const r = await
|
|
379
|
+
const r = await conn.scan(cursor, this._etc.pre + pattern, count);
|
|
378
380
|
for (let i = 0; i < r.items.length; ++i) {
|
|
379
|
-
r.items[i] = r.items[i].slice(this.
|
|
381
|
+
r.items[i] = r.items[i].slice(this._etc.pre.length);
|
|
380
382
|
}
|
|
381
383
|
return r;
|
|
382
384
|
}
|
|
@@ -388,8 +390,12 @@ end`;
|
|
|
388
390
|
* --- 清除当前所选数据库的所有内容 ---
|
|
389
391
|
*/
|
|
390
392
|
async flushDb() {
|
|
393
|
+
const conn = await this._getConnection();
|
|
394
|
+
if (!conn) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
391
397
|
try {
|
|
392
|
-
await
|
|
398
|
+
await conn.flushDb();
|
|
393
399
|
return true;
|
|
394
400
|
}
|
|
395
401
|
catch {
|
|
@@ -401,8 +407,12 @@ end`;
|
|
|
401
407
|
* @param last 是否刷新最后使用时间(默认刷新)
|
|
402
408
|
*/
|
|
403
409
|
async ping() {
|
|
410
|
+
const conn = await this._getConnection();
|
|
411
|
+
if (!conn) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
404
414
|
try {
|
|
405
|
-
return (await
|
|
415
|
+
return (await conn.ping()) === 'PONG' ? 'PONG' : false;
|
|
406
416
|
}
|
|
407
417
|
catch {
|
|
408
418
|
return false;
|
|
@@ -416,15 +426,19 @@ end`;
|
|
|
416
426
|
* @param mod 空,nx(key不存在才建立)
|
|
417
427
|
*/
|
|
418
428
|
async hSet(key, field, val, mod = '') {
|
|
429
|
+
const conn = await this._getConnection();
|
|
430
|
+
if (!conn) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
419
433
|
try {
|
|
420
434
|
if (typeof val !== 'string') {
|
|
421
435
|
val = lText.stringifyJson(val);
|
|
422
436
|
}
|
|
423
437
|
if (mod === 'nx') {
|
|
424
|
-
return await
|
|
438
|
+
return await conn.hSetNX(this._etc.pre + key, field, val);
|
|
425
439
|
}
|
|
426
440
|
else {
|
|
427
|
-
return await
|
|
441
|
+
return await conn.hSet(this._etc.pre + key, field, val);
|
|
428
442
|
}
|
|
429
443
|
}
|
|
430
444
|
catch {
|
|
@@ -437,6 +451,10 @@ end`;
|
|
|
437
451
|
* @param rows key / val 数组
|
|
438
452
|
*/
|
|
439
453
|
async hMSet(key, rows) {
|
|
454
|
+
const conn = await this._getConnection();
|
|
455
|
+
if (!conn) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
440
458
|
try {
|
|
441
459
|
for (const i in rows) {
|
|
442
460
|
const val = rows[i];
|
|
@@ -444,7 +462,7 @@ end`;
|
|
|
444
462
|
rows[i] = lText.stringifyJson(val);
|
|
445
463
|
}
|
|
446
464
|
}
|
|
447
|
-
await
|
|
465
|
+
await conn.hMSet(this._etc.pre + key, rows);
|
|
448
466
|
return true;
|
|
449
467
|
}
|
|
450
468
|
catch {
|
|
@@ -457,11 +475,15 @@ end`;
|
|
|
457
475
|
* @param field
|
|
458
476
|
*/
|
|
459
477
|
async hGet(key, field) {
|
|
478
|
+
const conn = await this._getConnection();
|
|
479
|
+
if (!conn) {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
460
482
|
try {
|
|
461
|
-
return await
|
|
483
|
+
return await conn.hGet(this._etc.pre + key, field);
|
|
462
484
|
}
|
|
463
485
|
catch {
|
|
464
|
-
return
|
|
486
|
+
return false;
|
|
465
487
|
}
|
|
466
488
|
}
|
|
467
489
|
/**
|
|
@@ -471,6 +493,9 @@ end`;
|
|
|
471
493
|
*/
|
|
472
494
|
async hGetJson(key, field) {
|
|
473
495
|
const v = await this.hGet(key, field);
|
|
496
|
+
if (v === false) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
474
499
|
if (v === null) {
|
|
475
500
|
return null;
|
|
476
501
|
}
|
|
@@ -483,15 +508,15 @@ end`;
|
|
|
483
508
|
* @param fields
|
|
484
509
|
*/
|
|
485
510
|
async hMGet(key, fields) {
|
|
511
|
+
const conn = await this._getConnection();
|
|
512
|
+
if (!conn) {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
486
515
|
try {
|
|
487
|
-
return await
|
|
516
|
+
return await conn.hMGet(this._etc.pre + key, fields);
|
|
488
517
|
}
|
|
489
518
|
catch {
|
|
490
|
-
|
|
491
|
-
for (const field of fields) {
|
|
492
|
-
rtn[field] = null;
|
|
493
|
-
}
|
|
494
|
-
return rtn;
|
|
519
|
+
return false;
|
|
495
520
|
}
|
|
496
521
|
}
|
|
497
522
|
/**
|
|
@@ -499,11 +524,15 @@ end`;
|
|
|
499
524
|
* @param key
|
|
500
525
|
*/
|
|
501
526
|
async hGetAll(key) {
|
|
527
|
+
const conn = await this._getConnection();
|
|
528
|
+
if (!conn) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
502
531
|
try {
|
|
503
|
-
return await
|
|
532
|
+
return await conn.hGetAll(this._etc.pre + key);
|
|
504
533
|
}
|
|
505
534
|
catch {
|
|
506
|
-
return
|
|
535
|
+
return false;
|
|
507
536
|
}
|
|
508
537
|
}
|
|
509
538
|
/**
|
|
@@ -512,11 +541,15 @@ end`;
|
|
|
512
541
|
* @param fields 值序列
|
|
513
542
|
*/
|
|
514
543
|
async hDel(key, fields) {
|
|
544
|
+
const conn = await this._getConnection();
|
|
545
|
+
if (!conn) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
515
548
|
try {
|
|
516
|
-
return await
|
|
549
|
+
return await conn.hDel(this._etc.pre + key, fields);
|
|
517
550
|
}
|
|
518
551
|
catch {
|
|
519
|
-
return
|
|
552
|
+
return false;
|
|
520
553
|
}
|
|
521
554
|
}
|
|
522
555
|
/**
|
|
@@ -525,8 +558,12 @@ end`;
|
|
|
525
558
|
* @param field
|
|
526
559
|
*/
|
|
527
560
|
async hExists(key, field) {
|
|
561
|
+
const conn = await this._getConnection();
|
|
562
|
+
if (!conn) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
528
565
|
try {
|
|
529
|
-
return await
|
|
566
|
+
return await conn.hExists(this._etc.pre + key, field);
|
|
530
567
|
}
|
|
531
568
|
catch {
|
|
532
569
|
return false;
|
|
@@ -539,16 +576,20 @@ end`;
|
|
|
539
576
|
* @param increment 正数或负数,整数或浮点
|
|
540
577
|
*/
|
|
541
578
|
async hIncr(key, field, increment) {
|
|
579
|
+
const conn = await this._getConnection();
|
|
580
|
+
if (!conn) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
542
583
|
try {
|
|
543
584
|
if (Number.isInteger(increment)) {
|
|
544
|
-
return await
|
|
585
|
+
return await conn.hIncr(this._etc.pre + key, field, increment);
|
|
545
586
|
}
|
|
546
587
|
else {
|
|
547
|
-
return await
|
|
588
|
+
return await conn.hIncrByFloat(this._etc.pre + key, field, increment);
|
|
548
589
|
}
|
|
549
590
|
}
|
|
550
591
|
catch {
|
|
551
|
-
return
|
|
592
|
+
return false;
|
|
552
593
|
}
|
|
553
594
|
}
|
|
554
595
|
/**
|
|
@@ -556,78 +597,152 @@ end`;
|
|
|
556
597
|
* @param key
|
|
557
598
|
*/
|
|
558
599
|
async hKeys(key) {
|
|
600
|
+
const conn = await this._getConnection();
|
|
601
|
+
if (!conn) {
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
559
604
|
try {
|
|
560
|
-
return await
|
|
605
|
+
return await conn.hKeys(this._etc.pre + key);
|
|
561
606
|
}
|
|
562
607
|
catch {
|
|
563
|
-
return
|
|
608
|
+
return false;
|
|
564
609
|
}
|
|
565
610
|
}
|
|
566
611
|
async lPush(key, values) {
|
|
612
|
+
const conn = await this._getConnection();
|
|
613
|
+
if (!conn) {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
567
616
|
try {
|
|
568
|
-
return await
|
|
617
|
+
return await conn.lPush(this._etc.pre + key, values);
|
|
569
618
|
}
|
|
570
619
|
catch {
|
|
571
|
-
return
|
|
620
|
+
return false;
|
|
572
621
|
}
|
|
573
622
|
}
|
|
574
623
|
async rPush(key, values) {
|
|
624
|
+
const conn = await this._getConnection();
|
|
625
|
+
if (!conn) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
575
628
|
try {
|
|
576
|
-
return await
|
|
629
|
+
return await conn.rPush(this._etc.pre + key, values);
|
|
577
630
|
}
|
|
578
631
|
catch {
|
|
579
|
-
return
|
|
632
|
+
return false;
|
|
580
633
|
}
|
|
581
634
|
}
|
|
582
635
|
async bLMove(sourceKey, destKey, soo, deo, timeout) {
|
|
636
|
+
const conn = await this._getConnection();
|
|
637
|
+
if (!conn) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
583
640
|
try {
|
|
584
|
-
return await
|
|
641
|
+
return await conn.bLMove(this._etc.pre + sourceKey, this._etc.pre + destKey, soo, deo, timeout);
|
|
585
642
|
}
|
|
586
643
|
catch {
|
|
587
|
-
return
|
|
644
|
+
return false;
|
|
588
645
|
}
|
|
589
646
|
}
|
|
590
647
|
async lPop(key) {
|
|
648
|
+
const conn = await this._getConnection();
|
|
649
|
+
if (!conn) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
591
652
|
try {
|
|
592
|
-
return await
|
|
653
|
+
return await conn.lPop(this._etc.pre + key);
|
|
593
654
|
}
|
|
594
655
|
catch {
|
|
595
|
-
return
|
|
656
|
+
return false;
|
|
596
657
|
}
|
|
597
658
|
}
|
|
598
659
|
async rPop(key) {
|
|
660
|
+
const conn = await this._getConnection();
|
|
661
|
+
if (!conn) {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
599
664
|
try {
|
|
600
|
-
return await
|
|
665
|
+
return await conn.rPop(this._etc.pre + key);
|
|
601
666
|
}
|
|
602
667
|
catch {
|
|
603
|
-
return
|
|
668
|
+
return false;
|
|
604
669
|
}
|
|
605
670
|
}
|
|
606
671
|
async bRPop(key, timeout) {
|
|
672
|
+
const conn = await this._getConnection();
|
|
673
|
+
if (!conn) {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
607
676
|
try {
|
|
608
677
|
if (typeof key === 'string') {
|
|
609
678
|
key = [key];
|
|
610
679
|
}
|
|
611
|
-
return await
|
|
680
|
+
return await conn.bRPop(key.map(item => this._etc.pre + item), timeout);
|
|
612
681
|
}
|
|
613
682
|
catch {
|
|
614
|
-
return
|
|
683
|
+
return false;
|
|
615
684
|
}
|
|
616
685
|
}
|
|
617
686
|
async lRange(key, start, stop) {
|
|
687
|
+
const conn = await this._getConnection();
|
|
688
|
+
if (!conn) {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
618
691
|
try {
|
|
619
|
-
return await
|
|
692
|
+
return await conn.lRange(this._etc.pre + key, start, stop);
|
|
620
693
|
}
|
|
621
694
|
catch {
|
|
622
|
-
return
|
|
695
|
+
return false;
|
|
623
696
|
}
|
|
624
697
|
}
|
|
625
698
|
async lLen(key) {
|
|
699
|
+
const conn = await this._getConnection();
|
|
700
|
+
if (!conn) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
626
703
|
try {
|
|
627
|
-
return await
|
|
704
|
+
return await conn.lLen(this._etc.pre + key);
|
|
628
705
|
}
|
|
629
706
|
catch {
|
|
630
|
-
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;
|
|
631
746
|
}
|
|
632
747
|
}
|
|
633
748
|
}
|
|
@@ -635,9 +750,7 @@ end`;
|
|
|
635
750
|
* --- 获取 Kv 对象 ---
|
|
636
751
|
* @param etc 配置信息可留空
|
|
637
752
|
*/
|
|
638
|
-
export
|
|
639
|
-
etc
|
|
640
|
-
|
|
641
|
-
const r = await kv.init(ctr, etc);
|
|
642
|
-
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);
|
|
643
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);
|