-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
fix(redis): version detection #11767
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
Conversation
WalkthroughReplaces runtime heuristic for Redis major-version detection with a package.json lookup via new PlatformTools.readPackageVersion(name); parses the returned version and sets redisMajorVersion = 3 for major <=4 or = 5 for major >=5; invalid version formats now throw a TypeORMError. Changes
Sequence Diagram(s)sequenceDiagram
participant Cache as RedisQueryResultCache
participant Tools as PlatformTools
participant PKG as require("redis/package.json")
rect "#E8F6FF"
Cache->>Tools: readPackageVersion("redis")
end
rect "#F6F8E8"
Tools->>PKG: require("redis/package.json")
PKG-->>Tools: { version: "x.y.z", ... }
Tools-->>Cache: "x.y.z"
end
rect "#FFF5E6"
Cache->>Cache: parse major = parseInt(x)
alt invalid or NaN
Cache->>Cache: throw TypeORMError("Invalid redis version format")
else major <= 4
Cache->>Cache: redisMajorVersion = 3
else major >= 5
Cache->>Cache: redisMajorVersion = 5
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/platform/PlatformTools.ts (1)
30-36: Consider renaming method to reflect actual behavior.The method name
readPackageVersionimplies it returns only the version string, but it actually returns the entire package.json object. This could lead to confusion for future maintainers.Consider one of these approaches:
Option 1: Rename the method to match its behavior:
- /** - * Reads package.json of the given package. - * This operation only supports on node platform - */ - static readPackageVersion(name: string): any { + /** + * Reads package.json of the given package. + * This operation only supports on node platform + */ + static readPackageJson(name: string): any { return require(`${name}/package.json`) }Option 2: Keep the name and return only the version:
/** - * Reads package.json of the given package. + * Reads the version from package.json of the given package. * This operation only supports on node platform */ static readPackageVersion(name: string): string { - return require(`${name}/package.json`) + return require(`${name}/package.json`).version }If you choose Option 2, you'll need to update the usage in RedisQueryResultCache.ts accordingly.
src/cache/RedisQueryResultCache.ts (1)
310-318: Improve semantic clarity of version detection logic.The current logic sets
redisMajorVersion = 3for all Redis versions 1-4, which is semantically confusing. The property name suggests it stores the actual major version, but it's actually storing a compatibility marker.Consider one of these approaches:
Option 1: Rename the property to reflect its purpose:
- /** - * Redis major version number - */ - protected redisMajorVersion: number | undefined + /** + * Redis API compatibility version (3 for v1-v4 callback-based API, 5 for v5+ Promise-based API) + */ + protected redisApiVersion: number | undefinedOption 2: Store the actual major version and update the compatibility check:
try { const { version } = PlatformTools.readPackageVersion("redis") const major = parseInt(version.split(".")[0], 10) - if (major <= 4) { - // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) - this.redisMajorVersion = 3 - } else { - // Redis 5+ set method accepts fewer parameters (key, value, options) - this.redisMajorVersion = 5 - } + // Store actual major version + this.redisMajorVersion = major } catch { - // Default to Redis 3/4 for maximum compatibility + // Default to Redis 3 for maximum compatibility this.redisMajorVersion = 3 }Then update
isRedis5OrHigher()to remain unchanged:private isRedis5OrHigher(): boolean { if (this.clientType !== "redis") return false return ( this.redisMajorVersion !== undefined && this.redisMajorVersion >= 5 ) }This approach is clearer and more maintainable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/cache/RedisQueryResultCache.ts(1 hunks)src/platform/PlatformTools.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/cache/RedisQueryResultCache.ts (1)
src/platform/PlatformTools.ts (1)
PlatformTools(17-287)
🔇 Additional comments (1)
src/cache/RedisQueryResultCache.ts (1)
306-323: LGTM! Clean approach to version detection.The new implementation using
PlatformTools.readPackageVersionis a significant improvement over runtime heuristics. The try-catch with a sensible fallback to version 3 ensures robustness when the package.json cannot be read.
f267efe to
941b757
Compare
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.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/cache/RedisQueryResultCache.ts (1)
302-305: Update the outdated method comment.The comment states the method "Detects the Redis version based on the connected client's API characteristics without creating test keys," but the implementation now reads the package version directly from
package.json. Please update the comment to reflect the current approach.Apply this diff to update the comment:
/** - * Detects the Redis version based on the connected client's API characteristics - * without creating test keys in the database + * Detects the Redis major version by reading the installed redis package version */ private detectRedisVersion(): void {
🧹 Nitpick comments (1)
src/cache/RedisQueryResultCache.ts (1)
319-322: Consider logging version detection failures for easier debugging.The catch block silently falls back to Redis 3 without any diagnostic information. In production environments, this could make it difficult to troubleshoot version detection issues or understand why a particular behavior was chosen.
Apply this diff to add logging:
} catch (error) { // Default to Redis 3/4 for maximum compatibility + this.connection.logger.log( + "warn", + `Failed to detect Redis version, defaulting to 3: ${error}`, + ) this.redisMajorVersion = 3 }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/cache/RedisQueryResultCache.ts(1 hunks)src/platform/PlatformTools.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/platform/PlatformTools.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/cache/RedisQueryResultCache.ts (1)
src/platform/PlatformTools.ts (1)
PlatformTools(17-290)
src/cache/RedisQueryResultCache.ts
Outdated
| const { version } = PlatformTools.readPackageVersion("redis") | ||
| const major = parseInt(version.split(".")[0], 10) | ||
| if (major <= 4) { | ||
| // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) | ||
| this.redisMajorVersion = 3 | ||
| } else { | ||
| // Redis 5+ set method accepts fewer parameters (key, value, options) | ||
| this.redisMajorVersion = 5 | ||
| } |
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.
Guard against NaN from parseInt to prevent incorrect version detection.
If the version string has an unexpected format, parseInt(version.split(".")[0], 10) returns NaN. Since NaN <= 4 evaluates to false, the code would incorrectly set redisMajorVersion = 5, which may not be compatible with the actual Redis version.
Apply this diff to handle malformed version strings:
const { version } = PlatformTools.readPackageVersion("redis")
const major = parseInt(version.split(".")[0], 10)
+ if (isNaN(major)) {
+ throw new Error(`Invalid Redis version format: ${version}`)
+ }
if (major <= 4) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { version } = PlatformTools.readPackageVersion("redis") | |
| const major = parseInt(version.split(".")[0], 10) | |
| if (major <= 4) { | |
| // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) | |
| this.redisMajorVersion = 3 | |
| } else { | |
| // Redis 5+ set method accepts fewer parameters (key, value, options) | |
| this.redisMajorVersion = 5 | |
| } | |
| const { version } = PlatformTools.readPackageVersion("redis") | |
| const major = parseInt(version.split(".")[0], 10) | |
| if (isNaN(major)) { | |
| throw new Error(`Invalid Redis version format: ${version}`) | |
| } | |
| if (major <= 4) { | |
| // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) | |
| this.redisMajorVersion = 3 | |
| } else { | |
| // Redis 5+ set method accepts fewer parameters (key, value, options) | |
| this.redisMajorVersion = 5 | |
| } |
🧩 Analysis chain
Verify that Redis 4.x is compatible with the Redis 3 API branch.
The code treats Redis 4.x the same as Redis 3.x (line 312-314). Please confirm that Redis 4.x uses the same callback-based API signatures for set, get, del, and other methods as Redis 3.x, as this grouping determines which API style is used throughout the class.
🏁 Script executed:
#!/bin/bash
# Description: Check Redis 4.x changelog to verify API compatibility with Redis 3.x
# Expected: Confirmation that Redis 4 uses callback-based API similar to Redis 3
echo "Checking for Redis API usage patterns in the codebase..."
rg -n -C3 'this\.client\.(set|get|del|quit|flushdb)\(' src/cache/RedisQueryResultCache.tsLength of output: 2402
I need to clarify what the code is actually detecting. Let me check the Redis package being used and what version is being read:
Critical bug: Redis v4 (node-redis client library) uses Promises, not callbacks. The code incorrectly groups v4 with v3.
Node Redis 4.x introduced breaking changes where it uses promises instead of callbacks. The current code at line 312-314 treats Redis 4.x the same as 3.x (callback-based), but Node Redis v4 now uses native Promises by default for all functions. This will cause runtime failures when using node-redis v4.
Change line 312 from if (major <= 4) to if (major <= 3) to use callback-based API only for v3, and promises for v4+.
🤖 Prompt for AI Agents
In src/cache/RedisQueryResultCache.ts around lines 310 to 318, the version
detection incorrectly treats Redis v4 as callback-based by using "if (major <=
4)"; update the condition to only treat v3 and below as callback-based (change
to "if (major <= 3)"), set redisMajorVersion accordingly (3 for callback-based,
5 for Promise-based), and update the accompanying comment to reflect that Redis
v4+ uses Promises rather than callbacks.
941b757 to
b5b477e
Compare
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.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/cache/RedisQueryResultCache.ts (1)
308-319: CRITICAL: Redis v4 uses Promises, not callbacks. Change condition tomajor <= 3.Node Redis v4 introduced breaking changes where all methods return Promises instead of using callbacks. The current code at line 313 treats Redis v4 the same as v3 (callback-based), which will cause runtime failures.
Apply this diff to fix the API version detection:
- if (major <= 4) { - // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) + if (major <= 3) { + // Redis 3 uses callback-based API this.redisMajorVersion = 3 } else { - // Redis 5+ set method accepts fewer parameters (key, value, options) + // Redis 4+ uses Promise-based API this.redisMajorVersion = 5 }
🧹 Nitpick comments (1)
src/platform/PlatformTools.ts (1)
30-39: Consider adding error handling for robustness.The method will throw if the package is not installed or doesn't have a
package.json. While the current caller (RedisQueryResultCache.detectRedisVersion) is protected by prior validation inloadRedis(), consider wrapping therequirein a try-catch for defensive programming and clearer error messages.Apply this diff to add error handling:
static readPackageVersion(name: string): { version: string [key: string]: any } { - return require(`${name}/package.json`) + try { + return require(`${name}/package.json`) + } catch (err) { + throw new TypeError(`Failed to read package.json for "${name}": ${err.message}`) + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/cache/RedisQueryResultCache.ts(1 hunks)src/platform/PlatformTools.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: alumni
Repo: typeorm/typeorm PR: 11581
File: docs/docs/drivers/mongodb.md:9-13
Timestamp: 2025-07-27T17:29:18.547Z
Learning: TypeORM is compatible only with mongodb@^6, not v4 as previously suggested. The package.json file contains the authoritative peer dependency information for the MongoDB driver version compatibility.
Learnt from: alumni
Repo: typeorm/typeorm PR: 11581
File: docs/docs/drivers/mongodb.md:9-13
Timestamp: 2025-07-27T17:29:18.547Z
Learning: TypeORM supports MongoDB driver versions "^5.8.0 || ^6.0.0" according to the peerDependencies in package.json. The v4 driver is NOT supported. Always check package.json for accurate peer dependency information.
📚 Learning: 2025-09-24T12:25:58.176Z
Learnt from: pkuczynski
Repo: typeorm/typeorm PR: 11681
File: package.json:135-135
Timestamp: 2025-09-24T12:25:58.176Z
Learning: When flagging potentially invalid npm package versions, always verify against the direct npm registry using `npm view <package> version` rather than relying solely on web search results, which can be stale due to caching. Recent releases (within hours/days) may not appear in search indexes immediately.
Applied to files:
src/cache/RedisQueryResultCache.ts
📚 Learning: 2025-07-27T17:29:18.547Z
Learnt from: alumni
Repo: typeorm/typeorm PR: 11581
File: docs/docs/drivers/mongodb.md:9-13
Timestamp: 2025-07-27T17:29:18.547Z
Learning: TypeORM supports MongoDB driver versions "^5.8.0 || ^6.0.0" according to the peerDependencies in package.json. The v4 driver is NOT supported. Always check package.json for accurate peer dependency information.
Applied to files:
src/cache/RedisQueryResultCache.ts
📚 Learning: 2025-07-27T17:29:18.547Z
Learnt from: alumni
Repo: typeorm/typeorm PR: 11581
File: docs/docs/drivers/mongodb.md:9-13
Timestamp: 2025-07-27T17:29:18.547Z
Learning: TypeORM is compatible only with mongodb@^6, not v4 as previously suggested. The package.json file contains the authoritative peer dependency information for the MongoDB driver version compatibility.
Applied to files:
src/cache/RedisQueryResultCache.ts
🧬 Code graph analysis (1)
src/cache/RedisQueryResultCache.ts (2)
src/platform/PlatformTools.ts (1)
PlatformTools(17-290)src/error/TypeORMError.ts (1)
TypeORMError(1-17)
commit: |
Refs: 1749
b5b477e to
5110e26
Compare
The proposed change adds a feature that will allow us to check versions in case a similar incompatibility occurs in the future. In addition, there are several aspects that don’t fully align with the other solution—or with the original one: Overall, I believe this solution is simpler and more reusable. |
mguida22
left a comment
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.
Thank you @AdolfodelSel!
How have you tested this so far? Can you add tests to the PR to ensure it works properly?
It looks like this will also resolve #11635
| if (major <= 4) { | ||
| // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) |
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.
With your new approach this comment (and the one about version 5) are not very relevant.
Also, it predates your changes here, but it's confusing to set the redis major version to 3 when we know the version is 4. It would be better to set the version to 4 and when we read the this.redisMajorVersion we can decide to treat 3 and 4 as the same if needed.
|
@AdolfodelSel if you don't have time for this please let me know and I can continue with your approach. I'd like to have this fix included in the next release 🙏 |
|
Hi @mguida22 is there a timeout for a PR so it is considered inactive? |
PR Code Suggestions ✨Latest suggestions up to 6379b70
Previous suggestionsSuggestions up to commit 43ea5d3
Suggestions up to commit 222e1f7
|
|||||||||||||||||||||||||||||||||
No, but we would welcome contributions that build on this. The approach here looks good but it needs tests. @ibrahimmenem if you have some time to add tests on top of these changes (perhaps as a PR into this one) I can help makes sure it gets across the line. |
Refs: 1749
fixes #11749
Description of change
Pull-Request Checklist
masterbranchFixes #00000Summary by CodeRabbit