New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@socket.io/redis-adapter

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@socket.io/redis-adapter - npm Package Compare versions

Comparing version 8.2.1 to 8.3.0

15

dist/sharded-adapter.d.ts

@@ -1,2 +0,2 @@

import { ClusterAdapter } from "./cluster-adapter";
import { ClusterAdapter, ClusterMessage, ClusterResponse, Offset } from "socket.io-adapter";
export interface ShardedRedisAdapterOptions {

@@ -21,9 +21,13 @@ /**

* Only public rooms (i.e. not related to a particular Socket ID) are taken in account, because:
*
* - a lot of connected clients would mean a lot of subscription/unsubscription
* - the Socket ID attribute is ephemeral
*
* - "dynamic-private"
*
* Like "dynamic" but creates separate channels for private rooms as well. Useful when there is lots of 1:1 communication
* via socket.emit() calls.
*
* @default "dynamic"
*/
subscriptionMode?: "static" | "dynamic";
subscriptionMode?: "static" | "dynamic" | "dynamic-private";
}

@@ -48,10 +52,11 @@ /**

close(): Promise<void> | void;
publishMessage(message: any): Promise<string>;
doPublish(message: ClusterMessage): Promise<Offset>;
private computeChannel;
private dynamicChannel;
publishResponse(requesterUid: any, response: any): void;
doPublishResponse(requesterUid: string, response: ClusterResponse): Promise<void>;
private encode;
private onRawMessage;
serverCount(): Promise<number>;
private shouldUseASeparateNamespace;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createShardedAdapter = void 0;
const cluster_adapter_1 = require("./cluster-adapter");
const socket_io_adapter_1 = require("socket.io-adapter");
const notepack_io_1 = require("notepack.io");

@@ -9,2 +9,5 @@ const util_1 = require("./util");

const debug = (0, debug_1.default)("socket.io-redis");
function looksLikeASocketId(room) {
return typeof room === "string" && room.length === 20;
}
/**

@@ -25,3 +28,3 @@ * Create a new Adapter based on Redis sharded Pub/Sub introduced in Redis 7.0.

exports.createShardedAdapter = createShardedAdapter;
class ShardedRedisAdapter extends cluster_adapter_1.ClusterAdapter {
class ShardedRedisAdapter extends socket_io_adapter_1.ClusterAdapter {
constructor(nsp, pubClient, subClient, opts) {

@@ -40,6 +43,6 @@ super(nsp);

(0, util_1.SSUBSCRIBE)(this.subClient, this.responseChannel, handler);
if (this.opts.subscriptionMode === "dynamic") {
if (this.opts.subscriptionMode === "dynamic" ||
this.opts.subscriptionMode === "dynamic-private") {
this.on("create-room", (room) => {
const isPublicRoom = !this.sids.has(room);
if (isPublicRoom) {
if (this.shouldUseASeparateNamespace(room)) {
(0, util_1.SSUBSCRIBE)(this.subClient, this.dynamicChannel(room), handler);

@@ -49,4 +52,3 @@ }

this.on("delete-room", (room) => {
const isPublicRoom = !this.sids.has(room);
if (isPublicRoom) {
if (this.shouldUseASeparateNamespace(room)) {
(0, util_1.SUNSUBSCRIBE)(this.subClient, this.dynamicChannel(room));

@@ -59,6 +61,6 @@ }

const channels = [this.channel, this.responseChannel];
if (this.opts.subscriptionMode === "dynamic") {
if (this.opts.subscriptionMode === "dynamic" ||
this.opts.subscriptionMode === "dynamic-private") {
this.rooms.forEach((_sids, room) => {
const isPublicRoom = !this.sids.has(room);
if (isPublicRoom) {
if (this.shouldUseASeparateNamespace(room)) {
channels.push(this.dynamicChannel(room));

@@ -70,7 +72,6 @@ }

}
publishMessage(message) {
doPublish(message) {
const channel = this.computeChannel(message);
debug("publishing message of type %s to %s", message.type, channel);
(0, util_1.SPUBLISH)(this.pubClient, channel, this.encode(message));
return Promise.resolve("");
return (0, util_1.SPUBLISH)(this.pubClient, channel, this.encode(message)).then(() => "");
}

@@ -80,6 +81,8 @@ computeChannel(message) {

// servers, not only the ones where the given room exists
const useDynamicChannel = this.opts.subscriptionMode === "dynamic" &&
message.type === cluster_adapter_1.MessageType.BROADCAST &&
const useDynamicChannel = message.type === socket_io_adapter_1.MessageType.BROADCAST &&
message.data.requestId === undefined &&
message.data.opts.rooms.length === 1;
message.data.opts.rooms.length === 1 &&
((this.opts.subscriptionMode === "dynamic" &&
!looksLikeASocketId(message.data.opts.rooms[0])) ||
this.opts.subscriptionMode === "dynamic-private");
if (useDynamicChannel) {

@@ -95,14 +98,15 @@ return this.dynamicChannel(message.data.opts.rooms[0]);

}
publishResponse(requesterUid, response) {
doPublishResponse(requesterUid, response) {
debug("publishing response of type %s to %s", response.type, requesterUid);
(0, util_1.SPUBLISH)(this.pubClient, `${this.channel}${requesterUid}#`, this.encode(response));
return (0, util_1.SPUBLISH)(this.pubClient, `${this.channel}${requesterUid}#`, this.encode(response)).then();
}
encode(message) {
const mayContainBinary = [
cluster_adapter_1.MessageType.BROADCAST,
cluster_adapter_1.MessageType.BROADCAST_ACK,
cluster_adapter_1.MessageType.FETCH_SOCKETS_RESPONSE,
cluster_adapter_1.MessageType.SERVER_SIDE_EMIT,
cluster_adapter_1.MessageType.SERVER_SIDE_EMIT_RESPONSE,
socket_io_adapter_1.MessageType.BROADCAST,
socket_io_adapter_1.MessageType.BROADCAST_ACK,
socket_io_adapter_1.MessageType.FETCH_SOCKETS_RESPONSE,
socket_io_adapter_1.MessageType.SERVER_SIDE_EMIT,
socket_io_adapter_1.MessageType.SERVER_SIDE_EMIT_RESPONSE,
].includes(message.type);
// @ts-ignore
if (mayContainBinary && (0, util_1.hasBinary)(message.data)) {

@@ -138,2 +142,7 @@ return (0, notepack_io_1.encode)(message);

}
shouldUseASeparateNamespace(room) {
const isPublicRoom = !this.sids.has(room);
return ((this.opts.subscriptionMode === "dynamic" && isPublicRoom) ||
this.opts.subscriptionMode === "dynamic-private");
}
}
/// <reference types="node" />
export declare function hasBinary(obj: any, toJSON?: boolean): boolean;
export declare function randomId(): string;
export declare function parseNumSubResponse(res: any): number;

@@ -8,3 +7,6 @@ export declare function sumValues(values: any): any;

export declare function SUNSUBSCRIBE(redisClient: any, channel: string | string[]): void;
export declare function SPUBLISH(redisClient: any, channel: string, payload: string | Uint8Array): void;
/**
* @see https://redis.io/commands/spublish/
*/
export declare function SPUBLISH(redisClient: any, channel: string, payload: string | Uint8Array): any;
export declare function PUBSUB(redisClient: any, arg: string, channel: string): any;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PUBSUB = exports.SPUBLISH = exports.SUNSUBSCRIBE = exports.SSUBSCRIBE = exports.sumValues = exports.parseNumSubResponse = exports.randomId = exports.hasBinary = void 0;
const crypto_1 = require("crypto");
exports.PUBSUB = exports.SPUBLISH = exports.SUNSUBSCRIBE = exports.SSUBSCRIBE = exports.sumValues = exports.parseNumSubResponse = exports.hasBinary = void 0;
function hasBinary(obj, toJSON) {

@@ -31,6 +30,2 @@ if (!obj || typeof obj !== "object") {

exports.hasBinary = hasBinary;
function randomId() {
return (0, crypto_1.randomBytes)(8).toString("hex");
}
exports.randomId = randomId;
function parseNumSubResponse(res) {

@@ -57,2 +52,3 @@ return parseInt(res[1], 10);

}
const kHandlers = Symbol("handlers");
function SSUBSCRIBE(redisClient, channel, handler) {

@@ -63,8 +59,11 @@ if (isRedisV4Client(redisClient)) {

else {
if (!redisClient[kHandlers]) {
redisClient[kHandlers] = new Map();
redisClient.on("smessageBuffer", (rawChannel, message) => {
var _a;
(_a = redisClient[kHandlers].get(rawChannel.toString())) === null || _a === void 0 ? void 0 : _a(message, rawChannel);
});
}
redisClient[kHandlers].set(channel, handler);
redisClient.ssubscribe(channel);
redisClient.on("smessageBuffer", (rawChannel, message) => {
if (rawChannel.toString() === channel) {
handler(message, rawChannel);
}
});
}

@@ -79,11 +78,20 @@ }

redisClient.sunsubscribe(channel);
if (Array.isArray(channel)) {
channel.forEach((c) => redisClient[kHandlers].delete(c));
}
else {
redisClient[kHandlers].delete(channel);
}
}
}
exports.SUNSUBSCRIBE = SUNSUBSCRIBE;
/**
* @see https://redis.io/commands/spublish/
*/
function SPUBLISH(redisClient, channel, payload) {
if (isRedisV4Client(redisClient)) {
redisClient.sPublish(channel, payload);
return redisClient.sPublish(channel, payload);
}
else {
redisClient.spublish(channel, payload);
return redisClient.spublish(channel, payload);
}

@@ -90,0 +98,0 @@ }

{
"name": "@socket.io/redis-adapter",
"version": "8.2.1",
"version": "8.3.0",
"description": "The Socket.IO Redis adapter, allowing to broadcast events between several Socket.IO servers",

@@ -16,6 +16,7 @@ "license": "MIT",

"scripts": {
"compile": "rimraf ./dist && tsc",
"test": "npm run format:check && tsc && nyc mocha --bail --require ts-node/register test/test-runner.ts",
"format:check": "prettier --parser typescript --check 'lib/**/*.ts' 'test/**/*.ts'",
"format:fix": "prettier --parser typescript --write 'lib/**/*.ts' 'test/**/*.ts'",
"prepack": "tsc"
"prepack": "npm run compile"
},

@@ -28,3 +29,3 @@ "dependencies": {

"peerDependencies": {
"socket.io-adapter": "^2.4.0"
"socket.io-adapter": "^2.5.4"
},

@@ -42,2 +43,3 @@ "devDependencies": {

"redis-v3": "npm:redis@^3.1.2",
"rimraf": "^5.0.5",
"socket.io": "^4.6.1",

@@ -44,0 +46,0 @@ "socket.io-client": "^4.1.1",

@@ -1,127 +0,161 @@

# socket.io-redis
# Socket.IO Redis adapter
[![Build Status](https://github.com/socketio/socket.io-redis/workflows/CI/badge.svg?branch=main)](https://github.com/socketio/socket.io-redis/actions)
[![npm version](https://badge.fury.io/js/%40socket.io%2Fredis-adapter.svg)](https://badge.fury.io/js/%40socket.io%2Fredis-adapter)
The `@socket.io/redis-adapter` package allows broadcasting packets between multiple Socket.IO servers.
## Table of contents
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/adapter_dark.png">
<img alt="Diagram of Socket.IO packets forwarded through Redis" src="./assets/adapter.png">
</picture>
- [How to use](#how-to-use)
- [CommonJS](#commonjs)
- [ES6 module](#es6-modules)
- [TypeScript](#typescript)
- [Sharded Redis Pub/Sub](#sharded-redis-pubsub)
**Table of contents**
- [Supported features](#supported-features)
- [Installation](#installation)
- [Compatibility table](#compatibility-table)
- [How does it work under the hood?](#how-does-it-work-under-the-hood)
- [API](#api)
- [adapter(pubClient, subClient[, opts])](#adapterpubclient-subclient-opts)
- [RedisAdapter](#redisadapter)
- [RedisAdapter#allRooms()](#redisadapterallrooms)
- [With ioredis client](#with-ioredis-client)
- [Cluster example](#cluster-example)
- [Sentinel Example](#sentinel-example)
- [Protocol](#protocol)
- [Migrating from `socket.io-redis`](#migrating-from-socketio-redis)
- [Usage](#usage)
- [With the `redis` package](#with-the-redis-package)
- [With the `redis` package and a Redis cluster](#with-the-redis-package-and-a-redis-cluster)
- [With the `ioredis` package](#with-the-ioredis-package)
- [With the `ioredis` package and a Redis cluster](#with-the-ioredis-package-and-a-redis-cluster)
- [With Redis sharded Pub/Sub](#with-redis-sharded-pubsub)
- [Options](#options)
- [Default adapter](#default-adapter)
- [Sharded adapter](#sharded-adapter)
- [License](#license)
## How to use
## Supported features
Installation:
| Feature | `socket.io` version | Support |
|---------------------------------|---------------------|------------------------------------------------|
| Socket management | `4.0.0` | :white_check_mark: YES (since version `6.1.0`) |
| Inter-server communication | `4.1.0` | :white_check_mark: YES (since version `7.0.0`) |
| Broadcast with acknowledgements | `4.5.0` | :white_check_mark: YES (since version `7.2.0`) |
| Connection state recovery | `4.6.0` | :x: NO |
## Installation
```
$ npm install @socket.io/redis-adapter redis
npm install @socket.io/redis-adapter
```
### CommonJS
## Compatibility table
| Redis Adapter version | Socket.IO server version |
|-----------------------|--------------------------|
| 4.x | 1.x |
| 5.x | 2.x |
| 6.0.x | 3.x |
| 6.1.x | 4.x |
| 7.x and above | 4.3.1 and above |
## Usage
### With the `redis` package
```js
const { Server } = require('socket.io');
const { createClient } = require('redis');
const { createAdapter } = require('@socket.io/redis-adapter');
import { createClient } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const io = new Server();
const pubClient = createClient({ host: 'localhost', port: 6379 });
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
io.listen(3000);
await Promise.all([
pubClient.connect(),
subClient.connect()
]);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
```
With `redis@3`, calling `connect()` on the Redis clients is not needed:
### With the `redis` package and a Redis cluster
```js
const { Server } = require('socket.io');
const { createClient } = require('redis');
const { createAdapter } = require('@socket.io/redis-adapter');
import { createCluster } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const io = new Server();
const pubClient = createClient({ host: 'localhost', port: 6379 });
const pubClient = createCluster({
rootNodes: [
{
url: "redis://localhost:7000",
},
{
url: "redis://localhost:7001",
},
{
url: "redis://localhost:7002",
},
],
});
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
await Promise.all([
pubClient.connect(),
subClient.connect()
]);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
```
### ES6 modules
### With the `ioredis` package
```js
import { Server } from 'socket.io';
import { createClient } from 'redis';
import { createAdapter } from '@socket.io/redis-adapter';
import { Redis } from "ioredis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const io = new Server();
const pubClient = createClient({ host: 'localhost', port: 6379 });
const pubClient = new Redis();
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
io.listen(3000);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
```
### TypeScript
### With the `ioredis` package and a Redis cluster
```ts
import { Server } from 'socket.io';
import { createClient } from 'redis';
import { createAdapter } from '@socket.io/redis-adapter';
```js
import { Cluster } from "ioredis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const io = new Server();
const pubClient = createClient({ host: 'localhost', port: 6379 });
const pubClient = new Cluster([
{
host: "localhost",
port: 7000,
},
{
host: "localhost",
port: 7001,
},
{
host: "localhost",
port: 7002,
},
]);
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
io.listen(3000);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
```
By running Socket.IO with the `@socket.io/redis-adapter` adapter you can run
multiple Socket.IO instances in different processes or servers that can
all broadcast and emit events to and from each other.
So any of the following commands:
```js
io.emit('hello', 'to all clients');
io.to('room42').emit('hello', "to all clients in 'room42' room");
io.on('connection', (socket) => {
socket.broadcast.emit('hello', 'to all clients except sender');
socket.to('room42').emit('hello', "to all clients in 'room42' room except sender");
});
io.listen(3000);
```
will properly be broadcast to the clients through the Redis [Pub/Sub mechanism](https://redis.io/topics/pubsub).
### With Redis sharded Pub/Sub
If you need to emit events to socket.io instances from a non-socket.io
process, you should use [socket.io-emitter](https://github.com/socketio/socket.io-emitter).
### Sharded Redis Pub/Sub
Sharded Pub/Sub was introduced in Redis 7.0 in order to help scaling the usage of Pub/Sub in cluster mode.
Reference: https://redis.io/docs/manual/pubsub/#sharded-pubsub
Reference: https://redis.io/docs/interact/pubsub/#sharded-pubsub

@@ -131,7 +165,7 @@ A dedicated adapter can be created with the `createShardedAdapter()` method:

```js
import { Server } from 'socket.io';
import { createClient } from 'redis';
import { createShardedAdapter } from '@socket.io/redis-adapter';
import { Server } from "socket.io";
import { createClient } from "redis";
import { createShardedAdapter } from "@socket.io/redis-adapter";
const pubClient = createClient({ host: 'localhost', port: 6379 });
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();

@@ -156,198 +190,24 @@

Note: it is not currently possible to use the sharded adapter with the `ioredis` package and a Redis cluster ([reference](https://github.com/luin/ioredis/issues/1759)).
## Compatibility table
## Options
| Redis Adapter version | Socket.IO server version |
|-----------------------| ------------------------ |
| 4.x | 1.x |
| 5.x | 2.x |
| 6.0.x | 3.x |
| 6.1.x and above | 4.x |
### Default adapter
## How does it work under the hood?
| Name | Description | Default value |
|------------------------------------|-------------------------------------------------------------------------------|---------------|
| `key` | The prefix for the Redis Pub/Sub channels. | `socket.io` |
| `requestsTimeout` | After this timeout the adapter will stop waiting from responses to request. | `5_000` |
| `publishOnSpecificResponseChannel` | Whether to publish a response to the channel specific to the requesting node. | `false` |
| `parser` | The parser to use for encoding and decoding messages sent to Redis. | `-` |
This adapter extends the [in-memory adapter](https://github.com/socketio/socket.io-adapter/) that is included by default with the Socket.IO server.
### Sharded adapter
The in-memory adapter stores the relationships between Sockets and Rooms in two Maps.
| Name | Description | Default value |
|--------------------|-----------------------------------------------------------------------------------------|---------------|
| `channelPrefix` | The prefix for the Redis Pub/Sub channels. | `socket.io` |
| `subscriptionMode` | The subscription mode impacts the number of Redis Pub/Sub channels used by the adapter. | `dynamic` |
When you run `socket.join("room21")`, here's what happens:
```
console.log(adapter.rooms); // Map { "room21" => Set { "mdpk4kxF5CmhwfCdAHD8" } }
console.log(adapter.sids); // Map { "mdpk4kxF5CmhwfCdAHD8" => Set { "mdpk4kxF5CmhwfCdAHD8", "room21" } }
// "mdpk4kxF5CmhwfCdAHD8" being the ID of the given socket
```
Those two Maps are then used when broadcasting:
- a broadcast to all sockets (`io.emit()`) loops through the `sids` Map, and send the packet to all sockets
- a broadcast to a given room (`io.to("room21").emit()`) loops through the Set in the `rooms` Map, and sends the packet to all matching sockets
The Redis adapter extends the broadcast function of the in-memory adapter: the packet is also [published](https://redis.io/topics/pubsub) to a Redis channel (see [below](#protocol) for the format of the channel name).
Each Socket.IO server receives this packet and broadcasts it to its own list of connected sockets.
To check what's happening on your Redis instance:
```
$ redis-cli
127.0.0.1:6379> PSUBSCRIBE *
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*"
3) (integer) 1
1) "pmessage"
2) "*"
3) "socket.io#/#" (a broadcast to all sockets or to a list of rooms)
4) <the packet content>
1) "pmessage"
2) "*"
3) "socket.io#/#room21#" (a broadcast to a single room)
4) <the packet content>
```
Note: **no data** is stored in Redis itself
There are 3 Redis subscriptions per namespace:
- main channel: `<prefix>#<namespace>#*` (glob)
- request channel: `<prefix>-request#<namespace>#`
- response channel: `<prefix>-response#<namespace>#`
The request and response channels are used in the additional methods exposed by the Redis adapter, like [RedisAdapter#allRooms()](#redisadapterallrooms).
## API
### adapter(pubClient, subClient[, opts])
The following options are allowed:
- `key`: the name of the key to pub/sub events on as prefix (`socket.io`)
- `requestsTimeout`: optional, after this timeout the adapter will stop waiting from responses to request (`5000ms`)
- `parser`: optional, parser to use for encoding and decoding messages passed through Redis ([`notepack.io`](https://www.npmjs.com/package/notepack.io))
### RedisAdapter
The redis adapter instances expose the following properties
that a regular `Adapter` does not
- `uid`
- `prefix`
- `pubClient`
- `subClient`
- `requestsTimeout`
- `parser`
### RedisAdapter#allRooms()
Returns the list of all rooms.
```js
const rooms = await io.of('/').adapter.allRooms();
console.log(rooms); // a Set containing all rooms (across every node)
```
## With ioredis client
### Cluster example
```js
const io = require('socket.io')(3000);
const redisAdapter = require('@socket.io/redis-adapter');
const Redis = require('ioredis');
const startupNodes = [
{
port: 6380,
host: '127.0.0.1'
},
{
port: 6381,
host: '127.0.0.1'
}
];
const pubClient = new Redis.Cluster(startupNodes);
const subClient = pubClient.duplicate();
io.adapter(redisAdapter(pubClient, subClient));
```
### Sentinel Example
```js
const io = require('socket.io')(3000);
const redisAdapter = require('@socket.io/redis-adapter');
const Redis = require('ioredis');
const options = {
sentinels: [
{ host: 'somehost1', port: 26379 },
{ host: 'somehost2', port: 26379 }
],
name: 'master01'
};
const pubClient = new Redis(options);
const subClient = pubClient.duplicate();
io.adapter(redisAdapter(pubClient, subClient));
```
## Protocol
The `@socket.io/redis-adapter` adapter broadcasts and receives messages on particularly named Redis channels. For global broadcasts the channel name is:
```
prefix + '#' + namespace + '#'
```
In broadcasting to a single room the channel name is:
```
prefix + '#' + namespace + '#' + room + '#'
```
- `prefix`: The base channel name. Default value is `socket.io`. Changed by setting `opts.key` in `adapter(opts)` constructor
- `namespace`: See https://github.com/socketio/socket.io#namespace.
- `room` : Used if targeting a specific room.
A number of other libraries adopt this protocol including:
- [socket.io-redis-emitter](https://github.com/socketio/socket.io-redis-emitter)
- [socket.io-python-emitter](https://github.com/GameXG/socket.io-python-emitter)
- [socket.io-emitter-go](https://github.com/stackcats/socket.io-emitter-go)
## Migrating from `socket.io-redis`
The package was renamed from `socket.io-redis` to `@socket.io/redis-adapter` in [v7](https://github.com/socketio/socket.io-redis-adapter/releases/tag/7.0.0), in order to match the name of the Redis emitter (`@socket.io/redis-emitter`).
To migrate to the new package, you'll need to make sure to provide your own Redis clients, as the package will no longer create Redis clients on behalf of the user.
Before:
```js
const redisAdapter = require("socket.io-redis");
io.adapter(redisAdapter({ host: "localhost", port: 6379 }));
```
After:
```js
const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
```
Please note that the communication protocol between the Socket.IO servers has not been updated, so you can have some servers with `socket.io-redis` and some others with `@socket.io/redis-adapter` at the same time.
## License
MIT
[MIT](LICENSE)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc