Skip to content

[SOLR-18130][WIP] Unified connection string CloudSolrClient.Builder implementation#4260

Open
vvova15 wants to merge 2 commits intoapache:mainfrom
vvova15:SOLR-18130-add-unified-connection-string-client-builder
Open

[SOLR-18130][WIP] Unified connection string CloudSolrClient.Builder implementation#4260
vvova15 wants to merge 2 commits intoapache:mainfrom
vvova15:SOLR-18130-add-unified-connection-string-client-builder

Conversation

@vvova15
Copy link
Copy Markdown

@vvova15 vvova15 commented Apr 1, 2026

https://issues.apache.org/jira/browse/SOLR-18130

Description

This patch introduces universal connection string support for CloudSolrClient.Builder
and replaces the existing usage in SolrClientCache.

Current state:

  • getCloudSolrClient now works with both connection types.
  • Variables and parameters are still called zkHost.

Proposed next steps:

  • Add an optional second parameter "connectionString" while retaining zkHost
    for backward compatibility.
  • Ensure full support for both ZooKeeper and HTTP connection types in solrj-streaming.

This is a work-in-progress PR for early feedback and discussion.

Solution

  • Added a CloudSolrClient.Builder constructor that handles a connection string that can be either a comma-separated list of HTTP(s) URLs in Solr or a list of Zookeeper hosts ending with /chroot.
  • Replaced the use of the CloudSolrClient.Builder constructor that accepts zookeeper parameters in favor of a constructor with a generic connection string.

Tests

Added unit tests in CloudHttp2SolrClientTest, SolrClientCacheTest
Written new unit test CloudClientConnectionStringTest

Checklist

Please review the following and check all that apply:

  • I have reviewed the guidelines for How to Contribute and my code conforms to the standards described there to the best of my ability.
  • I have created a Jira issue and added the issue ID to my pull request title.
  • I have given Solr maintainers access to contribute to my PR branch. (optional but recommended, not available for branches on forks living under an organisation)
  • I have developed this patch against the main branch.
  • I have run ./gradlew check.
  • I have added tests for my changes.
  • I have added documentation for the Reference Guide
  • I have added a changelog entry for my change

Copy link
Copy Markdown
Contributor

@dsmiley dsmiley left a comment

Choose a reason for hiding this comment

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

Great start! Heck; this is even contributable as-is... say maybe with some additonal usages of this nifty constructor.

@epugh in the CLI (or anywhere you know of) can this be used? From my experience, this is useful for clients creating CloudSolrClient in a generic way with respect to where the state comes from.

Comment on lines +257 to +280
* <p>The parser automatically detects the mode based on the presence of a scheme:
*
* <ul>
* <li>If any part starts with {@code http://} or {@code https://}, the entire string is
* treated as a list of HTTP(S) URLs.
* <li>Otherwise, it treated as a ZooKeeper connection string (with optional chroot)
* </ul>
*
* <p><b>Important:</b> Mixed schemes (e.g. zk hosts + HTTP URLs) are not allowed and will
* result in an error when building the client.
*
* <p>Usage examples:
*
* <pre>{@code
* // ZooKeeper with chroot
* new CloudSolrClient.Builder("zk1:2181,zk2:2181,zk3:2181/solr");
*
* // ZooKeeper without chroot
* new CloudSolrClient.Builder("zk1:2181,zk2:2181,zk3:2181");
*
* // Direct HTTPS connections
* new CloudSolrClient.Builder("https://solr1:8983/solr,https://solr2:8983/solr");
* }</pre>
*
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.

I would drop all this honestly

* @param connectionString a string specifying either ZooKeeper connection string or HTTP(S)
* Solr URLs
* @throws IllegalArgumentException if string is null, empty, or malformed
* @see CloudClientConnectionString#parse(String) for parsing logic
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.

no; that class seems should be a private detail, not a public API

public Builder(String connectionString) {
CloudClientConnectionString connStr = CloudClientConnectionString.parse(connectionString);
if (connStr.isZk()) {
this.zkHosts = List.copyOf(connStr.getQuorumItems());
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.

no point in copying... the result of parsing isn't shared / at-risk of shared use

import java.util.Objects;

/** Universal connection string parser logic. */
public final class CloudClientConnectionString {
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.

Are you familiar with Java records?

throw new IllegalArgumentException("Connection string must not be null or empty");
}
connectionString = connectionString.trim();
List<String> parts =
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.

IMO the very first thing after trimming to do is see if "://" is found and bifercate 2 different parse methods based on that. Very simple. The ZK side would then, first thing, extract off the trailing chroot, if present, before doing comma splitting.

Just trying to suggest something simple.

Arrays.stream(connectionString.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.toList();
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.

instead use org.apache.solr.common.util.StrUtils#split

Comment on lines +63 to +66
if (parts.isEmpty()) {
throw new IllegalArgumentException(
"No valid hosts/urls found in connection string: " + connectionString);
}
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.

can instead be in the constructor of the connection string

import java.util.Locale;
import java.util.Objects;

/** Universal connection string parser logic. */
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.

Suggested change
/** Universal connection string parser logic. */
/** Parses ZK and HTTP SolrCloud connection strings. */

CloudClientConnectionString cloudClientConnectionString =
CloudClientConnectionString.parse(connectionString);
if (cloudClientConnectionString.isZk()) {
String zkHostNoChroot = connectionString.split("/")[0];
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.

the chroot should be a field of cloudClientConnectionString

}

/**
* Provide a universal connection string that can represent either:
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.

This method we're documenting does not "provide a connection string". Javadocs should start with what the method does and secondarily say something about the arguments.

disclaimer: I'm a stickler for javadoc style. And plenty of javadocs here are non-compliant.

Suggested change
* Provide a universal connection string that can represent either:
* Creates a client builder based on a connection string of 2 possible formats:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants