-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathredis.providers.ts
More file actions
157 lines (143 loc) · 5.55 KB
/
Copy pathredis.providers.ts
File metadata and controls
157 lines (143 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import { Provider } from '@nestjs/common';
import IORedis, { Redis } from 'ioredis';
import { REDIS_PUBLISHER_CLIENT, REDIS_SUBSCRIBER_CLIENT } from './redis.constants';
// ⬇️ Switched from the `config` package to your custom ConfigService
import { ConfigService } from '../configs/config.service';
import { prefixesForRedisClients } from './redis.decorator';
import { RedisService } from './redis.service';
/**
* Factory that turns a base RedisService into a namespaced instance whose
* `client` property is a connected ioredis client. We keep exactly the same
* logging and option-building logic you had before – only the configuration
* source changed.
*/
function redisFactory(redis: RedisService, prefix: string, cfg: ConfigService): RedisService {
if (prefix) {
redis.setPrefix(prefix);
// 🚚 Pull the JSON string from .env via ConfigService and turn it into an object
const serversRaw = cfg.get('REDIS_SERVERS');
const servers = typeof serversRaw === 'string' ? JSON.parse(serversRaw) : serversRaw;
const server = servers[prefix];
if (!server) {
throw new Error(`[REDIS] No server definition for prefix "${prefix}" in REDIS_SERVERS`);
}
//console.log(`[REDIS] Connecting to ${server.host}:${server.port}`);
const redisOptions = {
keepAlive: 30000,
autoResubscribe: false,
lazyConnect: true, // Don't attempt to connect when initialising the client
showFriendlyErrorStack: true, // See https://github.com/luin/ioredis#error-handling
maxRetriesPerRequest: 10, // Prevent infinite retries
...(server.password && server.password.length > 0 && { password: server.password }),
...(server.tls && {
tls: {
servername: server.host,
},
}),
} as const;
redis.client = new IORedis(server.port, server.host, redisOptions);
redis.client.on('connect', () => {
console.log(`[REDIS] ✅ Redis (${redis.prefix}) connected`);
});
redis.client.on('close', () => {
console.log(`[REDIS] ❌ ${redis.prefix} redis disconnect`);
});
redis.client.on('error', (err) => {
console.log(`[REDIS] ❌ Redis (${redis.prefix}) error: ${err}`);
});
}
return redis;
}
/*
const redisServers = config.get<string>('REDIS_SERVERS');
var redisServerProviders = [];
for (var key in redisServers) {
if (!redisServers.hasOwnProperty(key)) continue;
const server = redisServers[key];
//console.log(`${key} = ${redisServers[key]}`);
redisServerProviders.push({
useFactory: (): Redis => {
console.log(`[REDIS] Connecting to ${server.host}:${server.port}}`);
return new Redis({
host: server.host,
port: server.port,
...(server.password && { password: server.password }),
...(server.tls === 'true' && {
tls: {
servername: server.host,
},
}),
keepAlive: 300,
autoResubscribe: false,
lazyConnect: true, // XXX Don't attempt to connect when initializing the client, in order to properly handle connection failure on a use-case basis
showFriendlyErrorStack: true, // See https://github.com/luin/ioredis#error-handling
maxRetriesPerRequest: 0, // <-- this seems to prevent retries and allow for try/catch
});
},
provide: `REDIS_${key}_CLIENT`,
inject: [RedisService],
});
}
*/
/**
* Creates a provider for a single prefix so that Nest can inject it as
* `RedisService<Prefix>`.
*/
function createRedisProvider(prefix: string): Provider<RedisService> {
return {
provide: `RedisService${prefix}`,
// ⬇️ Inject both the base RedisService *and* ConfigService so the factory
// can look up host/port/password.
useFactory: (redis: RedisService, cfg: ConfigService) => redisFactory(redis, prefix, cfg),
inject: [RedisService, ConfigService],
};
}
/**
* Generates providers for *all* prefixes captured by the @RedisServer decorator.
*/
export function createRedisProviders(): Array<Provider<RedisService>> {
return prefixesForRedisClients.map((prefix) => createRedisProvider(prefix));
}
/* --------------------------------------------------------------------------
* Core pub/sub clients (unchanged)
* --------------------------------------------------------------------------*/
export const redisProviders: Provider[] = [
{
provide: REDIS_SUBSCRIBER_CLIENT,
useFactory: (cfg: ConfigService): Redis => {
const host = cfg.get('QUEUE_REDIS_HOST');
const port = cfg.get('QUEUE_REDIS_PORT');
const password = cfg.get('QUEUE_REDIS_PASSWORD');
const useTls = cfg.get('QUEUE_REDIS_USE_TLS');
const options: any = {
host,
port,
...(password && password.length > 0 ? { password } : {}),
...(useTls ? { tls: { servername: host } } : {}),
};
return new IORedis(options);
},
inject: [ConfigService],
},
{
provide: REDIS_PUBLISHER_CLIENT,
useFactory: (cfg: ConfigService): Redis => {
const host = cfg.get('QUEUE_REDIS_HOST');
const port = cfg.get('QUEUE_REDIS_PORT');
const password = cfg.get('QUEUE_REDIS_PASSWORD');
const useTls = cfg.get('QUEUE_REDIS_USE_TLS');
const options: any = {
host,
port,
...(password && password.length > 0 ? { password } : {}),
...(useTls ? { tls: { servername: host } } : {}),
};
return new IORedis(options);
},
inject: [ConfigService],
},
// Prefix-based providers are appended at module initialisation time:
// ...createRedisProviders(),
];
/* For visibility while booting */
//console.log('redisProviders', redisProviders);