forked from mastodon/mastodon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathredis.js
135 lines (117 loc) · 3.83 KB
/
redis.js
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
import { Redis } from 'ioredis';
import { parseIntFromEnvValue } from './utils.js';
/**
* @typedef RedisConfiguration
* @property {string|undefined} namespace
* @property {string|undefined} url
* @property {import('ioredis').RedisOptions} options
*/
/**
*
* @param {NodeJS.ProcessEnv} env
* @returns {boolean}
*/
function hasSentinelConfiguration(env) {
return (
typeof env.REDIS_SENTINELS === 'string' &&
env.REDIS_SENTINELS.length > 0 &&
typeof env.REDIS_SENTINEL_MASTER === 'string' &&
env.REDIS_SENTINEL_MASTER.length > 0
);
}
/**
*
* @param {NodeJS.ProcessEnv} env
* @param {import('ioredis').SentinelConnectionOptions} commonOptions
* @returns {import('ioredis').SentinelConnectionOptions}
*/
function getSentinelConfiguration(env, commonOptions) {
const redisDatabase = parseIntFromEnvValue(env.REDIS_DB, 0, 'REDIS_DB');
const sentinelPort = parseIntFromEnvValue(env.REDIS_SENTINEL_PORT, 26379, 'REDIS_SENTINEL_PORT');
const sentinels = env.REDIS_SENTINELS.split(',').map((sentinel) => {
const [host, port] = sentinel.split(':', 2);
/** @type {import('ioredis').SentinelAddress} */
return {
host: host,
port: port ?? sentinelPort,
// Force support for both IPv6 and IPv4, by default ioredis sets this to 4,
// only allowing IPv4 connections:
// https://github.com/redis/ioredis/issues/1576
family: 0
};
});
return {
db: redisDatabase,
name: env.REDIS_SENTINEL_MASTER,
username: env.REDIS_USERNAME,
password: env.REDIS_PASSWORD,
sentinelUsername: env.REDIS_SENTINEL_USERNAME ?? env.REDIS_USERNAME,
sentinelPassword: env.REDIS_SENTINEL_PASSWORD ?? env.REDIS_PASSWORD,
sentinels,
...commonOptions,
};
}
/**
* @param {NodeJS.ProcessEnv} env the `process.env` value to read configuration from
* @returns {RedisConfiguration} configuration for the Redis connection
*/
export function configFromEnv(env) {
const redisNamespace = env.REDIS_NAMESPACE;
// These options apply for both REDIS_URL based connections and connections
// using the other REDIS_* environment variables:
const commonOptions = {
// Force support for both IPv6 and IPv4, by default ioredis sets this to 4,
// only allowing IPv4 connections:
// https://github.com/redis/ioredis/issues/1576
family: 0
// Note: we don't use auto-prefixing of keys since this doesn't apply to
// subscribe/unsubscribe which have "channel" instead of "key" arguments
};
// If we receive REDIS_URL, don't continue parsing any other REDIS_*
// environment variables:
if (typeof env.REDIS_URL === 'string' && env.REDIS_URL.length > 0) {
return {
url: env.REDIS_URL,
options: commonOptions,
namespace: redisNamespace
};
}
// If we have configuration for Redis Sentinel mode, prefer that:
if (hasSentinelConfiguration(env)) {
return {
options: getSentinelConfiguration(env, commonOptions),
namespace: redisNamespace
};
}
// Finally, handle all the other REDIS_* environment variables:
let redisPort = parseIntFromEnvValue(env.REDIS_PORT, 6379, 'REDIS_PORT');
let redisDatabase = parseIntFromEnvValue(env.REDIS_DB, 0, 'REDIS_DB');
/** @type {import('ioredis').RedisOptions} */
const options = {
host: env.REDIS_HOST ?? '127.0.0.1',
port: redisPort,
db: redisDatabase,
username: env.REDIS_USERNAME,
password: env.REDIS_PASSWORD,
...commonOptions,
};
return {
options,
namespace: redisNamespace
};
}
/**
* @param {RedisConfiguration} config
* @param {import('pino').Logger} logger
* @returns {Redis}
*/
export function createClient({ url, options }, logger) {
let client;
if (typeof url === 'string') {
client = new Redis(url, options);
} else {
client = new Redis(options);
}
client.on('error', (err) => logger.error({ err }, 'Redis Client Error!'));
return client;
}