@eggjs/redis 3.0.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/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/commonjs/agent.d.ts +2 -0
- package/dist/commonjs/agent.js +5 -0
- package/dist/commonjs/app.d.ts +2 -0
- package/dist/commonjs/app.js +5 -0
- package/dist/commonjs/config/config.default.d.ts +59 -0
- package/dist/commonjs/config/config.default.js +55 -0
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +4 -0
- package/dist/commonjs/lib/redis.d.ts +6 -0
- package/dist/commonjs/lib/redis.js +87 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +11 -0
- package/dist/commonjs/types.js +3 -0
- package/dist/esm/agent.d.ts +2 -0
- package/dist/esm/agent.js +3 -0
- package/dist/esm/app.d.ts +2 -0
- package/dist/esm/app.js +3 -0
- package/dist/esm/config/config.default.d.ts +59 -0
- package/dist/esm/config/config.default.js +53 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/lib/redis.d.ts +6 -0
- package/dist/esm/lib/redis.js +80 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +11 -0
- package/dist/esm/types.js +2 -0
- package/dist/package.json +4 -0
- package/package.json +94 -0
- package/src/agent.ts +3 -0
- package/src/app.ts +3 -0
- package/src/config/config.default.ts +111 -0
- package/src/index.ts +1 -0
- package/src/lib/redis.ts +92 -0
- package/src/types.ts +14 -0
- package/src/typings/index.d.ts +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017-present Alibaba Group Holding Limited and other contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# @eggjs/redis
|
|
2
|
+
|
|
3
|
+
[![NPM version][npm-image]][npm-url]
|
|
4
|
+
[](https://github.com/eggjs/redis/actions/workflows/nodejs.yml)
|
|
5
|
+
[![Test coverage][codecov-image]][codecov-url]
|
|
6
|
+
[![Known Vulnerabilities][snyk-image]][snyk-url]
|
|
7
|
+
[![npm download][download-image]][download-url]
|
|
8
|
+
[](https://nodejs.org/en/download/)
|
|
9
|
+
[](https://makeapullrequest.com)
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
[npm-image]: https://img.shields.io/npm/v/@eggjs/redis.svg?style=flat-square
|
|
13
|
+
[npm-url]: https://npmjs.org/package/@eggjs/redis
|
|
14
|
+
[codecov-image]: https://codecov.io/gh/eggjs/redis/branch/master/graph/badge.svg
|
|
15
|
+
[codecov-url]: https://codecov.io/gh/eggjs/redis
|
|
16
|
+
[snyk-image]: https://snyk.io/test/npm/@eggjs/redis/badge.svg?style=flat-square
|
|
17
|
+
[snyk-url]: https://snyk.io/test/npm/@eggjs/redis
|
|
18
|
+
[download-image]: https://img.shields.io/npm/dm/@eggjs/redis.svg?style=flat-square
|
|
19
|
+
[download-url]: https://npmjs.org/package/@eggjs/redis
|
|
20
|
+
|
|
21
|
+
Valkey / Redis client (support [redis protocol](https://redis.io/docs/latest/develop/reference/protocol-spec/)) based on iovalkey for egg framework
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i @eggjs/redis
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Valkey / Redis Plugin for egg, support egg application access to Valkey / Redis Service.
|
|
30
|
+
|
|
31
|
+
This plugin based on [ioredis](https://github.com/redis/ioredis).
|
|
32
|
+
If you want to know specific usage, you should refer to the document of [ioredis](https://github.com/redis/ioredis).
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
Change `${app_root}/config/plugin.js` to enable redis plugin:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
exports.redis = {
|
|
40
|
+
enable: true,
|
|
41
|
+
package: '@eggjs/redis',
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Configure redis information in `${app_root}/config/config.default.js`:
|
|
46
|
+
|
|
47
|
+
**Single Client**
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
config.redis = {
|
|
51
|
+
client: {
|
|
52
|
+
port: 6379, // Redis port
|
|
53
|
+
host: '127.0.0.1', // Redis host
|
|
54
|
+
password: 'auth',
|
|
55
|
+
db: 0,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Multi Clients**
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
config.redis = {
|
|
64
|
+
clients: {
|
|
65
|
+
foo: { // instanceName. See below
|
|
66
|
+
port: 6379, // Redis port
|
|
67
|
+
host: '127.0.0.1', // Redis host
|
|
68
|
+
password: 'auth',
|
|
69
|
+
db: 0,
|
|
70
|
+
},
|
|
71
|
+
bar: {
|
|
72
|
+
port: 6379,
|
|
73
|
+
host: '127.0.0.1',
|
|
74
|
+
password: 'auth',
|
|
75
|
+
db: 1,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Sentinel**
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
config.redis = {
|
|
85
|
+
client: {
|
|
86
|
+
// Sentinel instances
|
|
87
|
+
sentinels: [
|
|
88
|
+
{
|
|
89
|
+
port: 26379, // Sentinel port
|
|
90
|
+
host: '127.0.0.1', // Sentinel host
|
|
91
|
+
},
|
|
92
|
+
// other sentinel instance config
|
|
93
|
+
],
|
|
94
|
+
name: 'mymaster', // Master name
|
|
95
|
+
password: 'auth',
|
|
96
|
+
db: 0
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**No password**
|
|
102
|
+
|
|
103
|
+
Redis support no authentication access, but we are highly recommend you to use redis `requirepass` in `redis.conf`.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
$vim /etc/redis/redis.conf
|
|
107
|
+
|
|
108
|
+
requirepass xxxxxxxxxx // xxxxxxxxxx is your password
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Because it may be cause security risk, refer:
|
|
112
|
+
|
|
113
|
+
- <https://ruby-china.org/topics/28094>
|
|
114
|
+
- <https://zhuoroger.github.io/2016/07/29/redis-sec/>
|
|
115
|
+
|
|
116
|
+
If you want to access redis with no password, use `password: null`.
|
|
117
|
+
|
|
118
|
+
See [ioredis API Documentation](https://github.com/redis/ioredis#basic-usage) for all available options.
|
|
119
|
+
|
|
120
|
+
### Customize `ioredis` version
|
|
121
|
+
|
|
122
|
+
`@eggjs/redis` using `ioredis@5` now, if you want to use other version of iovalkey or ioredis,
|
|
123
|
+
you can pass the instance by `config.redis.Redis`:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
// config/config.default.js
|
|
127
|
+
config.redis = {
|
|
128
|
+
Redis: require('ioredis'), // customize ioredis version, only set when you needed
|
|
129
|
+
client: {
|
|
130
|
+
port: 6379, // Redis port
|
|
131
|
+
host: '127.0.0.1', // Redis host
|
|
132
|
+
password: 'auth',
|
|
133
|
+
db: 0,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**weakDependent**
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
config.redis = {
|
|
142
|
+
client: {
|
|
143
|
+
port: 6379, // Redis port
|
|
144
|
+
host: '127.0.0.1', // Redis host
|
|
145
|
+
password: 'auth',
|
|
146
|
+
db: 0,
|
|
147
|
+
weakDependent: true, // the redis instance won't block app start
|
|
148
|
+
},
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Usage
|
|
153
|
+
|
|
154
|
+
In controller, you can use `app.redis` to get the redis instance, check [ioredis](https://github.com/redis/ioredis#basic-usage) to see how to use.
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
// app/controller/home.js
|
|
158
|
+
|
|
159
|
+
module.exports = app => {
|
|
160
|
+
return class HomeController extends app.Controller {
|
|
161
|
+
async index() {
|
|
162
|
+
const { ctx, app } = this;
|
|
163
|
+
// set
|
|
164
|
+
await app.redis.set('foo', 'bar');
|
|
165
|
+
// get
|
|
166
|
+
ctx.body = await app.redis.get('foo');
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Multi Clients
|
|
173
|
+
|
|
174
|
+
If your Configure with multi clients, you can use `app.redis.get(instanceName)` to get the specific redis instance and use it like above.
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
// app/controller/home.js
|
|
178
|
+
|
|
179
|
+
module.exports = app => {
|
|
180
|
+
return class HomeController extends app.Controller {
|
|
181
|
+
async index() {
|
|
182
|
+
const { ctx, app } = this;
|
|
183
|
+
// set
|
|
184
|
+
await app.redis.get('instance1').set('foo', 'bar');
|
|
185
|
+
// get
|
|
186
|
+
ctx.body = await app.redis.get('instance1').get('foo');
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Clients Depend on Redis Cluster
|
|
193
|
+
|
|
194
|
+
Before you start to use Redis Cluster, please checkout the [document](https://redis.io/topics/cluster-tutorial) first, especially confirm `cluster-enabled yes` in Redis Cluster configuration file.
|
|
195
|
+
|
|
196
|
+
In controller, you also can use `app.redis` to get the redis instance based on Redis Cluster.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
// app/config/config.default.js
|
|
200
|
+
exports.redis = {
|
|
201
|
+
client: {
|
|
202
|
+
cluster: true,
|
|
203
|
+
nodes: [
|
|
204
|
+
{
|
|
205
|
+
host: '127.0.0.1',
|
|
206
|
+
port: '6379',
|
|
207
|
+
family: 'user',
|
|
208
|
+
password: 'password',
|
|
209
|
+
db: 'db',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
host: '127.0.0.1',
|
|
213
|
+
port: '6380',
|
|
214
|
+
family: 'user',
|
|
215
|
+
password: 'password',
|
|
216
|
+
db: 'db',
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// app/controller/home.js
|
|
223
|
+
module.exports = app => {
|
|
224
|
+
return class HomeController extends app.Controller {
|
|
225
|
+
async index() {
|
|
226
|
+
const { ctx, app } = this;
|
|
227
|
+
// set
|
|
228
|
+
await app.redis.set('foo', 'bar');
|
|
229
|
+
// get
|
|
230
|
+
ctx.body = await app.redis.get('foo');
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Questions & Suggestions
|
|
237
|
+
|
|
238
|
+
Please open an issue [here](https://github.com/eggjs/egg/issues).
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
[MIT](LICENSE)
|
|
243
|
+
|
|
244
|
+
## Contributors
|
|
245
|
+
|
|
246
|
+
[](https://github.com/eggjs/redis/graphs/contributors)
|
|
247
|
+
|
|
248
|
+
Made with [contributors-img](https://contrib.rocks).
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const redis_js_1 = require("./lib/redis.js");
|
|
4
|
+
exports.default = redis_js_1.RedisBoot;
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2Q0FBMkM7QUFFM0Msa0JBQWUsb0JBQVMsQ0FBQyJ9
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const redis_js_1 = require("./lib/redis.js");
|
|
4
|
+
exports.default = redis_js_1.RedisBoot;
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDZDQUEyQztBQUUzQyxrQkFBZSxvQkFBUyxDQUFDIn0=
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { RedisOptions, ClusterOptions } from 'ioredis';
|
|
2
|
+
export interface RedisClientOptions extends RedisOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Whether to enable weakDependent mode, the redis client start will not block the application start
|
|
5
|
+
*
|
|
6
|
+
* Default to `undefined`
|
|
7
|
+
*/
|
|
8
|
+
weakDependent?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface RedisClusterOptions extends ClusterOptions {
|
|
11
|
+
cluster: true;
|
|
12
|
+
nodes: RedisClientOptions[];
|
|
13
|
+
}
|
|
14
|
+
export interface RedisConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Default redis client config
|
|
17
|
+
*
|
|
18
|
+
* Default to `{}`
|
|
19
|
+
*/
|
|
20
|
+
default: RedisClientOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Single Redis or Cluster Redis config
|
|
23
|
+
*/
|
|
24
|
+
client?: RedisClientOptions | RedisClusterOptions;
|
|
25
|
+
/**
|
|
26
|
+
* Multi Redis config
|
|
27
|
+
*/
|
|
28
|
+
clients?: Record<string, RedisClientOptions>;
|
|
29
|
+
/**
|
|
30
|
+
* redis client will try to use TIME command to detect client is ready or not
|
|
31
|
+
* if your redis server not support TIME command, please set this config to false
|
|
32
|
+
* see https://redis.io/commands/time
|
|
33
|
+
*
|
|
34
|
+
* Default to `true`
|
|
35
|
+
*/
|
|
36
|
+
supportTimeCommand: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to enable redis for `app`
|
|
39
|
+
*
|
|
40
|
+
* Default to `true`
|
|
41
|
+
*/
|
|
42
|
+
app: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to enable redis for `agent`
|
|
45
|
+
*
|
|
46
|
+
* Default to `false`
|
|
47
|
+
*/
|
|
48
|
+
agent: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Customize iovalkey version, only set when you needed
|
|
51
|
+
*
|
|
52
|
+
* Default to `undefined`, which means using the built-in ioredis
|
|
53
|
+
*/
|
|
54
|
+
Redis?: any;
|
|
55
|
+
}
|
|
56
|
+
declare const _default: {
|
|
57
|
+
redis: RedisConfig;
|
|
58
|
+
};
|
|
59
|
+
export default _default;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = {
|
|
4
|
+
redis: {
|
|
5
|
+
default: {},
|
|
6
|
+
app: true,
|
|
7
|
+
agent: false,
|
|
8
|
+
supportTimeCommand: true,
|
|
9
|
+
// Single Redis
|
|
10
|
+
// client: {
|
|
11
|
+
// host: 'host',
|
|
12
|
+
// port: 'port',
|
|
13
|
+
// family: 'user',
|
|
14
|
+
// password: 'password',
|
|
15
|
+
// db: 'db',
|
|
16
|
+
// },
|
|
17
|
+
//
|
|
18
|
+
// Cluster Redis
|
|
19
|
+
// client: {
|
|
20
|
+
// cluster: true,
|
|
21
|
+
// nodes: [{
|
|
22
|
+
// host: 'host',
|
|
23
|
+
// port: 'port',
|
|
24
|
+
// family: 'user',
|
|
25
|
+
// password: 'password',
|
|
26
|
+
// db: 'db',
|
|
27
|
+
// }, {
|
|
28
|
+
// host: 'host',
|
|
29
|
+
// port: 'port',
|
|
30
|
+
// family: 'user',
|
|
31
|
+
// password: 'password',
|
|
32
|
+
// db: 'db',
|
|
33
|
+
// },
|
|
34
|
+
// ]},
|
|
35
|
+
//
|
|
36
|
+
// Multi Redis
|
|
37
|
+
// clients: {
|
|
38
|
+
// instance1: {
|
|
39
|
+
// host: 'host',
|
|
40
|
+
// port: 'port',
|
|
41
|
+
// family: 'user',
|
|
42
|
+
// password: 'password',
|
|
43
|
+
// db: 'db',
|
|
44
|
+
// },
|
|
45
|
+
// instance2: {
|
|
46
|
+
// host: 'host',
|
|
47
|
+
// port: 'port',
|
|
48
|
+
// family: 'user',
|
|
49
|
+
// password: 'password',
|
|
50
|
+
// db: 'db',
|
|
51
|
+
// },
|
|
52
|
+
// },
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBMkRBLGtCQUFlO0lBQ2IsS0FBSyxFQUFFO1FBQ0wsT0FBTyxFQUFFLEVBQUU7UUFDWCxHQUFHLEVBQUUsSUFBSTtRQUNULEtBQUssRUFBRSxLQUFLO1FBQ1osa0JBQWtCLEVBQUUsSUFBSTtRQUN4QixlQUFlO1FBQ2YsWUFBWTtRQUNaLGtCQUFrQjtRQUNsQixrQkFBa0I7UUFDbEIsb0JBQW9CO1FBQ3BCLDBCQUEwQjtRQUMxQixjQUFjO1FBQ2QsS0FBSztRQUNMLEVBQUU7UUFDRixnQkFBZ0I7UUFDaEIsWUFBWTtRQUNaLG1CQUFtQjtRQUNuQixjQUFjO1FBQ2Qsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixTQUFTO1FBQ1Qsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixPQUFPO1FBQ1AsTUFBTTtRQUNOLEVBQUU7UUFDRixjQUFjO1FBQ2QsYUFBYTtRQUNiLGlCQUFpQjtRQUNqQixvQkFBb0I7UUFDcEIsb0JBQW9CO1FBQ3BCLHNCQUFzQjtRQUN0Qiw0QkFBNEI7UUFDNUIsZ0JBQWdCO1FBQ2hCLE9BQU87UUFDUCxpQkFBaUI7UUFDakIsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixPQUFPO1FBQ1AsS0FBSztLQUNTO0NBQ2pCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
require("./types.js");
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxzQkFBb0IifQ==
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RedisBoot = void 0;
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
const node_events_1 = require("node:events");
|
|
9
|
+
const ioredis_1 = require("ioredis");
|
|
10
|
+
class RedisBoot {
|
|
11
|
+
app;
|
|
12
|
+
constructor(app) {
|
|
13
|
+
this.app = app;
|
|
14
|
+
// empty
|
|
15
|
+
}
|
|
16
|
+
async didLoad() {
|
|
17
|
+
const app = this.app;
|
|
18
|
+
if (app.type === 'application' && app.config.redis.app) {
|
|
19
|
+
app.addSingleton('redis', createClient);
|
|
20
|
+
}
|
|
21
|
+
else if (app.type === 'agent' && app.config.redis.agent) {
|
|
22
|
+
app.addSingleton('redis', createClient);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.RedisBoot = RedisBoot;
|
|
27
|
+
let count = 0;
|
|
28
|
+
function createClient(options, app) {
|
|
29
|
+
const RedisClass = app.config.redis.Redis ?? ioredis_1.Redis;
|
|
30
|
+
let client;
|
|
31
|
+
if ('cluster' in options && options.cluster === true) {
|
|
32
|
+
const config = options;
|
|
33
|
+
(0, node_assert_1.default)(config.nodes && config.nodes.length !== 0, '[@eggjs/redis] cluster nodes configuration is required when use cluster redis');
|
|
34
|
+
config.nodes.forEach(client => {
|
|
35
|
+
(0, node_assert_1.default)(client.host && client.port, `[@eggjs/redis] 'host: ${client.host}', 'port: ${client.port}' are required on config`);
|
|
36
|
+
});
|
|
37
|
+
app.coreLogger.info('[@eggjs/redis] cluster connecting');
|
|
38
|
+
client = new RedisClass.Cluster(config.nodes, config);
|
|
39
|
+
}
|
|
40
|
+
else if ('sentinels' in options && options.sentinels) {
|
|
41
|
+
const config = options;
|
|
42
|
+
(0, node_assert_1.default)(config.sentinels && config.sentinels.length !== 0, '[@eggjs/redis] sentinels configuration is required when use redis sentinel');
|
|
43
|
+
config.sentinels.forEach(sentinel => {
|
|
44
|
+
(0, node_assert_1.default)(sentinel.host && sentinel.port, `[@eggjs/redis] 'host: ${sentinel.host}', 'port: ${sentinel.port}' are required on config`);
|
|
45
|
+
});
|
|
46
|
+
const mask = config.password ? '***' : config.password;
|
|
47
|
+
(0, node_assert_1.default)(config.name && config.password !== undefined && config.db !== undefined, `[@eggjs/redis] 'name of master: ${config.name}', 'password: ${mask}', 'db: ${config.db}' are required on config`);
|
|
48
|
+
app.coreLogger.info('[@eggjs/redis] sentinel connecting start');
|
|
49
|
+
client = new RedisClass(config);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const config = options;
|
|
53
|
+
const mask = config.password ? '***' : config.password;
|
|
54
|
+
(0, node_assert_1.default)((config.host && config.port && config.password !== undefined && config.db !== undefined) || config.path, `[@eggjs/redis] 'host: ${config.host}', 'port: ${config.port}', 'password: ${mask}', 'db: ${config.db}' or 'path:${config.path}' are required on config`);
|
|
55
|
+
if (config.host) {
|
|
56
|
+
app.coreLogger.info('[@eggjs/redis] server connecting redis://:***@%s:%s/%s', config.host, config.port, config.db);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
app.coreLogger.info('[@eggjs/redis] server connecting %s', config.path || config);
|
|
60
|
+
}
|
|
61
|
+
client = new RedisClass(config);
|
|
62
|
+
}
|
|
63
|
+
client.on('connect', () => {
|
|
64
|
+
app.coreLogger.info('[@eggjs/redis] client connect success');
|
|
65
|
+
});
|
|
66
|
+
client.on('error', err => {
|
|
67
|
+
app.coreLogger.error('[@eggjs/redis] client error: %s', err);
|
|
68
|
+
app.coreLogger.error(err);
|
|
69
|
+
});
|
|
70
|
+
const index = count++;
|
|
71
|
+
app.lifecycle.registerBeforeStart(async () => {
|
|
72
|
+
if ('weakDependent' in options && options.weakDependent) {
|
|
73
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] is weak dependent and won't block app start`);
|
|
74
|
+
client.once('ready', () => {
|
|
75
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK`);
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await Promise.race([
|
|
80
|
+
(0, node_events_1.once)(client, 'ready'),
|
|
81
|
+
(0, node_events_1.once)(client, 'error'),
|
|
82
|
+
]);
|
|
83
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK, client ready`);
|
|
84
|
+
}, `[@eggjs/redis] instance[${index}] start check`);
|
|
85
|
+
return client;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JlZGlzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDhEQUFpQztBQUNqQyw2Q0FBbUM7QUFDbkMscUNBQWdDO0FBSWhDLE1BQWEsU0FBUztJQUNTO0lBQTdCLFlBQTZCLEdBQVk7UUFBWixRQUFHLEdBQUgsR0FBRyxDQUFTO1FBQ3ZDLFFBQVE7SUFDVixDQUFDO0lBQ0QsS0FBSyxDQUFDLE9BQU87UUFDWCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3JCLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxhQUFhLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDdkQsR0FBRyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDMUMsQ0FBQzthQUFNLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDMUQsR0FBRyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7Q0FDRjtBQVpELDhCQVlDO0FBRUQsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0FBQ2QsU0FBUyxZQUFZLENBQUMsT0FBaUQsRUFBRSxHQUFZO0lBQ25GLE1BQU0sVUFBVSxHQUFpQixHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksZUFBSyxDQUFDO0lBQ2pFLElBQUksTUFBTSxDQUFDO0lBRVgsSUFBSSxTQUFTLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDckQsTUFBTSxNQUFNLEdBQUcsT0FBOEIsQ0FBQztRQUM5QyxJQUFBLHFCQUFNLEVBQUMsTUFB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
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Singleton } from '@eggjs/core';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
3
|
+
import type { RedisConfig } from './config/config.default.js';
|
|
4
|
+
declare module '@eggjs/core' {
|
|
5
|
+
interface EggAppConfig {
|
|
6
|
+
redis: RedisConfig;
|
|
7
|
+
}
|
|
8
|
+
interface EggCore {
|
|
9
|
+
redis: Redis & Singleton<Redis>;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { RedisBoot } from './lib/redis.js';
|
|
2
|
+
export default RedisBoot;
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLGVBQWUsU0FBUyxDQUFDIn0=
|
package/dist/esm/app.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { RedisBoot } from './lib/redis.js';
|
|
2
|
+
export default RedisBoot;
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsZUFBZSxTQUFTLENBQUMifQ==
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { RedisOptions, ClusterOptions } from 'ioredis';
|
|
2
|
+
export interface RedisClientOptions extends RedisOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Whether to enable weakDependent mode, the redis client start will not block the application start
|
|
5
|
+
*
|
|
6
|
+
* Default to `undefined`
|
|
7
|
+
*/
|
|
8
|
+
weakDependent?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface RedisClusterOptions extends ClusterOptions {
|
|
11
|
+
cluster: true;
|
|
12
|
+
nodes: RedisClientOptions[];
|
|
13
|
+
}
|
|
14
|
+
export interface RedisConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Default redis client config
|
|
17
|
+
*
|
|
18
|
+
* Default to `{}`
|
|
19
|
+
*/
|
|
20
|
+
default: RedisClientOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Single Redis or Cluster Redis config
|
|
23
|
+
*/
|
|
24
|
+
client?: RedisClientOptions | RedisClusterOptions;
|
|
25
|
+
/**
|
|
26
|
+
* Multi Redis config
|
|
27
|
+
*/
|
|
28
|
+
clients?: Record<string, RedisClientOptions>;
|
|
29
|
+
/**
|
|
30
|
+
* redis client will try to use TIME command to detect client is ready or not
|
|
31
|
+
* if your redis server not support TIME command, please set this config to false
|
|
32
|
+
* see https://redis.io/commands/time
|
|
33
|
+
*
|
|
34
|
+
* Default to `true`
|
|
35
|
+
*/
|
|
36
|
+
supportTimeCommand: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to enable redis for `app`
|
|
39
|
+
*
|
|
40
|
+
* Default to `true`
|
|
41
|
+
*/
|
|
42
|
+
app: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to enable redis for `agent`
|
|
45
|
+
*
|
|
46
|
+
* Default to `false`
|
|
47
|
+
*/
|
|
48
|
+
agent: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Customize iovalkey version, only set when you needed
|
|
51
|
+
*
|
|
52
|
+
* Default to `undefined`, which means using the built-in ioredis
|
|
53
|
+
*/
|
|
54
|
+
Redis?: any;
|
|
55
|
+
}
|
|
56
|
+
declare const _default: {
|
|
57
|
+
redis: RedisConfig;
|
|
58
|
+
};
|
|
59
|
+
export default _default;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
redis: {
|
|
3
|
+
default: {},
|
|
4
|
+
app: true,
|
|
5
|
+
agent: false,
|
|
6
|
+
supportTimeCommand: true,
|
|
7
|
+
// Single Redis
|
|
8
|
+
// client: {
|
|
9
|
+
// host: 'host',
|
|
10
|
+
// port: 'port',
|
|
11
|
+
// family: 'user',
|
|
12
|
+
// password: 'password',
|
|
13
|
+
// db: 'db',
|
|
14
|
+
// },
|
|
15
|
+
//
|
|
16
|
+
// Cluster Redis
|
|
17
|
+
// client: {
|
|
18
|
+
// cluster: true,
|
|
19
|
+
// nodes: [{
|
|
20
|
+
// host: 'host',
|
|
21
|
+
// port: 'port',
|
|
22
|
+
// family: 'user',
|
|
23
|
+
// password: 'password',
|
|
24
|
+
// db: 'db',
|
|
25
|
+
// }, {
|
|
26
|
+
// host: 'host',
|
|
27
|
+
// port: 'port',
|
|
28
|
+
// family: 'user',
|
|
29
|
+
// password: 'password',
|
|
30
|
+
// db: 'db',
|
|
31
|
+
// },
|
|
32
|
+
// ]},
|
|
33
|
+
//
|
|
34
|
+
// Multi Redis
|
|
35
|
+
// clients: {
|
|
36
|
+
// instance1: {
|
|
37
|
+
// host: 'host',
|
|
38
|
+
// port: 'port',
|
|
39
|
+
// family: 'user',
|
|
40
|
+
// password: 'password',
|
|
41
|
+
// db: 'db',
|
|
42
|
+
// },
|
|
43
|
+
// instance2: {
|
|
44
|
+
// host: 'host',
|
|
45
|
+
// port: 'port',
|
|
46
|
+
// family: 'user',
|
|
47
|
+
// password: 'password',
|
|
48
|
+
// db: 'db',
|
|
49
|
+
// },
|
|
50
|
+
// },
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTJEQSxlQUFlO0lBQ2IsS0FBSyxFQUFFO1FBQ0wsT0FBTyxFQUFFLEVBQUU7UUFDWCxHQUFHLEVBQUUsSUFBSTtRQUNULEtBQUssRUFBRSxLQUFLO1FBQ1osa0JBQWtCLEVBQUUsSUFBSTtRQUN4QixlQUFlO1FBQ2YsWUFBWTtRQUNaLGtCQUFrQjtRQUNsQixrQkFBa0I7UUFDbEIsb0JBQW9CO1FBQ3BCLDBCQUEwQjtRQUMxQixjQUFjO1FBQ2QsS0FBSztRQUNMLEVBQUU7UUFDRixnQkFBZ0I7UUFDaEIsWUFBWTtRQUNaLG1CQUFtQjtRQUNuQixjQUFjO1FBQ2Qsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixTQUFTO1FBQ1Qsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixPQUFPO1FBQ1AsTUFBTTtRQUNOLEVBQUU7UUFDRixjQUFjO1FBQ2QsYUFBYTtRQUNiLGlCQUFpQjtRQUNqQixvQkFBb0I7UUFDcEIsb0JBQW9CO1FBQ3BCLHNCQUFzQjtRQUN0Qiw0QkFBNEI7UUFDNUIsZ0JBQWdCO1FBQ2hCLE9BQU87UUFDUCxpQkFBaUI7UUFDakIsb0JBQW9CO1FBQ3BCLG9CQUFvQjtRQUNwQixzQkFBc0I7UUFDdEIsNEJBQTRCO1FBQzVCLGdCQUFnQjtRQUNoQixPQUFPO1FBQ1AsS0FBSztLQUNTO0NBQ2pCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { once } from 'node:events';
|
|
3
|
+
import { Redis } from 'ioredis';
|
|
4
|
+
export class RedisBoot {
|
|
5
|
+
app;
|
|
6
|
+
constructor(app) {
|
|
7
|
+
this.app = app;
|
|
8
|
+
// empty
|
|
9
|
+
}
|
|
10
|
+
async didLoad() {
|
|
11
|
+
const app = this.app;
|
|
12
|
+
if (app.type === 'application' && app.config.redis.app) {
|
|
13
|
+
app.addSingleton('redis', createClient);
|
|
14
|
+
}
|
|
15
|
+
else if (app.type === 'agent' && app.config.redis.agent) {
|
|
16
|
+
app.addSingleton('redis', createClient);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
let count = 0;
|
|
21
|
+
function createClient(options, app) {
|
|
22
|
+
const RedisClass = app.config.redis.Redis ?? Redis;
|
|
23
|
+
let client;
|
|
24
|
+
if ('cluster' in options && options.cluster === true) {
|
|
25
|
+
const config = options;
|
|
26
|
+
assert(config.nodes && config.nodes.length !== 0, '[@eggjs/redis] cluster nodes configuration is required when use cluster redis');
|
|
27
|
+
config.nodes.forEach(client => {
|
|
28
|
+
assert(client.host && client.port, `[@eggjs/redis] 'host: ${client.host}', 'port: ${client.port}' are required on config`);
|
|
29
|
+
});
|
|
30
|
+
app.coreLogger.info('[@eggjs/redis] cluster connecting');
|
|
31
|
+
client = new RedisClass.Cluster(config.nodes, config);
|
|
32
|
+
}
|
|
33
|
+
else if ('sentinels' in options && options.sentinels) {
|
|
34
|
+
const config = options;
|
|
35
|
+
assert(config.sentinels && config.sentinels.length !== 0, '[@eggjs/redis] sentinels configuration is required when use redis sentinel');
|
|
36
|
+
config.sentinels.forEach(sentinel => {
|
|
37
|
+
assert(sentinel.host && sentinel.port, `[@eggjs/redis] 'host: ${sentinel.host}', 'port: ${sentinel.port}' are required on config`);
|
|
38
|
+
});
|
|
39
|
+
const mask = config.password ? '***' : config.password;
|
|
40
|
+
assert(config.name && config.password !== undefined && config.db !== undefined, `[@eggjs/redis] 'name of master: ${config.name}', 'password: ${mask}', 'db: ${config.db}' are required on config`);
|
|
41
|
+
app.coreLogger.info('[@eggjs/redis] sentinel connecting start');
|
|
42
|
+
client = new RedisClass(config);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const config = options;
|
|
46
|
+
const mask = config.password ? '***' : config.password;
|
|
47
|
+
assert((config.host && config.port && config.password !== undefined && config.db !== undefined) || config.path, `[@eggjs/redis] 'host: ${config.host}', 'port: ${config.port}', 'password: ${mask}', 'db: ${config.db}' or 'path:${config.path}' are required on config`);
|
|
48
|
+
if (config.host) {
|
|
49
|
+
app.coreLogger.info('[@eggjs/redis] server connecting redis://:***@%s:%s/%s', config.host, config.port, config.db);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
app.coreLogger.info('[@eggjs/redis] server connecting %s', config.path || config);
|
|
53
|
+
}
|
|
54
|
+
client = new RedisClass(config);
|
|
55
|
+
}
|
|
56
|
+
client.on('connect', () => {
|
|
57
|
+
app.coreLogger.info('[@eggjs/redis] client connect success');
|
|
58
|
+
});
|
|
59
|
+
client.on('error', err => {
|
|
60
|
+
app.coreLogger.error('[@eggjs/redis] client error: %s', err);
|
|
61
|
+
app.coreLogger.error(err);
|
|
62
|
+
});
|
|
63
|
+
const index = count++;
|
|
64
|
+
app.lifecycle.registerBeforeStart(async () => {
|
|
65
|
+
if ('weakDependent' in options && options.weakDependent) {
|
|
66
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] is weak dependent and won't block app start`);
|
|
67
|
+
client.once('ready', () => {
|
|
68
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK`);
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
await Promise.race([
|
|
73
|
+
once(client, 'ready'),
|
|
74
|
+
once(client, 'error'),
|
|
75
|
+
]);
|
|
76
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK, client ready`);
|
|
77
|
+
}, `[@eggjs/redis] instance[${index}] start check`);
|
|
78
|
+
return client;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JlZGlzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUNqQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ25DLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFJaEMsTUFBTSxPQUFPLFNBQVM7SUFDUztJQUE3QixZQUE2QixHQUFZO1FBQVosUUFBRyxHQUFILEdBQUcsQ0FBUztRQUN2QyxRQUFRO0lBQ1YsQ0FBQztJQUNELEtBQUssQ0FBQyxPQUFPO1FBQ1gsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNyQixJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssYUFBYSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3ZELEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFDLENBQUM7YUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzFELEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFDLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFFRCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7QUFDZCxTQUFTLFlBQVksQ0FBQyxPQUFpRCxFQUFFLEdBQVk7SUFDbkYsTUFBTSxVQUFVLEdBQWlCLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUM7SUFDakUsSUFBSSxNQUFNLENBQUM7SUFFWCxJQUFJLFNBQVMsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sS0FBSyxJQUFJLEVBQUUs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
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Singleton } from '@eggjs/core';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
3
|
+
import type { RedisConfig } from './config/config.default.js';
|
|
4
|
+
declare module '@eggjs/core' {
|
|
5
|
+
interface EggAppConfig {
|
|
6
|
+
redis: RedisConfig;
|
|
7
|
+
}
|
|
8
|
+
interface EggCore {
|
|
9
|
+
redis: Redis & Singleton<Redis>;
|
|
10
|
+
}
|
|
11
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eggjs/redis",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Valkey / Redis plugin for egg",
|
|
8
|
+
"eggPlugin": {
|
|
9
|
+
"name": "redis",
|
|
10
|
+
"exports": {
|
|
11
|
+
"import": "./dist/esm",
|
|
12
|
+
"require": "./dist/commonjs",
|
|
13
|
+
"typescript": "./src"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"egg",
|
|
18
|
+
"eggPlugin",
|
|
19
|
+
"egg-plugin",
|
|
20
|
+
"redis",
|
|
21
|
+
"Valkey",
|
|
22
|
+
"database"
|
|
23
|
+
],
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/eggjs/redis.git"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/eggjs/egg/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/eggjs/redis#readme",
|
|
32
|
+
"author": "jtyjty99999",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">= 18.19.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@eggjs/core": "^6.3.0",
|
|
39
|
+
"ioredis": "^5.4.2"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@arethetypeswrong/cli": "^0.17.1",
|
|
43
|
+
"@eggjs/bin": "7",
|
|
44
|
+
"@eggjs/mock": "^6.0.5",
|
|
45
|
+
"@eggjs/tsconfig": "1",
|
|
46
|
+
"@types/mocha": "10",
|
|
47
|
+
"@types/node": "22",
|
|
48
|
+
"egg": "^4.0.3",
|
|
49
|
+
"eslint": "8",
|
|
50
|
+
"eslint-config-egg": "14",
|
|
51
|
+
"rimraf": "6",
|
|
52
|
+
"snap-shot-it": "^7.9.10",
|
|
53
|
+
"tshy": "3",
|
|
54
|
+
"tshy-after": "1",
|
|
55
|
+
"typescript": "5"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"lint": "eslint --cache src test --ext .ts",
|
|
59
|
+
"pretest": "npm run clean && npm run lint -- --fix",
|
|
60
|
+
"test": "egg-bin test",
|
|
61
|
+
"preci": "npm run clean && npm run lint",
|
|
62
|
+
"ci": "egg-bin cov",
|
|
63
|
+
"postci": "npm run prepublishOnly && npm run clean",
|
|
64
|
+
"clean": "rimraf dist",
|
|
65
|
+
"prepublishOnly": "tshy && tshy-after && attw --pack"
|
|
66
|
+
},
|
|
67
|
+
"type": "module",
|
|
68
|
+
"tshy": {
|
|
69
|
+
"exports": {
|
|
70
|
+
".": "./src/index.ts",
|
|
71
|
+
"./package.json": "./package.json"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"exports": {
|
|
75
|
+
".": {
|
|
76
|
+
"import": {
|
|
77
|
+
"types": "./dist/esm/index.d.ts",
|
|
78
|
+
"default": "./dist/esm/index.js"
|
|
79
|
+
},
|
|
80
|
+
"require": {
|
|
81
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
82
|
+
"default": "./dist/commonjs/index.js"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"./package.json": "./package.json"
|
|
86
|
+
},
|
|
87
|
+
"files": [
|
|
88
|
+
"dist",
|
|
89
|
+
"src"
|
|
90
|
+
],
|
|
91
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
92
|
+
"main": "./dist/commonjs/index.js",
|
|
93
|
+
"module": "./dist/esm/index.js"
|
|
94
|
+
}
|
package/src/agent.ts
ADDED
package/src/app.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { RedisOptions, ClusterOptions } from 'ioredis';
|
|
2
|
+
|
|
3
|
+
export interface RedisClientOptions extends RedisOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Whether to enable weakDependent mode, the redis client start will not block the application start
|
|
6
|
+
*
|
|
7
|
+
* Default to `undefined`
|
|
8
|
+
*/
|
|
9
|
+
weakDependent?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RedisClusterOptions extends ClusterOptions {
|
|
13
|
+
cluster: true;
|
|
14
|
+
nodes: RedisClientOptions[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RedisConfig {
|
|
18
|
+
/**
|
|
19
|
+
* Default redis client config
|
|
20
|
+
*
|
|
21
|
+
* Default to `{}`
|
|
22
|
+
*/
|
|
23
|
+
default: RedisClientOptions;
|
|
24
|
+
/**
|
|
25
|
+
* Single Redis or Cluster Redis config
|
|
26
|
+
*/
|
|
27
|
+
client?: RedisClientOptions | RedisClusterOptions;
|
|
28
|
+
/**
|
|
29
|
+
* Multi Redis config
|
|
30
|
+
*/
|
|
31
|
+
clients?: Record<string, RedisClientOptions>;
|
|
32
|
+
/**
|
|
33
|
+
* redis client will try to use TIME command to detect client is ready or not
|
|
34
|
+
* if your redis server not support TIME command, please set this config to false
|
|
35
|
+
* see https://redis.io/commands/time
|
|
36
|
+
*
|
|
37
|
+
* Default to `true`
|
|
38
|
+
*/
|
|
39
|
+
supportTimeCommand: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to enable redis for `app`
|
|
42
|
+
*
|
|
43
|
+
* Default to `true`
|
|
44
|
+
*/
|
|
45
|
+
app: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to enable redis for `agent`
|
|
48
|
+
*
|
|
49
|
+
* Default to `false`
|
|
50
|
+
*/
|
|
51
|
+
agent: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Customize iovalkey version, only set when you needed
|
|
54
|
+
*
|
|
55
|
+
* Default to `undefined`, which means using the built-in ioredis
|
|
56
|
+
*/
|
|
57
|
+
Redis?: any;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default {
|
|
61
|
+
redis: {
|
|
62
|
+
default: {},
|
|
63
|
+
app: true,
|
|
64
|
+
agent: false,
|
|
65
|
+
supportTimeCommand: true,
|
|
66
|
+
// Single Redis
|
|
67
|
+
// client: {
|
|
68
|
+
// host: 'host',
|
|
69
|
+
// port: 'port',
|
|
70
|
+
// family: 'user',
|
|
71
|
+
// password: 'password',
|
|
72
|
+
// db: 'db',
|
|
73
|
+
// },
|
|
74
|
+
//
|
|
75
|
+
// Cluster Redis
|
|
76
|
+
// client: {
|
|
77
|
+
// cluster: true,
|
|
78
|
+
// nodes: [{
|
|
79
|
+
// host: 'host',
|
|
80
|
+
// port: 'port',
|
|
81
|
+
// family: 'user',
|
|
82
|
+
// password: 'password',
|
|
83
|
+
// db: 'db',
|
|
84
|
+
// }, {
|
|
85
|
+
// host: 'host',
|
|
86
|
+
// port: 'port',
|
|
87
|
+
// family: 'user',
|
|
88
|
+
// password: 'password',
|
|
89
|
+
// db: 'db',
|
|
90
|
+
// },
|
|
91
|
+
// ]},
|
|
92
|
+
//
|
|
93
|
+
// Multi Redis
|
|
94
|
+
// clients: {
|
|
95
|
+
// instance1: {
|
|
96
|
+
// host: 'host',
|
|
97
|
+
// port: 'port',
|
|
98
|
+
// family: 'user',
|
|
99
|
+
// password: 'password',
|
|
100
|
+
// db: 'db',
|
|
101
|
+
// },
|
|
102
|
+
// instance2: {
|
|
103
|
+
// host: 'host',
|
|
104
|
+
// port: 'port',
|
|
105
|
+
// family: 'user',
|
|
106
|
+
// password: 'password',
|
|
107
|
+
// db: 'db',
|
|
108
|
+
// },
|
|
109
|
+
// },
|
|
110
|
+
} as RedisConfig,
|
|
111
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
package/src/lib/redis.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { once } from 'node:events';
|
|
3
|
+
import { Redis } from 'ioredis';
|
|
4
|
+
import type { ILifecycleBoot, EggCore } from '@eggjs/core';
|
|
5
|
+
import type { RedisClusterOptions, RedisClientOptions } from '../config/config.default.js';
|
|
6
|
+
|
|
7
|
+
export class RedisBoot implements ILifecycleBoot {
|
|
8
|
+
constructor(private readonly app: EggCore) {
|
|
9
|
+
// empty
|
|
10
|
+
}
|
|
11
|
+
async didLoad() {
|
|
12
|
+
const app = this.app;
|
|
13
|
+
if (app.type === 'application' && app.config.redis.app) {
|
|
14
|
+
app.addSingleton('redis', createClient);
|
|
15
|
+
} else if (app.type === 'agent' && app.config.redis.agent) {
|
|
16
|
+
app.addSingleton('redis', createClient);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let count = 0;
|
|
22
|
+
function createClient(options: RedisClusterOptions | RedisClientOptions, app: EggCore) {
|
|
23
|
+
const RedisClass: typeof Redis = app.config.redis.Redis ?? Redis;
|
|
24
|
+
let client;
|
|
25
|
+
|
|
26
|
+
if ('cluster' in options && options.cluster === true) {
|
|
27
|
+
const config = options as RedisClusterOptions;
|
|
28
|
+
assert(config.nodes && config.nodes.length !== 0, '[@eggjs/redis] cluster nodes configuration is required when use cluster redis');
|
|
29
|
+
|
|
30
|
+
config.nodes.forEach(client => {
|
|
31
|
+
assert(client.host && client.port, `[@eggjs/redis] 'host: ${client.host}', 'port: ${client.port}' are required on config`);
|
|
32
|
+
});
|
|
33
|
+
app.coreLogger.info('[@eggjs/redis] cluster connecting');
|
|
34
|
+
client = new RedisClass.Cluster(config.nodes, config as any);
|
|
35
|
+
} else if ('sentinels' in options && options.sentinels) {
|
|
36
|
+
const config = options as RedisClientOptions;
|
|
37
|
+
assert(config.sentinels && config.sentinels.length !== 0, '[@eggjs/redis] sentinels configuration is required when use redis sentinel');
|
|
38
|
+
|
|
39
|
+
config.sentinels.forEach(sentinel => {
|
|
40
|
+
assert(sentinel.host && sentinel.port,
|
|
41
|
+
`[@eggjs/redis] 'host: ${sentinel.host}', 'port: ${sentinel.port}' are required on config`);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const mask = config.password ? '***' : config.password;
|
|
45
|
+
assert(config.name && config.password !== undefined && config.db !== undefined,
|
|
46
|
+
`[@eggjs/redis] 'name of master: ${config.name}', 'password: ${mask}', 'db: ${config.db}' are required on config`);
|
|
47
|
+
|
|
48
|
+
app.coreLogger.info('[@eggjs/redis] sentinel connecting start');
|
|
49
|
+
client = new RedisClass(config as any);
|
|
50
|
+
} else {
|
|
51
|
+
const config = options as RedisClientOptions;
|
|
52
|
+
const mask = config.password ? '***' : config.password;
|
|
53
|
+
assert((config.host && config.port && config.password !== undefined && config.db !== undefined) || config.path,
|
|
54
|
+
`[@eggjs/redis] 'host: ${config.host}', 'port: ${config.port}', 'password: ${mask}', 'db: ${config.db}' or 'path:${config.path}' are required on config`);
|
|
55
|
+
if (config.host) {
|
|
56
|
+
app.coreLogger.info('[@eggjs/redis] server connecting redis://:***@%s:%s/%s',
|
|
57
|
+
config.host, config.port, config.db);
|
|
58
|
+
} else {
|
|
59
|
+
app.coreLogger.info('[@eggjs/redis] server connecting %s',
|
|
60
|
+
config.path || config);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
client = new RedisClass(config as any);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
client.on('connect', () => {
|
|
67
|
+
app.coreLogger.info('[@eggjs/redis] client connect success');
|
|
68
|
+
});
|
|
69
|
+
client.on('error', err => {
|
|
70
|
+
app.coreLogger.error('[@eggjs/redis] client error: %s', err);
|
|
71
|
+
app.coreLogger.error(err);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const index = count++;
|
|
75
|
+
app.lifecycle.registerBeforeStart(async () => {
|
|
76
|
+
if ('weakDependent' in options && options.weakDependent) {
|
|
77
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] is weak dependent and won't block app start`);
|
|
78
|
+
client.once('ready', () => {
|
|
79
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK`);
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await Promise.race([
|
|
85
|
+
once(client, 'ready'),
|
|
86
|
+
once(client, 'error'),
|
|
87
|
+
]);
|
|
88
|
+
app.coreLogger.info(`[@eggjs/redis] instance[${index}] status OK, client ready`);
|
|
89
|
+
}, `[@eggjs/redis] instance[${index}] start check`);
|
|
90
|
+
|
|
91
|
+
return client;
|
|
92
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Singleton } from '@eggjs/core';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
3
|
+
import type { RedisConfig } from './config/config.default.js';
|
|
4
|
+
|
|
5
|
+
declare module '@eggjs/core' {
|
|
6
|
+
// add EggAppConfig overrides types
|
|
7
|
+
interface EggAppConfig {
|
|
8
|
+
redis: RedisConfig;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface EggCore {
|
|
12
|
+
redis: Redis & Singleton<Redis>;
|
|
13
|
+
}
|
|
14
|
+
}
|