-
Notifications
You must be signed in to change notification settings - Fork 23
feat: improve redis cluster handling #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||||||||||||||||||||
| import { Redis, Cluster, RedisOptions } from "ioredis"; | ||||||||||||||||||||||||
| import { ConnectionOptions as TlsConnectionOptions } from "tls"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import { QueueType, getQueueType, redisOptsFromUrl } from "./utils"; | ||||||||||||||||||||||||
| import { Queue } from "bullmq"; | ||||||||||||||||||||||||
|
|
@@ -167,21 +168,59 @@ export function getRedisClient( | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (!redisClients[key]) { | ||||||||||||||||||||||||
| if (clusterNodes && clusterNodes.length) { | ||||||||||||||||||||||||
| const { username, password } = redisOptsFromUrl(clusterNodes[0]); | ||||||||||||||||||||||||
| const firstClusterNode = clusterNodes[0]; | ||||||||||||||||||||||||
| const nodeCredentials: Partial<RedisOptions> = firstClusterNode | ||||||||||||||||||||||||
| ? redisOptsFromUrl(firstClusterNode) | ||||||||||||||||||||||||
| : {}; | ||||||||||||||||||||||||
| const userRedisOptions = | ||||||||||||||||||||||||
| ((redisOpts as any).redisOptions as Record<string, any>) ?? {}; | ||||||||||||||||||||||||
| const redisOptions: Record<string, any> = { | ||||||||||||||||||||||||
| ...userRedisOptions, | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
Comment on lines
+176
to
+179
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const resolvedUsername = | ||||||||||||||||||||||||
| redisOpts.username ?? | ||||||||||||||||||||||||
| userRedisOptions.username ?? | ||||||||||||||||||||||||
| nodeCredentials.username; | ||||||||||||||||||||||||
| if (resolvedUsername !== undefined) { | ||||||||||||||||||||||||
| redisOptions.username = resolvedUsername; | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| delete redisOptions.username; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const resolvedPassword = | ||||||||||||||||||||||||
| redisOpts.password ?? | ||||||||||||||||||||||||
| userRedisOptions.password ?? | ||||||||||||||||||||||||
| nodeCredentials.password; | ||||||||||||||||||||||||
| if (resolvedPassword !== undefined) { | ||||||||||||||||||||||||
| redisOptions.password = resolvedPassword; | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| delete redisOptions.password; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const tlsFromEnv = process.env.REDIS_CLUSTER_TLS | ||||||||||||||||||||||||
| ? ({ | ||||||||||||||||||||||||
| cert: Buffer.from( | ||||||||||||||||||||||||
| process.env.REDIS_CLUSTER_TLS, | ||||||||||||||||||||||||
| "base64" | ||||||||||||||||||||||||
| ).toString("ascii"), | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| ).toString("ascii"), | |
| ).toString("utf8"), |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Using Object.assign with an empty object is less idiomatic than using object spread syntax. Consider replacing this with: const mergedTls = { ...tlsFromEnv, ...userRedisOptions.tls, ...redisOpts.tls } as TlsConnectionOptions; Note that you'll need to handle undefined values explicitly or use ?? {} on each source.
| const mergedTls = Object.assign( | |
| {}, | |
| tlsFromEnv ?? {}, | |
| (userRedisOptions.tls as TlsConnectionOptions | undefined) ?? {}, | |
| (redisOpts.tls as TlsConnectionOptions | undefined) ?? {} | |
| ) as TlsConnectionOptions; | |
| const mergedTls = { | |
| ...(tlsFromEnv ?? {}), | |
| ...(userRedisOptions.tls as TlsConnectionOptions | undefined ?? {}), | |
| ...(redisOpts.tls as TlsConnectionOptions | undefined ?? {}) | |
| } as TlsConnectionOptions; |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The credential merging logic (lines 181-199) and TLS merging logic (lines 201-219) are repetitive. Consider extracting a generic helper function like mergeRedisOption(optionKey, ...sources) to reduce code duplication and improve maintainability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional check
if (firstClusterNode)on line 172 is redundant sinceclusterNodes[0]is already checked for truthiness on line 170 (clusterNodes && clusterNodes.length). An empty array would have falsylength, sofirstClusterNodewill always be defined when this code is reached.