Skip to content

CommandObjects refactoring Part 1: Move responsibility to the client class - #4513

Merged
uglide merged 9 commits into
masterfrom
im/refactor-command-objects-p1
May 18, 2026
Merged

uglide merged 9 commits into
masterfrom
im/refactor-command-objects-p1

Conversation

@uglide

@uglide uglide commented May 8, 2026 •

Copy link
Copy Markdown
Contributor

Note

Medium Risk
Refactors core client construction and how CommandObjects are created/configured, which could subtly affect protocol negotiation and module command defaults across all UnifiedJedis-based clients.

Overview
Moves CommandObjects responsibility from builders to the client layer. UnifiedJedis now constructs CommandObjects internally via a newCommandObjects(RedisProtocol) factory hook (overridden by cluster clients) and applies config-derived knobs in one place.

Promotes command-object configuration into JedisClientConfig. Adds commandKeyArgumentPreProcessor, jsonObjectMapper, and searchDialect to JedisClientConfig/DefaultJedisClientConfig, wires builders/clients to pass the full config through, and deprecates the old builder-level setters while still folding them into the final config for compatibility.

Reviewed by Cursor Bugbot for commit d1493e7. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented May 8, 2026 •

Copy link
Copy Markdown

Test Results

β€‡β€ˆ191 files  ± 0β€‚β€ƒβ€‡β€ˆ191 suites  Β±0   9m 21s ⏱️ +10s
7β€ˆ674 tests +12  7β€ˆ404 βœ… +1β€ˆ470  270 πŸ’€  -β€Š1β€ˆ458  0 ❌ Β±0 
7β€ˆ694 runsβ€Š +24  7β€ˆ422 βœ… +1β€ˆ488  272 πŸ’€  -β€Š1β€ˆ464  0 ❌ Β±0 

Results for commit d1493e7. ± Comparison against base commit 20c2f3d.

This pull request removes 2 and adds 14 tests. Note that renamed tests count towards both.
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest ‑ testScorer(Scorer, double, double)[1]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest ‑ testScorer(Scorer, double, double)[2]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][1]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][2]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][3]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][4]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][5]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][6]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[1] ‑ testScorer(Scorer, double, double)[1][7]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[2] ‑ testScorer(Scorer, double, double)[2][1]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[2] ‑ testScorer(Scorer, double, double)[2][2]
redis.clients.jedis.commands.unified.search.FTHybridCommandsTestBase$SupportedScorersTest[2] ‑ testScorer(Scorer, double, double)[2][3]
…

♻️ This comment has been updated with latest results.

@jit-ci

jit-ci Bot commented May 8, 2026 •

Copy link
Copy Markdown

πŸ›‘οΈ Jit Security Scan Results

CRITICAL HIGH MEDIUM

βœ… No security findings were detected in this PR


Security scan by Jit

@uglide
uglide force-pushed the im/refactor-command-objects-p1 branch from 8fe8c58 to c793b91 Compare May 8, 2026 07:54
@uglide uglide added the techdebt Things that can be improved or refactored label May 8, 2026
@uglide
uglide requested review from atakavci, ggivo and tishun May 8, 2026 08:59

@ggivo ggivo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in general

A builder for the newly introduced CommandObjectsConfig will avoid more constructors in the future.
And we need to document changes in AbstractClientBuilder in the migration guide.

@atakavci

atakavci commented May 11, 2026 •

Copy link
Copy Markdown
Contributor

Overall this feels like we are introducing more test surface and (more importantly) public API without much benefit.

it would be better to drop those preprocessor, dialect and mapper at all from abstract client and have a abstract supplier method for CommandObject, since they have no other use. Having said that, i see this does not align well with other createDefaultABC factory methods in abstract base.

Not trying to make it a huge deal but i'd push to refine what abstract class promises on the surface; providing defaults, configuring individual sub-objects and having more room for extensibility in concrete classes,, doing all those at one shot signals more refactoring in the future.

@uglide
uglide force-pushed the im/refactor-command-objects-p1 branch from b0171d7 to 3538739 Compare May 13, 2026 14:11
@uglide uglide added the breakingchange Pull request that has breaking changes. Must include the breaking behavior in release notes. label May 13, 2026
@uglide
uglide requested a review from ggivo May 13, 2026 14:23

@ggivo ggivo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM,

Suggestion to move Moving commandKeyArgumentPreProcessor / jsonObjectMapper / searchDialect onto JedisClientConfig makes sense to me.

Posted a follow-up question on whether CommandObjectsBuilder is needed.

uglide and others added 8 commits May 18, 2026 14:03
…#4531)

CommandObjects and ClusterCommandObjects already expose (RedisProtocol)
constructors, so the builder layered nothing on top of two plain setters.
Replace the protected createCommandObjects(protocol, clientConfig) +
buildCommandObjects(...) seam with a single newCommandObjects(protocol)
factory hook and a package-private applyCommandObjectsConfiguration(...)
that wires the three JedisClientConfig knobs onto the freshly constructed
instance. JedisCluster and RedisClusterClient overrides collapse to one
line each.

Net effect: -1 public class (CommandObjectsBuilder), -1 static factory
(CommandObjects.builder), and a cleaner step toward the
"// TODO: Remove together with setProtocol" plan already noted on both
no-arg ctors.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
@uglide
uglide force-pushed the im/refactor-command-objects-p1 branch from 980f47c to d79428a Compare May 18, 2026 12:08

@atakavci atakavci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d1493e7. Configure here.

}

this.commandObjects = newCommandObjects(resolvedProtocol);
applyCommandObjectsConfiguration(commandObjects, clientConfig);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overridable method called from superclass constructor is fragile

Medium Severity

newCommandObjects(resolvedProtocol) is a non-final overridable method invoked from the UnifiedJedis constructor. JedisCluster and RedisClusterClient override it to return ClusterCommandObjects. While currently safe (overrides don't access subclass instance state), this is a classic anti-pattern β€” any future modification adding subclass field references in the override would silently encounter uninitialized state, since the subclass constructor hasn't run yet. A factory-based or template-based approach that doesn't rely on virtual dispatch during construction would be more robust.

Additional Locations (2)
Fix in CursorΒ Fix in Web

Reviewed by Cursor Bugbot for commit d1493e7. Configure here.

@uglide
uglide merged commit a3d6d95 into master May 18, 2026
18 checks passed
@uglide
uglide deleted the im/refactor-command-objects-p1 branch May 18, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breakingchange Pull request that has breaking changes. Must include the breaking behavior in release notes. techdebt Things that can be improved or refactored

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants