0
# Redis Service
1
2
The RedisService provides the primary interface for Redis operations in Midway.js applications through dependency injection. It wraps the default Redis client instance and delegates all ioredis methods, providing seamless access to Redis functionality.
3
4
## Capabilities
5
6
### RedisService Class
7
8
Main service wrapper implementing the full Redis interface through method delegation.
9
10
```typescript { .api }
11
/**
12
* Primary Redis service for dependency injection
13
* Implements the full ioredis Redis interface
14
* Automatically connects to the default Redis client
15
*/
16
class RedisService implements Redis {
17
@Inject()
18
private serviceFactory: RedisServiceFactory;
19
20
private instance: Redis;
21
22
@Init()
23
async init(): Promise<void>;
24
25
defineCommand(
26
name: string,
27
definition: {
28
lua: string;
29
numberOfKeys?: number;
30
readOnly?: boolean;
31
}
32
): void;
33
}
34
35
interface RedisService extends Redis {}
36
```
37
38
### Service Initialization
39
40
Automatically initializes with the default Redis client from the service factory.
41
42
```typescript { .api }
43
/**
44
* Initializes the service with default Redis client
45
* Called automatically by Midway.js during dependency injection
46
* @throws MidwayCommonError if default Redis instance not found
47
*/
48
async init(): Promise<void>;
49
```
50
51
### Custom Command Definition
52
53
Defines custom Redis commands using Lua scripts.
54
55
```typescript { .api }
56
/**
57
* Defines a custom Redis command using Lua scripting
58
* The command becomes available as a method on the service
59
* @param name - Name of the custom command
60
* @param definition - Command definition with Lua script
61
*/
62
defineCommand(
63
name: string,
64
definition: {
65
lua: string;
66
numberOfKeys?: number;
67
readOnly?: boolean;
68
}
69
): void;
70
```
71
72
**Usage Examples:**
73
74
```typescript
75
import { RedisService } from "@midwayjs/redis";
76
import { Inject, Provide } from "@midwayjs/core";
77
78
@Provide()
79
export class CacheService {
80
@Inject()
81
redisService: RedisService;
82
83
async init() {
84
// Define a custom atomic increment with expire command
85
this.redisService.defineCommand('incrWithExpire', {
86
lua: `
87
local current = redis.call('INCR', KEYS[1])
88
if current == 1 then
89
redis.call('EXPIRE', KEYS[1], ARGV[1])
90
end
91
return current
92
`,
93
numberOfKeys: 1,
94
readOnly: false,
95
});
96
}
97
98
async incrementCounter(key: string, expireSeconds: number) {
99
// Use the custom command (TypeScript may need type assertion)
100
return (this.redisService as any).incrWithExpire(key, expireSeconds);
101
}
102
}
103
```
104
105
## Redis Operations
106
107
The RedisService implements the complete ioredis interface, providing access to all Redis commands and operations:
108
109
### String Operations
110
111
```typescript
112
// All string operations from ioredis are available
113
await redisService.set('key', 'value');
114
await redisService.get('key');
115
await redisService.setex('key', 60, 'value'); // Set with expiration
116
await redisService.incr('counter');
117
await redisService.mget(['key1', 'key2', 'key3']);
118
```
119
120
### Hash Operations
121
122
```typescript
123
await redisService.hset('user:123', 'name', 'John');
124
await redisService.hget('user:123', 'name');
125
await redisService.hmset('user:123', { name: 'John', age: 30 });
126
await redisService.hgetall('user:123');
127
```
128
129
### List Operations
130
131
```typescript
132
await redisService.lpush('queue', 'task1');
133
await redisService.rpop('queue');
134
await redisService.lrange('queue', 0, -1);
135
```
136
137
### Set Operations
138
139
```typescript
140
await redisService.sadd('tags', 'redis', 'database');
141
await redisService.smembers('tags');
142
await redisService.sismember('tags', 'redis');
143
```
144
145
### Sorted Set Operations
146
147
```typescript
148
await redisService.zadd('leaderboard', 100, 'player1');
149
await redisService.zrange('leaderboard', 0, 9);
150
await redisService.zrevrange('leaderboard', 0, 9, 'WITHSCORES');
151
```
152
153
### Key Management
154
155
```typescript
156
await redisService.exists('key');
157
await redisService.expire('key', 3600);
158
await redisService.ttl('key');
159
await redisService.del('key1', 'key2');
160
await redisService.keys('pattern*');
161
```
162
163
## Usage Examples
164
165
### Basic Operations
166
167
```typescript
168
import { RedisService } from "@midwayjs/redis";
169
import { Inject, Provide } from "@midwayjs/core";
170
171
@Provide()
172
export class UserService {
173
@Inject()
174
redisService: RedisService;
175
176
async cacheUser(userId: string, userData: any) {
177
const key = `user:${userId}`;
178
await this.redisService.setex(key, 3600, JSON.stringify(userData));
179
}
180
181
async getUser(userId: string) {
182
const key = `user:${userId}`;
183
const cached = await this.redisService.get(key);
184
return cached ? JSON.parse(cached) : null;
185
}
186
187
async deleteUser(userId: string) {
188
const key = `user:${userId}`;
189
await this.redisService.del(key);
190
}
191
}
192
```
193
194
### Session Management
195
196
```typescript
197
@Provide()
198
export class SessionService {
199
@Inject()
200
redisService: RedisService;
201
202
async createSession(sessionId: string, userData: any, ttlSeconds = 1800) {
203
const key = `session:${sessionId}`;
204
await this.redisService.setex(key, ttlSeconds, JSON.stringify(userData));
205
}
206
207
async getSession(sessionId: string) {
208
const key = `session:${sessionId}`;
209
const data = await this.redisService.get(key);
210
return data ? JSON.parse(data) : null;
211
}
212
213
async refreshSession(sessionId: string, ttlSeconds = 1800) {
214
const key = `session:${sessionId}`;
215
await this.redisService.expire(key, ttlSeconds);
216
}
217
218
async destroySession(sessionId: string) {
219
const key = `session:${sessionId}`;
220
await this.redisService.del(key);
221
}
222
}
223
```
224
225
### Rate Limiting
226
227
```typescript
228
@Provide()
229
export class RateLimitService {
230
@Inject()
231
redisService: RedisService;
232
233
async checkRateLimit(
234
identifier: string,
235
maxRequests: number,
236
windowSeconds: number
237
): Promise<{ allowed: boolean; remaining: number }> {
238
const key = `rate_limit:${identifier}`;
239
const current = await this.redisService.incr(key);
240
241
if (current === 1) {
242
await this.redisService.expire(key, windowSeconds);
243
}
244
245
const remaining = Math.max(0, maxRequests - current);
246
return {
247
allowed: current <= maxRequests,
248
remaining
249
};
250
}
251
}
252
```
253
254
## Event Handling
255
256
The RedisService supports all ioredis event handling:
257
258
```typescript
259
@Provide()
260
export class MonitorService {
261
@Inject()
262
redisService: RedisService;
263
264
async init() {
265
// Listen for connection events
266
this.redisService.on('connect', () => {
267
console.log('Redis connected');
268
});
269
270
this.redisService.on('error', (error) => {
271
console.error('Redis error:', error);
272
});
273
274
this.redisService.on('close', () => {
275
console.log('Redis connection closed');
276
});
277
}
278
}
279
```
280
281
## Transaction Support
282
283
Full support for Redis transactions and pipelines:
284
285
```typescript
286
async transferBetweenCounters(from: string, to: string, amount: number) {
287
const multi = this.redisService.multi();
288
multi.decrby(from, amount);
289
multi.incrby(to, amount);
290
291
const results = await multi.exec();
292
return results;
293
}
294
295
// Pipeline for bulk operations
296
async bulkSet(keyValuePairs: Record<string, string>) {
297
const pipeline = this.redisService.pipeline();
298
299
Object.entries(keyValuePairs).forEach(([key, value]) => {
300
pipeline.set(key, value);
301
});
302
303
await pipeline.exec();
304
}
305
```