redis-abstraction 0.0.2 → 1.0.5
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/README.md +14 -4
- package/index.d.ts +3 -0
- package/index.js +5 -1
- package/ioredis-client-pool.d.ts +11 -10
- package/ioredis-client-pool.js +14 -36
- package/package.json +10 -13
- package/redis-client-pool.d.ts +22 -0
- package/redis-client-pool.js +101 -0
- package/t-ioredis-common-commands.d.ts +20 -0
- package/t-ioredis-common-commands.js +2 -0
- package/t-redis-common-commands.d.ts +18 -0
- package/t-redis-common-commands.js +2 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A Redis client pool with abstraction to different Redis libraries.
|
|
|
4
4
|
This package helps to create redis connections in a connection pool fashion, ideally redis is single threaded so multiple connection or a connection pool for simple commands may not make sense, but there are some conditions in which connection pool makes sense like blocking commands, pub-sub commands etc apart form these cases there are also some fringe cases where if you have a simple command with a lot of data to be serialized on wire/network here multiple connections make sense as redis execution is single threaded but its I/O stack is multi so another command which has relatively small data to be serialized on wire gets stuck behind this big network transfer command ahead of it, It can take advantage of another connection where there is not que before-hand and get executed first in such a case connection pools make sense. This package also supports cluster mode connections.
|
|
5
5
|
|
|
6
6
|
Working of this package is simple it exposes an interface [i-redis-client-pool](https://github.com/LRagji/redis-abstraction/blob/main/source/i-redis-client-pool.ts) which has following methods
|
|
7
|
-
1. `acquire(token: string): Promise<void>` :
|
|
7
|
+
1. `acquire(token: string): Promise<void>` : Responsible to acquire a connection to redis server in-reference to the unique token provided.
|
|
8
8
|
2. `run(token: string, commandArgs: string[]): Promise<any>` : Responsible to run a redis command in-reference to the unique token acquired before.
|
|
9
9
|
3. `release(token: string): Promise<void>` : Responsible to release the acquired connection back into connection pool in-reference to the unique token acquired before.
|
|
10
10
|
|
|
@@ -31,10 +31,19 @@ Currently this package only supports ioredis as underneath client library, but i
|
|
|
31
31
|
### Non Cluster Initialization
|
|
32
32
|
|
|
33
33
|
```javascript
|
|
34
|
+
//Function which can decompose the connection string into different components like hostname,password etc.
|
|
35
|
+
function parseRedisConnectionString(connectionString) {
|
|
36
|
+
//Used to parse the connection string and return components of the same
|
|
37
|
+
//Refer:ioredis/built/utils/index.js parseURL function for more details
|
|
38
|
+
//This is just a mock implementation, you can enhance it as per your needs.
|
|
39
|
+
return {
|
|
40
|
+
password: ""
|
|
41
|
+
};
|
|
42
|
+
}
|
|
34
43
|
//Define the redis connection string
|
|
35
44
|
const singleNodeRedisConnectionString = 'rediss://redis.my-service.com';
|
|
36
45
|
//Create a injector function for creating redis connection instance.
|
|
37
|
-
const connectionInjector = () => IORedisClientPool.IORedisClientClusterFactory([singleNodeRedisConnectionString]);
|
|
46
|
+
const connectionInjector = () => IORedisClientPool.IORedisClientClusterFactory([singleNodeRedisConnectionString], Redis, Cluster, parseRedisConnectionString);
|
|
38
47
|
//Initialize the pool
|
|
39
48
|
const pool = new IORedisClientPool(connectionInjector);
|
|
40
49
|
|
|
@@ -52,7 +61,8 @@ main(pool)
|
|
|
52
61
|
const clusteredRedisConnectionStringPrimary = 'rediss://redis.my-service.com';
|
|
53
62
|
const clusteredRedisConnectionStringSecondary = 'rediss://redis.my-service.com' || clusteredRedisConnectionStringPrimary; //Secondary is optional if not present pass in primary connection.
|
|
54
63
|
//Create a injector function for creating redis connection instance.
|
|
55
|
-
|
|
64
|
+
//Passing more than one connection string indicates its a cluster setup.
|
|
65
|
+
const connectionInjector = () => IORedisClientPool.IORedisClientClusterFactory([clusteredRedisConnectionStringPrimary,clusteredRedisConnectionStringSecondary], Redis, Cluster, parseRedisConnectionString);
|
|
56
66
|
//Initialize the pool
|
|
57
67
|
const pool = new IORedisClientPool(connectionInjector);
|
|
58
68
|
|
|
@@ -93,4 +103,4 @@ main(pool)
|
|
|
93
103
|
|
|
94
104
|
## License
|
|
95
105
|
|
|
96
|
-
This project is
|
|
106
|
+
This project is contribution to public domain and completely free for use, view [LICENSE.md](/license.md) file for details.
|
package/index.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export { IRedisClientPool } from './i-redis-client-pool';
|
|
2
2
|
export { IORedisClientPool } from './ioredis-client-pool';
|
|
3
|
+
export { TIORedisCommonCommands } from './t-ioredis-common-commands';
|
|
4
|
+
export { RedisClientPool } from './redis-client-pool';
|
|
5
|
+
export { TRedisCommonCommands } from './t-redis-common-commands';
|
package/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IORedisClientPool = void 0;
|
|
3
|
+
exports.RedisClientPool = exports.IORedisClientPool = void 0;
|
|
4
|
+
//Implemented Class for IORedis
|
|
4
5
|
var ioredis_client_pool_1 = require("./ioredis-client-pool");
|
|
5
6
|
Object.defineProperty(exports, "IORedisClientPool", { enumerable: true, get: function () { return ioredis_client_pool_1.IORedisClientPool; } });
|
|
7
|
+
//Implemented Class for NodeRedis
|
|
8
|
+
var redis_client_pool_1 = require("./redis-client-pool");
|
|
9
|
+
Object.defineProperty(exports, "RedisClientPool", { enumerable: true, get: function () { return redis_client_pool_1.RedisClientPool; } });
|
package/ioredis-client-pool.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
import { IRedisClientPool } from "./i-redis-client-pool";
|
|
4
1
|
import crypto from 'node:crypto';
|
|
5
2
|
import fs from 'node:fs';
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { IRedisClientPool } from "./i-redis-client-pool";
|
|
4
|
+
import { TIORedisCommonCommands } from "./t-ioredis-common-commands";
|
|
5
|
+
/**
|
|
6
|
+
* A Redis Client Pool implementation using ioredis library
|
|
7
|
+
* @template redisConnectionType Type of the ioredis connection (Redis or Cluster)
|
|
8
|
+
*/
|
|
9
|
+
export declare class IORedisClientPool<redisConnectionType extends TIORedisCommonCommands> implements IRedisClientPool {
|
|
9
10
|
private readonly nodeFSModule;
|
|
10
11
|
private readonly nodeCryptoModule;
|
|
11
12
|
private poolRedisClients;
|
|
@@ -14,13 +15,13 @@ export declare class IORedisClientPool implements IRedisClientPool {
|
|
|
14
15
|
private redisConnectionCreator;
|
|
15
16
|
private idlePoolSize;
|
|
16
17
|
private totalConnectionCounter;
|
|
17
|
-
constructor(redisConnectionCreator: () =>
|
|
18
|
+
constructor(redisConnectionCreator: () => redisConnectionType, idlePoolSize?: number, nodeFSModule?: typeof fs, nodeCryptoModule?: typeof crypto);
|
|
18
19
|
generateUniqueToken(prefix: string): string;
|
|
19
20
|
shutdown(): Promise<void>;
|
|
20
21
|
acquire(token: string): Promise<void>;
|
|
21
22
|
release(token: string): Promise<void>;
|
|
22
|
-
run(token: string, commandArgs: any): Promise<
|
|
23
|
-
pipeline(token: string, commands: string[][], transaction?: boolean): Promise<
|
|
23
|
+
run(token: string, commandArgs: any): Promise<any>;
|
|
24
|
+
pipeline(token: string, commands: string[][], transaction?: boolean): Promise<any[]>;
|
|
24
25
|
script(token: string, filePath: string, keys: string[], args: any[]): Promise<any>;
|
|
25
26
|
info(): {
|
|
26
27
|
"Idle Size": number;
|
|
@@ -29,5 +30,5 @@ export declare class IORedisClientPool implements IRedisClientPool {
|
|
|
29
30
|
"Peak Connections": number;
|
|
30
31
|
};
|
|
31
32
|
private MD5Hash;
|
|
32
|
-
static IORedisClientClusterFactory(connectionDetails: string[], instanceInjection?: <T>(c: new (...args: any) => T, args: any[]) => T):
|
|
33
|
+
static IORedisClientClusterFactory(connectionDetails: string[], redisClass: new (...args: any) => TIORedisCommonCommands, clusterClass: new (...args: any) => TIORedisCommonCommands, parseURLFunction: (url: string) => Record<string, any>, instanceInjection?: <T>(c: new (...args: any) => T, args: any[]) => T): TIORedisCommonCommands;
|
|
33
34
|
}
|
package/ioredis-client-pool.js
CHANGED
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -38,9 +15,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
38
15
|
exports.IORedisClientPool = void 0;
|
|
39
16
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
40
17
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
41
|
-
const ioredis_1 = __importStar(require("ioredis"));
|
|
42
|
-
const utils_1 = require("ioredis/built/utils");
|
|
43
18
|
function createInstance(c, args = []) { return new c(...args); }
|
|
19
|
+
/**
|
|
20
|
+
* A Redis Client Pool implementation using ioredis library
|
|
21
|
+
* @template redisConnectionType Type of the ioredis connection (Redis or Cluster)
|
|
22
|
+
*/
|
|
44
23
|
class IORedisClientPool {
|
|
45
24
|
constructor(redisConnectionCreator, idlePoolSize = 6, nodeFSModule = node_fs_1.default, nodeCryptoModule = node_crypto_1.default) {
|
|
46
25
|
this.nodeFSModule = nodeFSModule;
|
|
@@ -99,14 +78,15 @@ class IORedisClientPool {
|
|
|
99
78
|
return yield redisClient.call(commandArgs.shift(), ...commandArgs);
|
|
100
79
|
});
|
|
101
80
|
}
|
|
102
|
-
pipeline(
|
|
103
|
-
return __awaiter(this,
|
|
81
|
+
pipeline(token_1, commands_1) {
|
|
82
|
+
return __awaiter(this, arguments, void 0, function* (token, commands, transaction = true) {
|
|
83
|
+
var _a;
|
|
104
84
|
const redisClient = this.activeRedisClients.get(token);
|
|
105
85
|
if (redisClient == undefined) {
|
|
106
86
|
throw new Error("Please acquire a client with proper token");
|
|
107
87
|
}
|
|
108
|
-
const result = transaction === true ? yield redisClient.multi(commands).exec() : yield redisClient.pipeline(commands).exec();
|
|
109
|
-
return result
|
|
88
|
+
const result = (_a = (transaction === true ? yield redisClient.multi(commands).exec() : yield redisClient.pipeline(commands).exec())) !== null && _a !== void 0 ? _a : [];
|
|
89
|
+
return result.map(r => {
|
|
110
90
|
let err = r[0];
|
|
111
91
|
if (err != null) {
|
|
112
92
|
throw err;
|
|
@@ -122,14 +102,12 @@ class IORedisClientPool {
|
|
|
122
102
|
throw new Error("Please acquire a client with proper token");
|
|
123
103
|
}
|
|
124
104
|
let command = this.filenameToCommand.get(filePath);
|
|
125
|
-
// @ts-ignore
|
|
126
105
|
if (command == null || redisClient[command] == null) {
|
|
127
106
|
const contents = yield this.nodeFSModule.promises.readFile(filePath, { encoding: "utf-8" });
|
|
128
107
|
command = this.MD5Hash(contents);
|
|
129
108
|
redisClient.defineCommand(command, { lua: contents });
|
|
130
109
|
this.filenameToCommand.set(filePath, command);
|
|
131
110
|
}
|
|
132
|
-
// @ts-ignore
|
|
133
111
|
return yield redisClient[command](keys.length, keys, args);
|
|
134
112
|
});
|
|
135
113
|
}
|
|
@@ -146,13 +124,13 @@ class IORedisClientPool {
|
|
|
146
124
|
MD5Hash(value) {
|
|
147
125
|
return this.nodeCryptoModule.createHash('md5').update(value).digest('hex');
|
|
148
126
|
}
|
|
149
|
-
static IORedisClientClusterFactory(connectionDetails, instanceInjection = createInstance) {
|
|
127
|
+
static IORedisClientClusterFactory(connectionDetails, redisClass, clusterClass, parseURLFunction, instanceInjection = createInstance) {
|
|
150
128
|
const distinctConnections = new Set(connectionDetails);
|
|
151
129
|
if (distinctConnections.size === 0) {
|
|
152
|
-
throw new Error("
|
|
130
|
+
throw new Error("Incorrect or Invalid Connection details, cannot be empty");
|
|
153
131
|
}
|
|
154
132
|
if (connectionDetails.length > distinctConnections.size || distinctConnections.size > 1) {
|
|
155
|
-
const parsedRedisURl = (
|
|
133
|
+
const parsedRedisURl = parseURLFunction(connectionDetails[0]); //Assuming all have same password(they should have finally its a cluster)
|
|
156
134
|
const awsElasticCacheOptions = {
|
|
157
135
|
dnsLookup: (address, callback) => callback(null, address),
|
|
158
136
|
redisOptions: {
|
|
@@ -161,10 +139,10 @@ class IORedisClientPool {
|
|
|
161
139
|
maxRedirections: 32
|
|
162
140
|
},
|
|
163
141
|
};
|
|
164
|
-
return instanceInjection(
|
|
142
|
+
return instanceInjection(clusterClass, [Array.from(distinctConnections.values()), awsElasticCacheOptions]);
|
|
165
143
|
}
|
|
166
144
|
else {
|
|
167
|
-
return instanceInjection(
|
|
145
|
+
return instanceInjection(redisClass, [connectionDetails[0]]);
|
|
168
146
|
}
|
|
169
147
|
}
|
|
170
148
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redis-abstraction",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A Redis client pool with abstraction to different Redis libraries.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -39,18 +39,15 @@
|
|
|
39
39
|
"Laukik"
|
|
40
40
|
],
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/mocha": "^
|
|
43
|
-
"@types/sinon": "^
|
|
44
|
-
"cross-env": "^
|
|
45
|
-
"mocha": "^
|
|
46
|
-
"nyc": "^
|
|
42
|
+
"@types/mocha": "^10.0.10",
|
|
43
|
+
"@types/sinon": "^21.0.0",
|
|
44
|
+
"cross-env": "^10.1.0",
|
|
45
|
+
"mocha": "^11.3.0",
|
|
46
|
+
"nyc": "^17.1.0",
|
|
47
47
|
"run-script-os": "^1.1.6",
|
|
48
|
-
"sinon": "^
|
|
49
|
-
"ts-node": "^10.
|
|
50
|
-
"typedoc": "^0.
|
|
51
|
-
"typescript": "^
|
|
52
|
-
},
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"ioredis": "^5.3.2"
|
|
48
|
+
"sinon": "^21.0.1",
|
|
49
|
+
"ts-node": "^10.9.2",
|
|
50
|
+
"typedoc": "^0.28.16",
|
|
51
|
+
"typescript": "^5.9.3"
|
|
55
52
|
}
|
|
56
53
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { IRedisClientPool } from "./i-redis-client-pool";
|
|
4
|
+
import { TRedisCommonCommands } from './t-redis-common-commands';
|
|
5
|
+
export declare class RedisClientPool<redisConnectionType extends TRedisCommonCommands> implements IRedisClientPool {
|
|
6
|
+
private readonly redisConnectionCreator;
|
|
7
|
+
private idlePoolSize;
|
|
8
|
+
private readonly nodeFSModule;
|
|
9
|
+
private readonly nodeCryptoModule;
|
|
10
|
+
private totalConnectionCounter;
|
|
11
|
+
private poolRedisClients;
|
|
12
|
+
private activeRedisClients;
|
|
13
|
+
constructor(redisConnectionCreator: () => redisConnectionType, idlePoolSize?: number, nodeFSModule?: typeof fs, nodeCryptoModule?: typeof crypto);
|
|
14
|
+
initialize(): Promise<void>;
|
|
15
|
+
acquire(token: string): Promise<void>;
|
|
16
|
+
release(token: string): Promise<void>;
|
|
17
|
+
shutdown(): Promise<void>;
|
|
18
|
+
run(token: string, commandArgs: string[]): Promise<any>;
|
|
19
|
+
pipeline(token: string, commands: string[][], transaction: boolean): Promise<any>;
|
|
20
|
+
script(token: string, filePath: string, keys: string[], args: string[]): Promise<any>;
|
|
21
|
+
generateUniqueToken(prefix: string): string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RedisClientPool = void 0;
|
|
16
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
17
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
18
|
+
class RedisClientPool {
|
|
19
|
+
constructor(redisConnectionCreator, idlePoolSize = 6, nodeFSModule = node_fs_1.default, nodeCryptoModule = node_crypto_1.default) {
|
|
20
|
+
this.redisConnectionCreator = redisConnectionCreator;
|
|
21
|
+
this.idlePoolSize = idlePoolSize;
|
|
22
|
+
this.nodeFSModule = nodeFSModule;
|
|
23
|
+
this.nodeCryptoModule = nodeCryptoModule;
|
|
24
|
+
this.totalConnectionCounter = 0;
|
|
25
|
+
this.poolRedisClients = Array.from({ length: idlePoolSize }, (_) => redisConnectionCreator());
|
|
26
|
+
this.totalConnectionCounter += idlePoolSize;
|
|
27
|
+
this.activeRedisClients = new Map();
|
|
28
|
+
}
|
|
29
|
+
initialize() {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const initHandles = this.poolRedisClients.map((_) => __awaiter(this, void 0, void 0, function* () { yield _.connect(); }));
|
|
32
|
+
yield Promise.allSettled(initHandles);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
acquire(token) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
if (!this.activeRedisClients.has(token)) {
|
|
38
|
+
const availableClient = this.poolRedisClients.pop() || (() => { this.totalConnectionCounter += 1; return this.redisConnectionCreator(); })();
|
|
39
|
+
this.activeRedisClients.set(token, availableClient);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
release(token) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const releasedClient = this.activeRedisClients.get(token);
|
|
46
|
+
if (releasedClient == undefined) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.activeRedisClients.delete(token);
|
|
50
|
+
if (this.poolRedisClients.length < this.idlePoolSize) {
|
|
51
|
+
this.poolRedisClients.push(releasedClient);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
yield releasedClient.close();
|
|
55
|
+
releasedClient.destroy();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
shutdown() {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const waitHandles = [...this.poolRedisClients, ...Array.from(this.activeRedisClients.values())]
|
|
62
|
+
.map((_) => __awaiter(this, void 0, void 0, function* () { yield _.close(); _.destroy(); }));
|
|
63
|
+
yield Promise.allSettled(waitHandles);
|
|
64
|
+
this.poolRedisClients = [];
|
|
65
|
+
this.activeRedisClients.clear();
|
|
66
|
+
this.totalConnectionCounter = 0;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
run(token, commandArgs) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const redisClient = this.activeRedisClients.get(token);
|
|
72
|
+
if (redisClient == undefined) {
|
|
73
|
+
throw new Error("Please acquire a client with proper token");
|
|
74
|
+
}
|
|
75
|
+
return yield redisClient.sendCommand(commandArgs);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
pipeline(token, commands, transaction) {
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
var _a;
|
|
81
|
+
const redisClient = this.activeRedisClients.get(token);
|
|
82
|
+
if (redisClient == undefined) {
|
|
83
|
+
throw new Error("Please acquire a client with proper token");
|
|
84
|
+
}
|
|
85
|
+
const transactionContext = redisClient.multi();
|
|
86
|
+
for (const cmd of commands) {
|
|
87
|
+
const commandName = ((_a = cmd.shift()) !== null && _a !== void 0 ? _a : "").toLowerCase();
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
transactionContext[commandName](...cmd);
|
|
90
|
+
}
|
|
91
|
+
return transaction === true ? yield transactionContext.exec() : yield transactionContext.execAsPipeline();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
script(token, filePath, keys, args) {
|
|
95
|
+
throw new Error("Method not implemented.");
|
|
96
|
+
}
|
|
97
|
+
generateUniqueToken(prefix) {
|
|
98
|
+
return `${prefix}-${this.nodeCryptoModule.randomUUID()}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.RedisClientPool = RedisClientPool;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface IIORedisRequiredCommands {
|
|
2
|
+
quit(): Promise<void>;
|
|
3
|
+
disconnect(): void;
|
|
4
|
+
multi(commands: string[][]): this;
|
|
5
|
+
pipeline(commands: string[][]): this;
|
|
6
|
+
exec(): Promise<(Error | null | any)[] | null>;
|
|
7
|
+
defineCommand(commandName: string, definition: {
|
|
8
|
+
lua: string;
|
|
9
|
+
}): void;
|
|
10
|
+
call(commandName: string, ...args: any[]): Promise<any>;
|
|
11
|
+
}
|
|
12
|
+
type TExclusion<T> = {
|
|
13
|
+
[key in Exclude<string, keyof T>]: (argsLength: number, ...args: any[]) => Promise<any>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Type representing common commands for ioredis clients
|
|
17
|
+
* This interface abstracts the common methods used in both Redis and Cluster clients.
|
|
18
|
+
*/
|
|
19
|
+
export type TIORedisCommonCommands = TExclusion<IIORedisRequiredCommands> & IIORedisRequiredCommands;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface IRedisRequiredCommands {
|
|
2
|
+
close(): Promise<void>;
|
|
3
|
+
connect(): Promise<void>;
|
|
4
|
+
destroy(): void;
|
|
5
|
+
multi(): this;
|
|
6
|
+
exec(): Promise<(Error | null | any)[] | null>;
|
|
7
|
+
execAsPipeline(): Promise<(Error | null | any)[] | null>;
|
|
8
|
+
sendCommand(args: any[]): Promise<any>;
|
|
9
|
+
}
|
|
10
|
+
type TExclusion<T> = {
|
|
11
|
+
[key in Exclude<string, keyof T>]: (argsLength: number, ...args: any[]) => Promise<any>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Type representing common commands for node-redis clients
|
|
15
|
+
* This interface abstracts the common methods used in both Redis and Cluster clients.
|
|
16
|
+
*/
|
|
17
|
+
export type TRedisCommonCommands = TExclusion<IRedisRequiredCommands> & IRedisRequiredCommands;
|
|
18
|
+
export {};
|