0
# Utility Functions
1
2
Cross-client compatibility utilities for Redis operations and binary data handling. These functions provide a unified interface for working with different Redis client libraries and managing message encoding.
3
4
## Capabilities
5
6
### Binary Data Detection
7
8
Utility function for detecting binary data in objects, used for message encoding decisions.
9
10
```typescript { .api }
11
/**
12
* Checks if an object contains binary data (ArrayBuffer, TypedArray, etc.)
13
* @param obj - Object to check for binary data
14
* @param toJSON - Whether to check toJSON method output (internal use)
15
* @returns True if object contains binary data
16
*/
17
function hasBinary(obj: any, toJSON?: boolean): boolean;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { hasBinary } from "@socket.io/redis-adapter";
24
25
// Check various data types
26
console.log(hasBinary("string")); // false
27
console.log(hasBinary(123)); // false
28
console.log(hasBinary({ text: "hello" })); // false
29
30
// Binary data detection
31
console.log(hasBinary(Buffer.from("hello"))); // true
32
console.log(hasBinary(new Uint8Array([1, 2, 3]))); // true
33
console.log(hasBinary(new ArrayBuffer(10))); // true
34
35
// Mixed data structures
36
console.log(hasBinary({
37
text: "hello",
38
data: Buffer.from("binary")
39
})); // true
40
41
console.log(hasBinary([
42
"string",
43
{ buffer: new Uint8Array([1, 2, 3]) }
44
])); // true
45
```
46
47
### Sharded Redis Operations
48
49
Cross-client utilities for Redis sharded pub/sub operations, providing compatibility across different Redis client versions.
50
51
```typescript { .api }
52
/**
53
* Subscribe to a sharded Redis channel with cross-client compatibility
54
* @param redisClient - Redis client instance (redis v3, v4, or ioredis)
55
* @param channel - Channel name to subscribe to
56
* @param handler - Message handler function receiving raw message and channel
57
*/
58
function SSUBSCRIBE(
59
redisClient: any,
60
channel: string,
61
handler: (rawMessage: Buffer, channel: Buffer) => void
62
): void;
63
64
/**
65
* Unsubscribe from sharded Redis channel(s)
66
* @param redisClient - Redis client instance
67
* @param channel - Channel name or array of channel names to unsubscribe from
68
*/
69
function SUNSUBSCRIBE(redisClient: any, channel: string | string[]): void;
70
71
/**
72
* Publish message to sharded Redis channel
73
* @param redisClient - Redis client instance
74
* @param channel - Channel name to publish to
75
* @param payload - Message payload (string or binary data)
76
* @returns Promise resolving to publish result
77
*/
78
function SPUBLISH(
79
redisClient: any,
80
channel: string,
81
payload: string | Uint8Array
82
): Promise<any>;
83
```
84
85
**Usage Examples:**
86
87
```typescript
88
import { createClient } from "redis";
89
import { SSUBSCRIBE, SUNSUBSCRIBE, SPUBLISH } from "@socket.io/redis-adapter";
90
91
const client = createClient();
92
await client.connect();
93
94
// Subscribe to sharded channel
95
SSUBSCRIBE(client, "game-events", (message, channel) => {
96
console.log(`Received on ${channel}:`, message.toString());
97
});
98
99
// Publish to sharded channel
100
await SPUBLISH(client, "game-events", JSON.stringify({
101
type: "player-joined",
102
playerId: 123
103
}));
104
105
// Unsubscribe from single channel
106
SUNSUBSCRIBE(client, "game-events");
107
108
// Unsubscribe from multiple channels
109
SUNSUBSCRIBE(client, ["channel1", "channel2", "channel3"]);
110
```
111
112
### Redis Pub/Sub Information
113
114
Utility for querying Redis pub/sub information across different client types and cluster configurations.
115
116
```typescript { .api }
117
/**
118
* Execute PUBSUB commands across different Redis client types and topologies
119
* Handles standalone Redis, Redis clusters, and different client libraries
120
* @param redisClient - Redis client instance (any supported type)
121
* @param arg - PUBSUB command argument (e.g., "NUMSUB", "SHARDNUMSUB")
122
* @param channel - Channel name to query
123
* @returns Promise resolving to numeric result (subscriber count, etc.)
124
*/
125
function PUBSUB(redisClient: any, arg: string, channel: string): Promise<number>;
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
import { createClient, createCluster } from "redis";
132
import { PUBSUB } from "@socket.io/redis-adapter";
133
134
// With standalone Redis client
135
const standaloneClient = createClient();
136
await standaloneClient.connect();
137
138
// Get subscriber count for regular channel
139
const subscriberCount = await PUBSUB(standaloneClient, "NUMSUB", "my-channel");
140
console.log(`Subscribers: ${subscriberCount}`);
141
142
// Get subscriber count for sharded channel
143
const shardedCount = await PUBSUB(standaloneClient, "SHARDNUMSUB", "sharded-channel");
144
console.log(`Sharded subscribers: ${shardedCount}`);
145
146
// With Redis cluster
147
const clusterClient = createCluster({
148
rootNodes: [
149
{ url: "redis://localhost:7000" },
150
{ url: "redis://localhost:7001" }
151
]
152
});
153
await clusterClient.connect();
154
155
// Automatically handles cluster topology
156
const clusterCount = await PUBSUB(clusterClient, "NUMSUB", "cluster-channel");
157
console.log(`Cluster subscribers: ${clusterCount}`);
158
```
159
160
### ioredis Compatibility
161
162
The utilities also work with ioredis clients:
163
164
```typescript
165
import { Redis, Cluster } from "ioredis";
166
import { PUBSUB } from "@socket.io/redis-adapter";
167
168
// ioredis standalone
169
const ioredisClient = new Redis();
170
const count1 = await PUBSUB(ioredisClient, "NUMSUB", "channel");
171
172
// ioredis cluster
173
const ioredisCluster = new Cluster([
174
{ host: "localhost", port: 7000 },
175
{ host: "localhost", port: 7001 }
176
]);
177
const count2 = await PUBSUB(ioredisCluster, "NUMSUB", "channel");
178
```
179
180
### Redis Response Parsing
181
182
Helper functions for parsing Redis command responses, exported for advanced use cases.
183
184
```typescript { .api }
185
/**
186
* Parse NUMSUB command response from Redis
187
* @param res - Raw Redis response array containing channel and subscriber count
188
* @returns Parsed subscriber count as integer
189
*/
190
function parseNumSubResponse(res: any[]): number;
191
192
/**
193
* Sum an array of numeric values
194
* @param values - Array of numbers to sum
195
* @returns Total sum of all values
196
*/
197
function sumValues(values: number[]): number;
198
```
199
200
**Usage Examples:**
201
202
```typescript
203
import { parseNumSubResponse, sumValues } from "@socket.io/redis-adapter";
204
205
// Parse Redis NUMSUB response
206
const redisResponse = ["my-channel", "5"];
207
const subscriberCount = parseNumSubResponse(redisResponse);
208
console.log(`Subscribers: ${subscriberCount}`); // Subscribers: 5
209
210
// Sum cluster node responses
211
const clusterCounts = [3, 5, 2, 8];
212
const totalSubscribers = sumValues(clusterCounts);
213
console.log(`Total: ${totalSubscribers}`); // Total: 18
214
```
215
216
## Client Detection
217
218
The utilities automatically detect Redis client types and versions:
219
220
- **redis v4+**: Detected by presence of `sSubscribe` method
221
- **redis v3**: Legacy callback-based API
222
- **ioredis**: Detected by constructor name or `isCluster` property
223
- **Clusters**: Automatically detected and handled appropriately
224
225
## Error Handling
226
227
The utilities include built-in error handling for common scenarios:
228
229
- **Malformed Messages**: Invalid JSON or MessagePack data is ignored
230
- **Connection Errors**: Client connection issues are handled gracefully
231
- **Version Compatibility**: Automatic fallback for different client versions
232
233
## Binary Data Support
234
235
The `hasBinary` function supports comprehensive binary data detection:
236
237
- **Native Types**: ArrayBuffer, all TypedArray variants
238
- **Node.js Types**: Buffer objects
239
- **Nested Objects**: Recursively checks object properties and array elements
240
- **JSON Serializable**: Checks `toJSON()` output if present
241
- **Performance**: Optimized for common cases, early returns for primitives