Skip to content

SOLR-18360: remove HttpJettySolrClient.addListenerFactory via a repointable wrapper - #4780

Open
serhiy-bzhezytskyy wants to merge 3 commits into
apache:mainfrom
serhiy-bzhezytskyy:SOLR-18360-undeprecate-addlistenerfactory
Open

SOLR-18360: remove HttpJettySolrClient.addListenerFactory via a repointable wrapper#4780
serhiy-bzhezytskyy wants to merge 3 commits into
apache:mainfrom
serhiy-bzhezytskyy:SOLR-18360-undeprecate-addlistenerfactory

Conversation

@serhiy-bzhezytskyy

@serhiy-bzhezytskyy serhiy-bzhezytskyy commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Removes HttpJettySolrClient.addListenerFactory(HttpListenerFactory) per the original ticket, instead of un-deprecating it as this PR first did.

PKIAuthenticationPlugin needs to attach a listener to a client that's already built and already referenced elsewhere (HttpShardHandlerFactory's defaultClient is captured by loadbalancer at construction time) -- so a straight removal broke security wiring. @dsmiley's suggestion: don't expose a mutable method on the client itself, use a small repointable wrapper instead.

MutableListenerFactory is a HttpListenerFactory whose delegate is repointed via a single volatile write. HttpJettySolrClient is registered with one at construction time (immutable, via Builder.addListenerFactory, same as before) and stays fully immutable itself -- listenerFactory field is final, no instance mutator. HttpClientBuilderPlugin.setup() now takes the MutableListenerFactory instead of the client (it's @lucene.experimental, no compat concern there).

This also fixes two real bugs the old instance method had:

  • Mutating a plain, unsynchronized List while other threads iterate it on every inter-node request.
  • Silently accumulating a duplicate PKI listener on every security.json hot-reload -- each call only ever appended, never replaced.

HttpShardHandlerFactory/UpdateShardHandler/HttpSolrClientProvider updated to hold a MutableListenerFactory field and pass it to setup() instead of the client. No changelog file yet -- flagging since this went from "un-deprecation" to an actual removal + new class; your call on whether one's warranted.

50 tests, 0 failures. TestPKIAuthenticationPlugin, BasicAuthIntegrationTest, MultiAuthPluginTest re-run and pass.

AI-assisted (Claude Sonnet 5)

…istenerFactory)

The ticket asked to remove this instance method in favor of the
Builder-only equivalent, but PKIAuthenticationPlugin (implementing
HttpClientBuilderPlugin) attaches a listener to already-built clients
across HttpShardHandlerFactory/UpdateShardHandler/HttpSolrClientProvider
from CoreContainer.setupHttpClientForAuthPlugin -- a path that can
re-fire on security.json hot-reload, on clients that other long-lived
objects (e.g. HttpShardHandlerFactory's own loadbalancer) already
reference. Rebuilding via the Builder instead would desync those
references. Migrated the one call site that WAS just construction-time
convenience (HttpShardHandlerFactory's own defaultClient) to the Builder
method; left the instance method for the case it actually serves.
@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

@epugh flagging this un-deprecation (not a removal) -- see PR description for why the instance method is still needed.

@dsmiley

dsmiley commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Maybe a mutable ListenerFactory wrapper could be repointed (a hack), instead of exposing a mutable method on an important SolrJ class.

Per dsmiley's review: MutableListenerFactory repoints via a single volatile
write instead of mutating a shared List -- fixes a real thread-safety issue
and a listener-accumulation bug on security.json reload, and lets us
actually remove the method per the original ticket instead of un-deprecating.
@serhiy-bzhezytskyy serhiy-bzhezytskyy changed the title SOLR-18360: un-deprecate HttpJettySolrClient.addListenerFactory SOLR-18360: remove HttpJettySolrClient.addListenerFactory via a repointable wrapper Aug 25, 2026
@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

Implemented -- added MutableListenerFactory, a repointable HttpListenerFactory (single volatile write, no mutable method on the client). Turned out this also fixes two real bugs the old instance method had: it mutated a plain, unsynchronized List while requests iterate it concurrently, and every security.json reload silently added another duplicate PKI listener since it only ever appended. Updated PR description with the details.

@dsmiley dsmiley 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.

I like this!
(please credit me in the changelog)


public default void setup(HttpJettySolrClient client) {}
/** May be called more than once; each call replaces the previous listener, not adds to it. */
public default void setup(MutableListenerFactory listenerFactory) {}

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.

If someone is writing a HttpClientBuilderPlugin, maybe this setup method should expose the HttpJettySolrClient? On the other hand, if the client instance is really many/variable but they all share a MutableListenerFactory then it'd be the wrong design. Yeah ... just speaking out loud.

CC @gerlowskija @janhoy the change proposed here changes our API for customizing HttpClientBuilder. It's labeled "lucene.experiment" so I suppose we can change at-will but I want to raise attention on this. It will belong in the changelog.

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.

nice documentation

@serhiy-bzhezytskyy

serhiy-bzhezytskyy commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

@epugh does this need a changelog entry, or can you add no-changelog?

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