Skip to content

Commit c68a47c

Browse files
feat: remove direct redis dependency
BREAKING CHANGE: the library will no longer create Redis clients on behalf of the user. Before: ```js io.adapter(redisAdapter({ host: "localhost", port: 6379 })); ``` After: ```js const pubClient = createClient({ host: "localhost", port: 6379 }); const subClient = pubClient.duplicate(); io.adapter(redisAdapter(pubClient, subClient)); ``` Related: - #314 - #374
1 parent 3cac178 commit c68a47c

File tree

5 files changed

+88
-120
lines changed

5 files changed

+88
-120
lines changed

README.md

+26-61
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,41 @@
3030

3131
## How to use
3232

33+
Installation:
34+
35+
```
36+
$ npm install @socket.io/redis-adapter redis
37+
```
38+
3339
### CommonJS
3440

3541
```js
3642
const io = require('socket.io')(3000);
43+
const { createClient } = require('redis');
3744
const redisAdapter = require('@socket.io/redis-adapter');
38-
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
45+
46+
const pubClient = createClient({ host: 'localhost', port: 6379 });
47+
const subClient = pubClient.duplicate();
48+
io.adapter(redisAdapter(pubClient, subClient));
3949
```
4050

4151
### ES6 modules
4252

4353
```js
4454
import { Server } from 'socket.io';
55+
import { createClient } from 'redis';
4556
import redisAdapter from '@socket.io/redis-adapter';
4657

4758
const io = new Server(3000);
48-
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
59+
const pubClient = createClient({ host: 'localhost', port: 6379 });
60+
const subClient = pubClient.duplicate();
61+
io.adapter(redisAdapter(pubClient, subClient));
4962
```
5063

5164
### TypeScript
5265

5366
```ts
54-
// npm i -D @types/redis
67+
// npm i -D redis @types/redis
5568
import { Server } from 'socket.io';
5669
import { createAdapter } from '@socket.io/redis-adapter';
5770
import { RedisClient } from 'redis';
@@ -60,7 +73,7 @@ const io = new Server(8080);
6073
const pubClient = new RedisClient({ host: 'localhost', port: 6379 });
6174
const subClient = pubClient.duplicate();
6275

63-
io.adapter(createAdapter({ pubClient, subClient }));
76+
io.adapter(createAdapter(pubClient, subClient));
6477
```
6578

6679
By running Socket.IO with the `@socket.io/redis-adapter` adapter you can run
@@ -150,26 +163,13 @@ The request and response channels are used in the additional methods exposed by
150163

151164
## API
152165

153-
### adapter(uri[, opts])
154-
155-
`uri` is a string like `localhost:6379` where your redis server
156-
is located. For a list of options see below.
157-
158-
### adapter(opts)
166+
### adapter(pubClient, subClient[, opts])
159167

160168
The following options are allowed:
161169

162170
- `key`: the name of the key to pub/sub events on as prefix (`socket.io`)
163-
- `host`: host to connect to redis on (`localhost`)
164-
- `port`: port to connect to redis on (`6379`)
165-
- `pubClient`: optional, the redis client to publish events on
166-
- `subClient`: optional, the redis client to subscribe to events on
167171
- `requestsTimeout`: optional, after this timeout the adapter will stop waiting from responses to request (`5000ms`)
168172

169-
If you decide to supply `pubClient` and `subClient`, make sure you use
170-
[node_redis](https://github.com/mranney/node_redis) as a client or one
171-
with an equivalent API.
172-
173173
### RedisAdapter
174174

175175
The redis adapter instances expose the following properties
@@ -242,41 +242,6 @@ try {
242242
}
243243
```
244244

245-
## Client error handling
246-
247-
Access the `pubClient` and `subClient` properties of the
248-
Redis Adapter instance to subscribe to its `error` event:
249-
250-
```js
251-
const adapter = require('@socket.io/redis-adapter')('localhost:6379');
252-
adapter.pubClient.on('error', function(){});
253-
adapter.subClient.on('error', function(){});
254-
```
255-
256-
The errors emitted from `pubClient` and `subClient` will
257-
also be forwarded to the adapter instance:
258-
259-
```js
260-
const io = require('socket.io')(3000);
261-
const redisAdapter = require('@socket.io/redis-adapter');
262-
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
263-
io.of('/').adapter.on('error', function(){});
264-
```
265-
266-
## Custom client (eg: with authentication)
267-
268-
If you need to create a redisAdapter to a redis instance
269-
that has a password, use pub/sub options instead of passing
270-
a connection string.
271-
272-
```js
273-
const redis = require('redis');
274-
const redisAdapter = require('@socket.io/redis-adapter');
275-
const pubClient = redis.createClient(port, host, { auth_pass: "pwd" });
276-
const subClient = pubClient.duplicate();
277-
io.adapter(redisAdapter({ pubClient, subClient }));
278-
```
279-
280245
## With ioredis client
281246

282247
### Cluster example
@@ -297,10 +262,10 @@ const startupNodes = [
297262
}
298263
];
299264

300-
io.adapter(redisAdapter({
301-
pubClient: new Redis.Cluster(startupNodes),
302-
subClient: new Redis.Cluster(startupNodes)
303-
}));
265+
const pubClient = new Redis.Cluster(startupNodes);
266+
const subClient = pubClient.duplicate();
267+
268+
io.adapter(redisAdapter(pubClient, subClient));
304269
```
305270

306271
### Sentinel Example
@@ -318,10 +283,10 @@ const options = {
318283
name: 'master01'
319284
};
320285

321-
io.adapter(redisAdapter({
322-
pubClient: new Redis(options),
323-
subClient: new Redis(options)
324-
}));
286+
const pubClient = new Redis(options);
287+
const subClient = pubClient.duplicate();
288+
289+
io.adapter(redisAdapter(pubClient, subClient));
325290
```
326291

327292
## Protocol

lib/index.ts

+17-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import uid2 = require("uid2");
2-
import { createClient } from "redis";
32
import msgpack = require("notepack.io");
43
import { Adapter, BroadcastOptions, Room, SocketId } from "socket.io-adapter";
54

@@ -35,60 +34,34 @@ export interface RedisAdapterOptions {
3534
* @default socket.io
3635
*/
3736
key: string;
38-
/**
39-
* the redis client to publish events on
40-
*/
41-
pubClient: any;
42-
/**
43-
* the redis client to subscribe to events on
44-
*/
45-
subClient: any;
4637
/**
4738
* after this timeout the adapter will stop waiting from responses to request
4839
* @default 5000
4940
*/
5041
requestsTimeout: number;
5142
}
5243

53-
function createRedisClient(uri, opts) {
54-
if (uri) {
55-
// handle uri string
56-
return createClient(uri, opts);
57-
} else {
58-
return createClient(opts);
59-
}
60-
}
61-
6244
/**
63-
* Returns a redis Adapter class.
45+
* Returns a function that will create a RedisAdapter instance.
6446
*
65-
* @param {String} uri - optional, redis uri
66-
* @param {String} opts - redis connection options
67-
* @return {RedisAdapter} adapter
47+
* @param pubClient - a Redis client that will be used to publish messages
48+
* @param subClient - a Redis client that will be used to receive messages (put in subscribed state)
49+
* @param opts - additional options
6850
*
6951
* @public
7052
*/
71-
export function createAdapter(uri: string, opts?: Partial<RedisAdapterOptions>);
72-
export function createAdapter(opts: Partial<RedisAdapterOptions>);
7353
export function createAdapter(
74-
uri?: any,
75-
opts: Partial<RedisAdapterOptions> = {}
54+
pubClient: any,
55+
subClient: any,
56+
opts?: Partial<RedisAdapterOptions>
7657
) {
77-
// handle options only
78-
if (typeof uri === "object") {
79-
opts = uri;
80-
uri = null;
81-
}
82-
8358
return function (nsp) {
84-
return new RedisAdapter(nsp, uri, opts);
59+
return new RedisAdapter(nsp, pubClient, subClient, opts);
8560
};
8661
}
8762

8863
export class RedisAdapter extends Adapter {
8964
public readonly uid;
90-
public readonly pubClient: any;
91-
public readonly subClient: any;
9265
public readonly requestsTimeout: number;
9366

9467
private readonly channel: string;
@@ -100,17 +73,21 @@ export class RedisAdapter extends Adapter {
10073
* Adapter constructor.
10174
*
10275
* @param nsp - the namespace
103-
* @param uri - the url of the Redis server
104-
* @param opts - the options for both the Redis adapter and the Redis client
76+
* @param pubClient - a Redis client that will be used to publish messages
77+
* @param subClient - a Redis client that will be used to receive messages (put in subscribed state)
78+
* @param opts - additional options
10579
*
10680
* @public
10781
*/
108-
constructor(nsp, uri: string, opts: Partial<RedisAdapterOptions> = {}) {
82+
constructor(
83+
nsp: any,
84+
readonly pubClient: any,
85+
readonly subClient: any,
86+
opts: Partial<RedisAdapterOptions> = {}
87+
) {
10988
super(nsp);
11089

11190
this.uid = uid2(6);
112-
this.pubClient = opts.pubClient || createRedisClient(uri, opts);
113-
this.subClient = opts.subClient || createRedisClient(uri, opts);
11491
this.requestsTimeout = opts.requestsTimeout || 5000;
11592

11693
const prefix = opts.key || "socket.io";

package-lock.json

+36-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,20 @@
2121
"dependencies": {
2222
"debug": "~4.3.1",
2323
"notepack.io": "~2.2.0",
24-
"redis": "^3.0.0",
2524
"socket.io-adapter": "^2.2.0",
2625
"uid2": "0.0.3"
2726
},
2827
"devDependencies": {
2928
"@types/expect.js": "^0.3.29",
3029
"@types/mocha": "^8.2.1",
3130
"@types/node": "^14.14.7",
31+
"@types/redis": "^2.8.28",
3232
"expect.js": "0.3.1",
3333
"ioredis": "^4.0.0",
3434
"mocha": "^3.4.2",
3535
"nyc": "^15.1.0",
3636
"prettier": "^2.1.2",
37+
"redis": "^3.1.2",
3738
"socket.io": "^4.0.0",
3839
"socket.io-client": "^4.0.0",
3940
"ts-node": "^9.1.1",

0 commit comments

Comments
 (0)