-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
fix(redis): version detection logic #11764
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
fix(redis): version detection logic #11764
Conversation
add extra check to detect v3.x and take into account legacy mode closes typeorm#11635
WalkthroughAdded legacy mode support for Redis client compatibility by introducing runtime version detection (Redis 3.x via Changes
Sequence DiagramsequenceDiagram
participant App
participant RedisQueryResultCache
participant PlatformTools
participant RedisClient
App->>RedisQueryResultCache: connect()
RedisQueryResultCache->>PlatformTools: load("redis")
PlatformTools-->>RedisQueryResultCache: createClient factory
RedisQueryResultCache->>RedisClient: createClient()
RedisQueryResultCache->>RedisQueryResultCache: detectRedisVersion()
alt connect() method present
RedisQueryResultCache->>RedisClient: client.connect()
RedisClient-->>RedisQueryResultCache: connected
RedisQueryResultCache->>RedisQueryResultCache: Set redisMajorVersion >= 4
else connect() method absent
RedisQueryResultCache->>RedisQueryResultCache: Set redisMajorVersion = 3
end
alt legacyMode enabled
RedisQueryResultCache->>RedisQueryResultCache: Set isLegacyMode = true
end
App->>RedisQueryResultCache: getFromCache()
RedisQueryResultCache->>RedisQueryResultCache: shouldUsePromiseApi()?
alt shouldUsePromiseApi() returns true
RedisQueryResultCache->>RedisClient: client.get() [Promise-based]
RedisClient-->>RedisQueryResultCache: Promise<value>
else shouldUsePromiseApi() returns false
RedisQueryResultCache->>RedisClient: client.get(key, callback) [Callback-based]
RedisClient-->>RedisQueryResultCache: value via callback
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 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: 0
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)
71-77: Redis v5 incorrectly receives legacy mode flag; Promise API inaccessibleThe code detects Redis 4+ by checking for the
connect()method (line 69), which is present in both Redis v4 and v5. However, it unconditionally setslegacyMode: truefor all matches (line 74) before precise version detection occurs (line 97).Redis v5 does not support
legacyModeat createClient time; instead it usesclient.legacy()method on an existing client. The project supports Redis v3, v4, and v5 (per package.json:"redis": "^3.1.1 || ^4.0.0 || ^5.0.14"), so the code must distinguish between them.Critical issues:
- Line 74 sets
legacyMode: truefor Redis v5, which is unsupported and causes Redis v5 clients to never use Promise-based API (line 345-348)- Version detection at line 97 (
detectRedisVersion()) occurs after the legacyMode flag is already set, making it impossible to apply Redis 5-specific handling- Line 327 correctly identifies Redis v5, but by then
isLegacyModeis already true, permanently disabling Promise API for v5 usersFix required: Refactor lines 71-77 to detect Redis version before applying legacyMode. Only set
legacyMode: truefor Redis v4; use an alternative approach for Redis v5 (e.g., callclient.legacy()after connection if needed for compatibility) or skip legacy mode entirely for v5.
🧹 Nitpick comments (1)
src/cache/RedisQueryResultCache.ts (1)
324-331: Minor: Comment slightly imprecise.The comment on line 329 mentions "Redis 3/4 set method" but line 330 sets
redisMajorVersion = 3. While this is functionally correct (Redis 4 would haveisLegacyMode = trueanyway, forcing callback-based API), the version number could be misleading for debugging.Consider updating the comment for clarity:
} else { - // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) - this.redisMajorVersion = 3 + // Redis 3/4 set method requires more parameters (key, value, flag, duration, callback) + // Set to 3 as fallback (Redis 4 would have isLegacyMode=true anyway) + this.redisMajorVersion = 3 }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/cache/RedisQueryResultCache.ts(9 hunks)test/unit/cache/redis-query-result-cache.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
test/unit/cache/redis-query-result-cache.ts (2)
src/platform/PlatformTools.ts (1)
PlatformTools(17-279)src/cache/RedisQueryResultCache.ts (1)
RedisQueryResultCache(11-350)
🔇 Additional comments (6)
test/unit/cache/redis-query-result-cache.ts (3)
1-21: LGTM!Test setup is well-structured with proper cleanup and type definitions for Redis callbacks.
23-86: LGTM!Test accurately simulates a Redis v3 client (lacking
connect()method) and verifies correct version detection and callback-based API usage.
88-149: LGTM, but consider testing Redis 5 without legacy mode.The test validates legacy mode behavior correctly. However, the current implementation always enables
legacyModefor any Redis client with aconnect()method (Redis 4+). This means Redis 5 users never get the native promise-based API even though they should.Consider adding a test case for Redis 5 clients that should use the native promise-based API without legacy mode. The current flow at line 71-76 in src/cache/RedisQueryResultCache.ts unconditionally enables legacy mode for all Redis 4+ clients, which may prevent Redis 5 users from benefiting from the native promise API.
src/cache/RedisQueryResultCache.ts (3)
36-39: LGTM!The
isLegacyModeproperty correctly tracks whether the Redis client requires callback-based API when legacy mode is enabled for Redis 4.x compatibility.
318-323: LGTM! This is the core fix.Detecting Redis v3 by checking for the absence of the
connect()method is correct and addresses the root cause reported in issue #11635, where Redis 3 clients were incorrectly detected as v5 whenset.lengthreturned 0.
338-349: LGTM! Method rename improves clarity.The rename from
isRedis5OrHigher()toshouldUsePromiseApi()better reflects the actual behavior, which considers both version and legacy mode. The implementation correctly prioritizes legacy mode over version detection.
|
@pkuczynski no I didn't see that! my approach is a continuation of the first approach, but probably the one in #11767 is more robust. the only possible downside is |
|
@ibrahimmenem thank you for your work on this. I think we are going to go with the approach in #11767 since it sets us up to better handle different redis versions going forward, but let's leave this open until we have a working fix merged in. |
add extra check to detect v3.x and take into account legacy mode
fixes #11635
fixes #11749
Description of change
Redis 3 client is being detected as v5 because the set.length is returning 0.
The fix checks if the client has no connect() function and immediately set it as version 3
also conserves the legacy mode flag to be used in isRedis5OrHigher , and changes the function
name to shouldUsePromiseApi to match what it now does.
tested locally with redis3 client
added 2 unit tests
Pull-Request Checklist
masterbranchFixes #11635Summary by CodeRabbit
Release Notes
New Features
Tests