@naturalcycles/redis-lib 3.1.0 → 3.2.0
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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/redisClient.d.ts +3 -1
- package/dist/redisClient.js +35 -8
- package/dist/redisHashKeyValueDB.d.ts +7 -3
- package/dist/redisHashKeyValueDB.js +9 -2
- package/dist/redisKeyValueDB.d.ts +7 -3
- package/dist/redisKeyValueDB.js +9 -2
- package/package.json +10 -5
- package/src/index.ts +1 -1
- package/src/redisClient.ts +58 -12
- package/src/redisHashKeyValueDB.ts +20 -4
- package/src/redisKeyValueDB.ts +17 -4
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./redisClient"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./redisKeyValueDB"), exports);
|
|
6
5
|
tslib_1.__exportStar(require("./redisHashKeyValueDB"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./redisKeyValueDB"), exports);
|
package/dist/redisClient.d.ts
CHANGED
|
@@ -47,11 +47,13 @@ export declare class RedisClient implements CommonClient {
|
|
|
47
47
|
hmget(key: string, fields: string[]): Promise<NullableString[]>;
|
|
48
48
|
hmgetBuffer(key: string, fields: string[]): Promise<NullableBuffer[]>;
|
|
49
49
|
hincr(key: string, field: string, increment?: number): Promise<number>;
|
|
50
|
+
hincrBatch(key: string, incrementTuples: [string, number][]): Promise<[string, number][]>;
|
|
50
51
|
setWithTTL(key: string, value: string | number | Buffer, expireAt: UnixTimestampNumber): Promise<void>;
|
|
51
|
-
hsetWithTTL(
|
|
52
|
+
hsetWithTTL(_key: string, _value: AnyObject, _expireAt: UnixTimestampNumber): Promise<void>;
|
|
52
53
|
mset(obj: Record<string, string | number>): Promise<void>;
|
|
53
54
|
msetBuffer(obj: Record<string, Buffer>): Promise<void>;
|
|
54
55
|
incr(key: string, by?: number): Promise<number>;
|
|
56
|
+
incrBatch(incrementTuples: [string, number][]): Promise<[string, number][]>;
|
|
55
57
|
ttl(key: string): Promise<number>;
|
|
56
58
|
dropTable(table: string): Promise<void>;
|
|
57
59
|
clearAll(): Promise<void>;
|
package/dist/redisClient.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RedisClient = void 0;
|
|
4
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
4
5
|
/**
|
|
5
6
|
Wraps the redis sdk with unified interface.
|
|
6
7
|
Features:
|
|
@@ -98,17 +99,30 @@ class RedisClient {
|
|
|
98
99
|
async hincr(key, field, increment = 1) {
|
|
99
100
|
return await this.redis().hincrby(key, field, increment);
|
|
100
101
|
}
|
|
102
|
+
async hincrBatch(key, incrementTuples) {
|
|
103
|
+
const results = {};
|
|
104
|
+
await this.withPipeline(async (pipeline) => {
|
|
105
|
+
for (const [field, increment] of incrementTuples) {
|
|
106
|
+
pipeline.hincrby(key, field, increment, (_err, newValue) => {
|
|
107
|
+
results[field] = newValue;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const validResults = (0, js_lib_1._stringMapEntries)(results).filter(([_, v]) => v !== undefined);
|
|
112
|
+
return validResults;
|
|
113
|
+
}
|
|
101
114
|
async setWithTTL(key, value, expireAt) {
|
|
102
115
|
await this.redis().set(key, value, 'EXAT', expireAt);
|
|
103
116
|
}
|
|
104
|
-
async hsetWithTTL(
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
await this.redis().
|
|
117
|
+
async hsetWithTTL(_key, _value, _expireAt) {
|
|
118
|
+
throw new Error('Not supported until Redis 7.4.0');
|
|
119
|
+
// const valueKeys = Object.keys(value)
|
|
120
|
+
// const numberOfKeys = valueKeys.length
|
|
121
|
+
// const keyList = valueKeys.join(' ')
|
|
122
|
+
// const commandString = `HEXPIREAT ${key} ${expireAt} FIELDS ${numberOfKeys} ${keyList}`
|
|
123
|
+
// const [command, ...args] = commandString.split(' ')
|
|
124
|
+
// await this.redis().hset(key, value)
|
|
125
|
+
// await this.redis().call(command!, args)
|
|
112
126
|
}
|
|
113
127
|
async mset(obj) {
|
|
114
128
|
await this.redis().mset(obj);
|
|
@@ -119,6 +133,18 @@ class RedisClient {
|
|
|
119
133
|
async incr(key, by = 1) {
|
|
120
134
|
return await this.redis().incrby(key, by);
|
|
121
135
|
}
|
|
136
|
+
async incrBatch(incrementTuples) {
|
|
137
|
+
const results = {};
|
|
138
|
+
await this.withPipeline(async (pipeline) => {
|
|
139
|
+
for (const [key, increment] of incrementTuples) {
|
|
140
|
+
pipeline.incrby(key, increment, (_err, newValue) => {
|
|
141
|
+
results[key] = newValue;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const validResults = (0, js_lib_1._stringMapEntries)(results).filter(([_, v]) => v !== undefined);
|
|
146
|
+
return validResults;
|
|
147
|
+
}
|
|
122
148
|
async ttl(key) {
|
|
123
149
|
return await this.redis().ttl(key);
|
|
124
150
|
}
|
|
@@ -158,6 +184,7 @@ class RedisClient {
|
|
|
158
184
|
* Like scanStream, but flattens the stream of keys.
|
|
159
185
|
*/
|
|
160
186
|
scanStreamFlat(opt) {
|
|
187
|
+
// biome-ignore lint/correctness/noFlatMapIdentity: ok
|
|
161
188
|
return this.redis().scanStream(opt).flatMap(keys => keys);
|
|
162
189
|
}
|
|
163
190
|
async scanCount(opt) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommonDBCreateOptions, CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, IncrementTuple, KeyValueDBTuple } from '@naturalcycles/db-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { RedisClient } from './redisClient';
|
|
4
4
|
import { RedisKeyValueDBCfg } from './redisKeyValueDB';
|
|
@@ -9,6 +9,10 @@ export declare class RedisHashKeyValueDB implements CommonKeyValueDB, AsyncDispo
|
|
|
9
9
|
client: RedisClient;
|
|
10
10
|
keyOfHashField: string;
|
|
11
11
|
constructor(cfg: RedisHashKeyValueDBCfg);
|
|
12
|
+
support: {
|
|
13
|
+
count?: boolean;
|
|
14
|
+
increment?: boolean;
|
|
15
|
+
};
|
|
12
16
|
ping(): Promise<void>;
|
|
13
17
|
[Symbol.asyncDispose](): Promise<void>;
|
|
14
18
|
getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]>;
|
|
@@ -16,9 +20,9 @@ export declare class RedisHashKeyValueDB implements CommonKeyValueDB, AsyncDispo
|
|
|
16
20
|
saveBatch(table: string, entries: KeyValueDBTuple[], opt?: CommonKeyValueDBSaveBatchOptions): Promise<void>;
|
|
17
21
|
streamIds(table: string, limit?: number): ReadableTyped<string>;
|
|
18
22
|
streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
|
|
19
|
-
streamEntries(table: string, limit?: number
|
|
23
|
+
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
|
|
20
24
|
count(table: string): Promise<number>;
|
|
21
|
-
|
|
25
|
+
incrementBatch(table: string, increments: IncrementTuple[]): Promise<IncrementTuple[]>;
|
|
22
26
|
createTable(table: string, opt?: CommonDBCreateOptions): Promise<void>;
|
|
23
27
|
private idsToKeys;
|
|
24
28
|
private idToKey;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RedisHashKeyValueDB = void 0;
|
|
4
|
+
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
4
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
6
|
class RedisHashKeyValueDB {
|
|
6
7
|
constructor(cfg) {
|
|
8
|
+
this.support = {
|
|
9
|
+
...db_lib_1.commonKeyValueDBFullSupport,
|
|
10
|
+
};
|
|
7
11
|
this.client = cfg.client;
|
|
8
12
|
this.keyOfHashField = cfg.hashKey;
|
|
9
13
|
}
|
|
@@ -90,8 +94,11 @@ class RedisHashKeyValueDB {
|
|
|
90
94
|
match: `${table}:*`,
|
|
91
95
|
});
|
|
92
96
|
}
|
|
93
|
-
async
|
|
94
|
-
|
|
97
|
+
async incrementBatch(table, increments) {
|
|
98
|
+
const incrementTuplesWithInternalKeys = increments.map(([id, v]) => [this.idToKey(table, id), v]);
|
|
99
|
+
const resultsWithInternalKeys = await this.client.hincrBatch(this.keyOfHashField, incrementTuplesWithInternalKeys);
|
|
100
|
+
const results = resultsWithInternalKeys.map(([k, v]) => [this.keyToId(table, k), v]);
|
|
101
|
+
return results;
|
|
95
102
|
}
|
|
96
103
|
async createTable(table, opt) {
|
|
97
104
|
if (!opt?.dropIfExists)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommonDBCreateOptions, CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, IncrementTuple, KeyValueDBTuple } from '@naturalcycles/db-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { RedisClient } from './redisClient';
|
|
4
4
|
export interface RedisKeyValueDBCfg {
|
|
@@ -7,6 +7,10 @@ export interface RedisKeyValueDBCfg {
|
|
|
7
7
|
export declare class RedisKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
8
8
|
constructor(cfg: RedisKeyValueDBCfg);
|
|
9
9
|
client: RedisClient;
|
|
10
|
+
support: {
|
|
11
|
+
count?: boolean;
|
|
12
|
+
increment?: boolean;
|
|
13
|
+
};
|
|
10
14
|
ping(): Promise<void>;
|
|
11
15
|
[Symbol.asyncDispose](): Promise<void>;
|
|
12
16
|
getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]>;
|
|
@@ -14,9 +18,9 @@ export declare class RedisKeyValueDB implements CommonKeyValueDB, AsyncDisposabl
|
|
|
14
18
|
saveBatch(table: string, entries: KeyValueDBTuple[], opt?: CommonKeyValueDBSaveBatchOptions): Promise<void>;
|
|
15
19
|
streamIds(table: string, limit?: number): ReadableTyped<string>;
|
|
16
20
|
streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
|
|
17
|
-
streamEntries(table: string, limit?: number
|
|
21
|
+
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
|
|
18
22
|
count(table: string): Promise<number>;
|
|
19
|
-
|
|
23
|
+
incrementBatch(table: string, increments: IncrementTuple[]): Promise<IncrementTuple[]>;
|
|
20
24
|
createTable(table: string, opt?: CommonDBCreateOptions): Promise<void>;
|
|
21
25
|
private idsToKeys;
|
|
22
26
|
private idToKey;
|
package/dist/redisKeyValueDB.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RedisKeyValueDB = void 0;
|
|
4
|
+
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
4
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
6
|
class RedisKeyValueDB {
|
|
6
7
|
constructor(cfg) {
|
|
8
|
+
this.support = {
|
|
9
|
+
...db_lib_1.commonKeyValueDBFullSupport,
|
|
10
|
+
};
|
|
7
11
|
this.client = cfg.client;
|
|
8
12
|
}
|
|
9
13
|
async ping() {
|
|
@@ -85,8 +89,11 @@ class RedisKeyValueDB {
|
|
|
85
89
|
match: `${table}:*`,
|
|
86
90
|
});
|
|
87
91
|
}
|
|
88
|
-
async
|
|
89
|
-
|
|
92
|
+
async incrementBatch(table, increments) {
|
|
93
|
+
const incrementTuplesWithInternalKeys = increments.map(([id, v]) => [this.idToKey(table, id), v]);
|
|
94
|
+
const resultsWithInternalKeys = await this.client.incrBatch(incrementTuplesWithInternalKeys);
|
|
95
|
+
const results = resultsWithInternalKeys.map(([k, v]) => [this.keyToId(table, k), v]);
|
|
96
|
+
return results;
|
|
90
97
|
}
|
|
91
98
|
async createTable(table, opt) {
|
|
92
99
|
if (!opt?.dropIfExists)
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/redis-lib",
|
|
3
3
|
"scripts": {
|
|
4
|
-
"prepare": "husky"
|
|
4
|
+
"prepare": "husky",
|
|
5
|
+
"build": "dev-lib build",
|
|
6
|
+
"test": "dev-lib test",
|
|
7
|
+
"lint": "dev-lib lint",
|
|
8
|
+
"bt": "dev-lib bt",
|
|
9
|
+
"lbt": "dev-lib lbt"
|
|
5
10
|
},
|
|
6
11
|
"dependencies": {
|
|
7
12
|
"@naturalcycles/db-lib": "^9.9.2",
|
|
@@ -10,8 +15,8 @@
|
|
|
10
15
|
"ioredis": "^5.3.2"
|
|
11
16
|
},
|
|
12
17
|
"devDependencies": {
|
|
13
|
-
"@naturalcycles/dev-lib": "^
|
|
14
|
-
"@types/node": "^
|
|
18
|
+
"@naturalcycles/dev-lib": "^15.22.0",
|
|
19
|
+
"@types/node": "^22.7.5",
|
|
15
20
|
"jest": "^29.7.0"
|
|
16
21
|
},
|
|
17
22
|
"files": [
|
|
@@ -33,9 +38,9 @@
|
|
|
33
38
|
"url": "https://github.com/NaturalCycles/redis-lib"
|
|
34
39
|
},
|
|
35
40
|
"engines": {
|
|
36
|
-
"node": ">=
|
|
41
|
+
"node": ">=20.13"
|
|
37
42
|
},
|
|
38
|
-
"version": "3.
|
|
43
|
+
"version": "3.2.0",
|
|
39
44
|
"description": "Redis implementation of CommonKeyValueDB interface",
|
|
40
45
|
"author": "Natural Cycles Team",
|
|
41
46
|
"license": "MIT"
|
package/src/index.ts
CHANGED
package/src/redisClient.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
_stringMapEntries,
|
|
2
3
|
AnyObject,
|
|
3
4
|
CommonLogger,
|
|
4
5
|
NullableBuffer,
|
|
5
6
|
NullableString,
|
|
6
7
|
Promisable,
|
|
8
|
+
StringMap,
|
|
7
9
|
UnixTimestampNumber,
|
|
8
10
|
} from '@naturalcycles/js-lib'
|
|
9
11
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
10
|
-
// eslint-disable-next-line import/no-duplicates
|
|
12
|
+
// eslint-disable-next-line import-x/no-duplicates
|
|
11
13
|
import type { Redis, RedisOptions } from 'ioredis'
|
|
12
|
-
// eslint-disable-next-line import/no-duplicates
|
|
14
|
+
// eslint-disable-next-line import-x/no-duplicates
|
|
13
15
|
import type * as RedisLib from 'ioredis'
|
|
14
16
|
import type { ScanStreamOptions } from 'ioredis/built/types'
|
|
15
17
|
import type { ChainableCommander } from 'ioredis/built/utils/RedisCommander'
|
|
@@ -153,10 +155,29 @@ export class RedisClient implements CommonClient {
|
|
|
153
155
|
return await this.redis().hmgetBuffer(key, ...fields)
|
|
154
156
|
}
|
|
155
157
|
|
|
156
|
-
async hincr(key: string, field: string, increment
|
|
158
|
+
async hincr(key: string, field: string, increment = 1): Promise<number> {
|
|
157
159
|
return await this.redis().hincrby(key, field, increment)
|
|
158
160
|
}
|
|
159
161
|
|
|
162
|
+
async hincrBatch(key: string, incrementTuples: [string, number][]): Promise<[string, number][]> {
|
|
163
|
+
const results: StringMap<number | undefined> = {}
|
|
164
|
+
|
|
165
|
+
await this.withPipeline(async pipeline => {
|
|
166
|
+
for (const [field, increment] of incrementTuples) {
|
|
167
|
+
pipeline.hincrby(key, field, increment, (_err, newValue) => {
|
|
168
|
+
results[field] = newValue
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const validResults = _stringMapEntries(results).filter(([_, v]) => v !== undefined) as [
|
|
174
|
+
string,
|
|
175
|
+
number,
|
|
176
|
+
][]
|
|
177
|
+
|
|
178
|
+
return validResults
|
|
179
|
+
}
|
|
180
|
+
|
|
160
181
|
async setWithTTL(
|
|
161
182
|
key: string,
|
|
162
183
|
value: string | number | Buffer,
|
|
@@ -165,14 +186,19 @@ export class RedisClient implements CommonClient {
|
|
|
165
186
|
await this.redis().set(key, value, 'EXAT', expireAt)
|
|
166
187
|
}
|
|
167
188
|
|
|
168
|
-
async hsetWithTTL(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
189
|
+
async hsetWithTTL(
|
|
190
|
+
_key: string,
|
|
191
|
+
_value: AnyObject,
|
|
192
|
+
_expireAt: UnixTimestampNumber,
|
|
193
|
+
): Promise<void> {
|
|
194
|
+
throw new Error('Not supported until Redis 7.4.0')
|
|
195
|
+
// const valueKeys = Object.keys(value)
|
|
196
|
+
// const numberOfKeys = valueKeys.length
|
|
197
|
+
// const keyList = valueKeys.join(' ')
|
|
198
|
+
// const commandString = `HEXPIREAT ${key} ${expireAt} FIELDS ${numberOfKeys} ${keyList}`
|
|
199
|
+
// const [command, ...args] = commandString.split(' ')
|
|
200
|
+
// await this.redis().hset(key, value)
|
|
201
|
+
// await this.redis().call(command!, args)
|
|
176
202
|
}
|
|
177
203
|
|
|
178
204
|
async mset(obj: Record<string, string | number>): Promise<void> {
|
|
@@ -183,10 +209,29 @@ export class RedisClient implements CommonClient {
|
|
|
183
209
|
await this.redis().mset(obj)
|
|
184
210
|
}
|
|
185
211
|
|
|
186
|
-
async incr(key: string, by
|
|
212
|
+
async incr(key: string, by = 1): Promise<number> {
|
|
187
213
|
return await this.redis().incrby(key, by)
|
|
188
214
|
}
|
|
189
215
|
|
|
216
|
+
async incrBatch(incrementTuples: [string, number][]): Promise<[string, number][]> {
|
|
217
|
+
const results: StringMap<number | undefined> = {}
|
|
218
|
+
|
|
219
|
+
await this.withPipeline(async pipeline => {
|
|
220
|
+
for (const [key, increment] of incrementTuples) {
|
|
221
|
+
pipeline.incrby(key, increment, (_err, newValue) => {
|
|
222
|
+
results[key] = newValue
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
const validResults = _stringMapEntries(results).filter(([_, v]) => v !== undefined) as [
|
|
228
|
+
string,
|
|
229
|
+
number,
|
|
230
|
+
][]
|
|
231
|
+
|
|
232
|
+
return validResults
|
|
233
|
+
}
|
|
234
|
+
|
|
190
235
|
async ttl(key: string): Promise<number> {
|
|
191
236
|
return await this.redis().ttl(key)
|
|
192
237
|
}
|
|
@@ -234,6 +279,7 @@ export class RedisClient implements CommonClient {
|
|
|
234
279
|
* Like scanStream, but flattens the stream of keys.
|
|
235
280
|
*/
|
|
236
281
|
scanStreamFlat(opt: ScanStreamOptions): ReadableTyped<string> {
|
|
282
|
+
// biome-ignore lint/correctness/noFlatMapIdentity: ok
|
|
237
283
|
return (this.redis().scanStream(opt) as ReadableTyped<string[]>).flatMap(keys => keys)
|
|
238
284
|
}
|
|
239
285
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CommonKeyValueDBSaveBatchOptions,
|
|
3
2
|
CommonDBCreateOptions,
|
|
4
3
|
CommonKeyValueDB,
|
|
4
|
+
commonKeyValueDBFullSupport,
|
|
5
|
+
CommonKeyValueDBSaveBatchOptions,
|
|
6
|
+
IncrementTuple,
|
|
5
7
|
KeyValueDBTuple,
|
|
6
8
|
} from '@naturalcycles/db-lib'
|
|
7
9
|
import { _chunk, StringMap } from '@naturalcycles/js-lib'
|
|
@@ -22,6 +24,10 @@ export class RedisHashKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
22
24
|
this.keyOfHashField = cfg.hashKey
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
support = {
|
|
28
|
+
...commonKeyValueDBFullSupport,
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
async ping(): Promise<void> {
|
|
26
32
|
await this.client.ping()
|
|
27
33
|
}
|
|
@@ -96,7 +102,7 @@ export class RedisHashKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
96
102
|
.take(limit || Infinity)
|
|
97
103
|
}
|
|
98
104
|
|
|
99
|
-
streamEntries(table: string, limit?: number
|
|
105
|
+
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple> {
|
|
100
106
|
return this.client
|
|
101
107
|
.hscanStream(this.keyOfHashField, {
|
|
102
108
|
match: `${table}:*`,
|
|
@@ -116,8 +122,18 @@ export class RedisHashKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
116
122
|
})
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
async
|
|
120
|
-
|
|
125
|
+
async incrementBatch(table: string, increments: IncrementTuple[]): Promise<IncrementTuple[]> {
|
|
126
|
+
const incrementTuplesWithInternalKeys = increments.map(
|
|
127
|
+
([id, v]) => [this.idToKey(table, id), v] as [string, number],
|
|
128
|
+
)
|
|
129
|
+
const resultsWithInternalKeys = await this.client.hincrBatch(
|
|
130
|
+
this.keyOfHashField,
|
|
131
|
+
incrementTuplesWithInternalKeys,
|
|
132
|
+
)
|
|
133
|
+
const results = resultsWithInternalKeys.map(
|
|
134
|
+
([k, v]) => [this.keyToId(table, k), v] as IncrementTuple,
|
|
135
|
+
)
|
|
136
|
+
return results
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
async createTable(table: string, opt?: CommonDBCreateOptions): Promise<void> {
|
package/src/redisKeyValueDB.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CommonKeyValueDBSaveBatchOptions,
|
|
3
2
|
CommonDBCreateOptions,
|
|
4
3
|
CommonKeyValueDB,
|
|
4
|
+
commonKeyValueDBFullSupport,
|
|
5
|
+
CommonKeyValueDBSaveBatchOptions,
|
|
6
|
+
IncrementTuple,
|
|
5
7
|
KeyValueDBTuple,
|
|
6
8
|
} from '@naturalcycles/db-lib'
|
|
7
9
|
import { _isTruthy, _zip } from '@naturalcycles/js-lib'
|
|
@@ -19,6 +21,10 @@ export class RedisKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
19
21
|
|
|
20
22
|
client: RedisClient
|
|
21
23
|
|
|
24
|
+
support = {
|
|
25
|
+
...commonKeyValueDBFullSupport,
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
async ping(): Promise<void> {
|
|
23
29
|
await this.client.ping()
|
|
24
30
|
}
|
|
@@ -93,7 +99,7 @@ export class RedisKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
93
99
|
.take(limit || Infinity)
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
streamEntries(table: string, limit?: number
|
|
102
|
+
streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple> {
|
|
97
103
|
return this.client
|
|
98
104
|
.scanStream({
|
|
99
105
|
match: `${table}:*`,
|
|
@@ -118,8 +124,15 @@ export class RedisKeyValueDB implements CommonKeyValueDB, AsyncDisposable {
|
|
|
118
124
|
})
|
|
119
125
|
}
|
|
120
126
|
|
|
121
|
-
async
|
|
122
|
-
|
|
127
|
+
async incrementBatch(table: string, increments: IncrementTuple[]): Promise<IncrementTuple[]> {
|
|
128
|
+
const incrementTuplesWithInternalKeys = increments.map(
|
|
129
|
+
([id, v]) => [this.idToKey(table, id), v] as [string, number],
|
|
130
|
+
)
|
|
131
|
+
const resultsWithInternalKeys = await this.client.incrBatch(incrementTuplesWithInternalKeys)
|
|
132
|
+
const results = resultsWithInternalKeys.map(
|
|
133
|
+
([k, v]) => [this.keyToId(table, k), v] as IncrementTuple,
|
|
134
|
+
)
|
|
135
|
+
return results
|
|
123
136
|
}
|
|
124
137
|
|
|
125
138
|
async createTable(table: string, opt?: CommonDBCreateOptions): Promise<void> {
|