@creator.co/wapi 1.5.3 → 1.5.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/dist/package.json +1 -1
- package/dist/src/Cache/Redis.d.ts +10 -3
- package/dist/src/Cache/Redis.js +51 -4
- package/dist/src/Cache/Redis.js.map +1 -1
- package/dist/src/Cache/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/Cache/Redis.ts +50 -9
- package/src/Cache/types.ts +1 -0
- package/tests/Cache/{Redis.test.ts → Redis-client.test.ts} +2 -2
- package/tests/Cache/Redis-cluster.test.ts +98 -0
package/dist/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RedisClientType } from 'redis';
|
|
1
|
+
import { RedisClientType, RedisClusterType } from 'redis';
|
|
2
2
|
import { CacheConfig } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Represents a Redis cache connection class.
|
|
@@ -10,7 +10,13 @@ export default class Redis {
|
|
|
10
10
|
* This property is used to create client.
|
|
11
11
|
*/
|
|
12
12
|
private static ClientFactory;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* A private static property that references the createCluster function.
|
|
15
|
+
* This property can be used to create clusters within the class.
|
|
16
|
+
*/
|
|
17
|
+
private static ClusterFactory;
|
|
18
|
+
static connection(config: CacheConfig<'redis'>): Promise<RedisClientType | RedisClusterType>;
|
|
19
|
+
private static connectionFactory;
|
|
14
20
|
/**
|
|
15
21
|
* Establishes a connection to a Redis client based on the provided configuration
|
|
16
22
|
* and holds it for reusability. If connection is detected closed, new connection is
|
|
@@ -18,5 +24,6 @@ export default class Redis {
|
|
|
18
24
|
* @param {CacheConfig<'redis'>} config - The configuration object for connecting to the Redis client.
|
|
19
25
|
* @returns {Promise<RedisClientType>} A promise that resolves to the Redis client connection.
|
|
20
26
|
*/
|
|
21
|
-
private static
|
|
27
|
+
private static redisClientConnection;
|
|
28
|
+
private static redisClusterConnection;
|
|
22
29
|
}
|
package/dist/src/Cache/Redis.js
CHANGED
|
@@ -58,6 +58,17 @@ var Redis = /** @class */ (function () {
|
|
|
58
58
|
Redis.connection = function (config) {
|
|
59
59
|
return _a.singleton.instance(config);
|
|
60
60
|
};
|
|
61
|
+
Redis.connectionFactory = function (config) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
63
|
+
return __generator(this, function (_b) {
|
|
64
|
+
if (config.clusterMode)
|
|
65
|
+
return [2 /*return*/, _a.redisClusterConnection(config)];
|
|
66
|
+
else
|
|
67
|
+
return [2 /*return*/, _a.redisClientConnection(config)];
|
|
68
|
+
return [2 /*return*/];
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
};
|
|
61
72
|
/**
|
|
62
73
|
* Establishes a connection to a Redis client based on the provided configuration
|
|
63
74
|
* and holds it for reusability. If connection is detected closed, new connection is
|
|
@@ -65,14 +76,45 @@ var Redis = /** @class */ (function () {
|
|
|
65
76
|
* @param {CacheConfig<'redis'>} config - The configuration object for connecting to the Redis client.
|
|
66
77
|
* @returns {Promise<RedisClientType>} A promise that resolves to the Redis client connection.
|
|
67
78
|
*/
|
|
68
|
-
Redis.
|
|
79
|
+
Redis.redisClientConnection = function (config) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
81
|
+
var connection;
|
|
82
|
+
return __generator(this, function (_b) {
|
|
83
|
+
switch (_b.label) {
|
|
84
|
+
case 0:
|
|
85
|
+
console.debug('Starting remote client cache connection');
|
|
86
|
+
connection = _a.ClientFactory(__assign(__assign({ username: config.username }, (config.password ? { password: config.password } : {})), { disableOfflineQueue: true, socket: {
|
|
87
|
+
host: config.hostname,
|
|
88
|
+
tls: config.enableTLS,
|
|
89
|
+
connectTimeout: 10000,
|
|
90
|
+
} }));
|
|
91
|
+
return [4 /*yield*/, connection.connect()];
|
|
92
|
+
case 1:
|
|
93
|
+
_b.sent();
|
|
94
|
+
return [2 /*return*/, connection];
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
Redis.redisClusterConnection = function (config) {
|
|
69
100
|
return __awaiter(this, void 0, void 0, function () {
|
|
70
101
|
var connection;
|
|
71
102
|
return __generator(this, function (_b) {
|
|
72
103
|
switch (_b.label) {
|
|
73
104
|
case 0:
|
|
74
|
-
console.debug('Starting remote cache connection');
|
|
75
|
-
connection = _a.
|
|
105
|
+
console.debug('Starting remote cluster cache connection');
|
|
106
|
+
connection = _a.ClusterFactory({
|
|
107
|
+
defaults: __assign(__assign({ username: config.username }, (config.password ? { password: config.password } : {})), { socket: {
|
|
108
|
+
tls: config.enableTLS,
|
|
109
|
+
connectTimeout: 10000,
|
|
110
|
+
} }),
|
|
111
|
+
rootNodes: [
|
|
112
|
+
{
|
|
113
|
+
url: "redis://".concat(config.username, ":").concat(config.username, "@").concat(config.hostname, ":6379"),
|
|
114
|
+
disableOfflineQueue: true,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
});
|
|
76
118
|
return [4 /*yield*/, connection.connect()];
|
|
77
119
|
case 1:
|
|
78
120
|
_b.sent();
|
|
@@ -83,7 +125,7 @@ var Redis = /** @class */ (function () {
|
|
|
83
125
|
};
|
|
84
126
|
var _a;
|
|
85
127
|
_a = Redis;
|
|
86
|
-
Redis.singleton = new AsyncSingleton_1.default(_a.
|
|
128
|
+
Redis.singleton = new AsyncSingleton_1.default(_a.connectionFactory, function (c) { return __awaiter(void 0, void 0, void 0, function () { return __generator(_a, function (_b) {
|
|
87
129
|
return [2 /*return*/, c.isOpen];
|
|
88
130
|
}); }); });
|
|
89
131
|
/**
|
|
@@ -91,6 +133,11 @@ var Redis = /** @class */ (function () {
|
|
|
91
133
|
* This property is used to create client.
|
|
92
134
|
*/
|
|
93
135
|
Redis.ClientFactory = redis_1.createClient;
|
|
136
|
+
/**
|
|
137
|
+
* A private static property that references the createCluster function.
|
|
138
|
+
* This property can be used to create clusters within the class.
|
|
139
|
+
*/
|
|
140
|
+
Redis.ClusterFactory = redis_1.createCluster;
|
|
94
141
|
return Redis;
|
|
95
142
|
}());
|
|
96
143
|
exports.default = Redis;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Redis.js","sourceRoot":"","sources":["../../../src/Cache/Redis.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+
|
|
1
|
+
{"version":3,"file":"Redis.js","sourceRoot":"","sources":["../../../src/Cache/Redis.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+BAAsF;AAGtF,yDAAmD;AACnD;;GAEG;AACH;IAAA;IAgFA,CAAC;IA9De,gBAAU,GAAxB,UACE,MAA4B;QAE5B,OAAO,EAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC;IAEoB,uBAAiB,GAAtC,UACE,MAA4B;;;gBAE5B,IAAI,MAAM,CAAC,WAAW;oBAAE,sBAAO,EAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAAA;;oBAC9D,sBAAO,EAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAA;;;;KAChD;IACD;;;;;;OAMG;IACkB,2BAAqB,GAA1C,UACE,MAA4B;;;;;;wBAE5B,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAA;wBAClD,UAAU,GAAG,EAAK,CAAC,aAAa,qBACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IACtB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzD,mBAAmB,EAAE,IAAI,EACzB,MAAM,EAAE;gCACN,IAAI,EAAE,MAAM,CAAC,QAAQ;gCACrB,GAAG,EAAE,MAAM,CAAC,SAAS;gCACrB,cAAc,EAAE,KAAK;6BACtB,IACD,CAAA;wBACF,qBAAM,UAAU,CAAC,OAAO,EAAE,EAAA;;wBAA1B,SAA0B,CAAA;wBAE1B,sBAAO,UAAiB,EAAA;;;;KACzB;IAEoB,4BAAsB,GAA3C,UACE,MAA4B;;;;;;wBAE5B,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAA;wBACnD,UAAU,GAAG,EAAK,CAAC,cAAc,CAAC;4BACtC,QAAQ,sBACN,QAAQ,EAAE,MAAM,CAAC,QAAQ,IACtB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzD,MAAM,EAAE;oCACN,GAAG,EAAE,MAAM,CAAC,SAAS;oCACrB,cAAc,EAAE,KAAK;iCACtB,GACF;4BACD,SAAS,EAAE;gCACT;oCACE,GAAG,EAAE,kBAAW,MAAM,CAAC,QAAQ,cAAI,MAAM,CAAC,QAAQ,cAAI,MAAM,CAAC,QAAQ,UAAO;oCAC5E,mBAAmB,EAAE,IAAI;iCAC1B;6BACF;yBACF,CAAC,CAAA;wBACF,qBAAM,UAAU,CAAC,OAAO,EAAE,EAAA;;wBAA1B,SAA0B,CAAA;wBAE1B,sBAAO,UAAiB,EAAA;;;;KACzB;;;IA9Ec,eAAS,GAAG,IAAI,wBAAc,CAG3C,EAAK,CAAC,iBAAiB,EAAE,UAAM,CAAC;QAAI,sBAAA,CAAC,CAAC,MAAM,EAAA;aAAA,CAAC,AAHvB,CAGuB;IAE/C;;;OAGG;IACY,mBAAa,GAAG,oBAAY,AAAf,CAAe;IAE3C;;;OAGG;IACY,oBAAc,GAAG,qBAAa,AAAhB,CAAgB;IAgE/C,YAAC;CAAA,AAhFD,IAgFC;kBAhFoB,KAAK"}
|
package/package.json
CHANGED
package/src/Cache/Redis.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RedisClientType, createClient } from 'redis'
|
|
1
|
+
import { RedisClientType, RedisClusterType, createCluster, createClient } from 'redis'
|
|
2
2
|
|
|
3
3
|
import { CacheConfig } from './types'
|
|
4
4
|
import AsyncSingleton from '../Util/AsyncSingleton'
|
|
@@ -6,10 +6,10 @@ import AsyncSingleton from '../Util/AsyncSingleton'
|
|
|
6
6
|
* Represents a Redis cache connection class.
|
|
7
7
|
*/
|
|
8
8
|
export default class Redis {
|
|
9
|
-
private static singleton = new AsyncSingleton<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
)
|
|
9
|
+
private static singleton = new AsyncSingleton<
|
|
10
|
+
RedisClientType | RedisClusterType,
|
|
11
|
+
CacheConfig<'redis'>
|
|
12
|
+
>(Redis.connectionFactory, async c => c.isOpen)
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* A private static property that holds a reference to the redis.createClient function.
|
|
@@ -17,10 +17,24 @@ export default class Redis {
|
|
|
17
17
|
*/
|
|
18
18
|
private static ClientFactory = createClient
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* A private static property that references the createCluster function.
|
|
22
|
+
* This property can be used to create clusters within the class.
|
|
23
|
+
*/
|
|
24
|
+
private static ClusterFactory = createCluster
|
|
25
|
+
|
|
26
|
+
public static connection(
|
|
27
|
+
config: CacheConfig<'redis'>
|
|
28
|
+
): Promise<RedisClientType | RedisClusterType> {
|
|
21
29
|
return Redis.singleton.instance(config)
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
private static async connectionFactory(
|
|
33
|
+
config: CacheConfig<'redis'>
|
|
34
|
+
): Promise<RedisClientType | RedisClusterType> {
|
|
35
|
+
if (config.clusterMode) return Redis.redisClusterConnection(config)
|
|
36
|
+
else return Redis.redisClientConnection(config)
|
|
37
|
+
}
|
|
24
38
|
/**
|
|
25
39
|
* Establishes a connection to a Redis client based on the provided configuration
|
|
26
40
|
* and holds it for reusability. If connection is detected closed, new connection is
|
|
@@ -28,15 +42,17 @@ export default class Redis {
|
|
|
28
42
|
* @param {CacheConfig<'redis'>} config - The configuration object for connecting to the Redis client.
|
|
29
43
|
* @returns {Promise<RedisClientType>} A promise that resolves to the Redis client connection.
|
|
30
44
|
*/
|
|
31
|
-
private static async
|
|
32
|
-
|
|
45
|
+
private static async redisClientConnection(
|
|
46
|
+
config: CacheConfig<'redis'>
|
|
47
|
+
): Promise<RedisClientType> {
|
|
48
|
+
console.debug('Starting remote client cache connection')
|
|
33
49
|
const connection = Redis.ClientFactory({
|
|
34
50
|
username: config.username,
|
|
35
51
|
...(config.password ? { password: config.password } : {}),
|
|
36
52
|
disableOfflineQueue: true,
|
|
37
53
|
socket: {
|
|
38
54
|
host: config.hostname,
|
|
39
|
-
|
|
55
|
+
tls: config.enableTLS,
|
|
40
56
|
connectTimeout: 10000,
|
|
41
57
|
},
|
|
42
58
|
})
|
|
@@ -44,4 +60,29 @@ export default class Redis {
|
|
|
44
60
|
|
|
45
61
|
return connection as any
|
|
46
62
|
}
|
|
63
|
+
|
|
64
|
+
private static async redisClusterConnection(
|
|
65
|
+
config: CacheConfig<'redis'>
|
|
66
|
+
): Promise<RedisClusterType> {
|
|
67
|
+
console.debug('Starting remote cluster cache connection')
|
|
68
|
+
const connection = Redis.ClusterFactory({
|
|
69
|
+
defaults: {
|
|
70
|
+
username: config.username,
|
|
71
|
+
...(config.password ? { password: config.password } : {}),
|
|
72
|
+
socket: {
|
|
73
|
+
tls: config.enableTLS,
|
|
74
|
+
connectTimeout: 10000,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
rootNodes: [
|
|
78
|
+
{
|
|
79
|
+
url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
|
|
80
|
+
disableOfflineQueue: true,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
await connection.connect()
|
|
85
|
+
|
|
86
|
+
return connection as any
|
|
87
|
+
}
|
|
47
88
|
}
|
package/src/Cache/types.ts
CHANGED
|
@@ -33,7 +33,7 @@ async function simpleRedisTest(config: any, concurrent?: boolean) {
|
|
|
33
33
|
disableOfflineQueue: true,
|
|
34
34
|
socket: {
|
|
35
35
|
host: config.hostname,
|
|
36
|
-
|
|
36
|
+
tls: config.enableTLS,
|
|
37
37
|
connectTimeout: 10000,
|
|
38
38
|
},
|
|
39
39
|
})
|
|
@@ -43,7 +43,7 @@ async function simpleRedisTest(config: any, concurrent?: boolean) {
|
|
|
43
43
|
expect(provider2.connect).toHaveBeenCalledTimes(1)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
describe('Redis', () => {
|
|
46
|
+
describe('Redis (client)', () => {
|
|
47
47
|
beforeEach(async () => {
|
|
48
48
|
// hack to close singleton connection
|
|
49
49
|
if (Redis['singleton'].getValue()) Redis['singleton'].clear()
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import Redis from '../../src/Cache/Redis'
|
|
2
|
+
|
|
3
|
+
let _connectionId = 1
|
|
4
|
+
|
|
5
|
+
async function simpleRedisTest(config: any, concurrent?: boolean) {
|
|
6
|
+
const RedisMock = jest.fn(() => {
|
|
7
|
+
let opened = false
|
|
8
|
+
const connectionId = _connectionId++
|
|
9
|
+
return {
|
|
10
|
+
connectionId,
|
|
11
|
+
isOpen: () => opened,
|
|
12
|
+
close: () => (opened = false),
|
|
13
|
+
connect: jest.fn(() => {
|
|
14
|
+
opened = true
|
|
15
|
+
return {
|
|
16
|
+
mget: jest.fn(() => {
|
|
17
|
+
return true
|
|
18
|
+
}),
|
|
19
|
+
}
|
|
20
|
+
}),
|
|
21
|
+
} as any
|
|
22
|
+
})
|
|
23
|
+
Redis['ClusterFactory'] = RedisMock
|
|
24
|
+
// Double call is intentional
|
|
25
|
+
const [provider, provider2] = concurrent
|
|
26
|
+
? await Promise.all([Redis.connection(config), Redis.connection(config)])
|
|
27
|
+
: [await Redis.connection(config), await Redis.connection(config)]
|
|
28
|
+
|
|
29
|
+
// client checks
|
|
30
|
+
expect(RedisMock).toHaveBeenNthCalledWith(1, {
|
|
31
|
+
defaults: {
|
|
32
|
+
username: config.username,
|
|
33
|
+
...(config.password ? { password: config.password } : {}),
|
|
34
|
+
socket: {
|
|
35
|
+
tls: config.enableTLS,
|
|
36
|
+
connectTimeout: 10000,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
rootNodes: [
|
|
40
|
+
{
|
|
41
|
+
url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
|
|
42
|
+
disableOfflineQueue: true,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
})
|
|
46
|
+
// Does not have double connection
|
|
47
|
+
expect(provider['connectionId']).toEqual(provider2['connectionId'])
|
|
48
|
+
expect(provider.connect).toHaveBeenCalledTimes(1)
|
|
49
|
+
expect(provider2.connect).toHaveBeenCalledTimes(1)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('Redis (cluster)', () => {
|
|
53
|
+
beforeEach(async () => {
|
|
54
|
+
// hack to close singleton connection
|
|
55
|
+
if (Redis['singleton'].getValue()) Redis['singleton'].clear()
|
|
56
|
+
})
|
|
57
|
+
test('Simple redis - do not connect twice', async () => {
|
|
58
|
+
await simpleRedisTest({
|
|
59
|
+
hostname: 'redis://localhost',
|
|
60
|
+
username: 'gabe',
|
|
61
|
+
password: 'mypassword',
|
|
62
|
+
enableTLS: true,
|
|
63
|
+
clusterMode: true,
|
|
64
|
+
type: 'redis',
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
test('Simple redis (no SSL) - do not connect twice', async () => {
|
|
68
|
+
await simpleRedisTest({
|
|
69
|
+
hostname: 'redis://localhost',
|
|
70
|
+
username: 'gabe',
|
|
71
|
+
password: 'mypassword',
|
|
72
|
+
enableTLS: false,
|
|
73
|
+
clusterMode: true,
|
|
74
|
+
type: 'redis',
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
test('Simple redis (passwordless) - do not connect twice', async () => {
|
|
78
|
+
await simpleRedisTest({
|
|
79
|
+
hostname: 'redis://localhost',
|
|
80
|
+
username: 'gabe',
|
|
81
|
+
enableTLS: false,
|
|
82
|
+
clusterMode: true,
|
|
83
|
+
type: 'redis',
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
test('Concurrent redis - do not connect twice', async () => {
|
|
87
|
+
await simpleRedisTest(
|
|
88
|
+
{
|
|
89
|
+
hostname: 'redis://localhost',
|
|
90
|
+
username: 'gabe',
|
|
91
|
+
enableTLS: false,
|
|
92
|
+
clusterMode: true,
|
|
93
|
+
type: 'redis',
|
|
94
|
+
},
|
|
95
|
+
true
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
})
|