Migrate from HLRC to elasticsearch-java 8.x client - #920
Open
Yeikel Santana (yeikel) wants to merge 8 commits into
Open
Migrate from HLRC to elasticsearch-java 8.x client#920Yeikel Santana (yeikel) wants to merge 8 commits into
Yeikel Santana (yeikel) wants to merge 8 commits into
Conversation
|
🎉 All Contributor License Agreements have been signed. Ready to merge. |
| @@ -0,0 +1,37 @@ | |||
| name: CI | |||
There was a problem hiding this comment.
Can be removed before we merge. This was added to help me test end to end rather than locally only
| <!-- switch statements on types exceed maximum complexity --> | ||
| <suppress | ||
| checks="(CyclomaticComplexity)" | ||
| checks="(CyclomaticComplexity|NPathComplexity)" |
There was a problem hiding this comment.
My goal with the migration was to producer the smaller diff possible. I can definitely fix this but the diff will be much larger. I think that it makes sense to take this in a subsequent change
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
11 times, most recently
from
May 15, 2026 22:04
45ad48c to
e34f70d
Compare
This was referenced May 15, 2026
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
10 times, most recently
from
May 19, 2026 21:01
6157170 to
5bee901
Compare
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
3 times, most recently
from
May 29, 2026 03:45
f4c2754 to
fa12854
Compare
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
from
May 29, 2026 03:48
ee4e127 to
83888d1
Compare
Replace the deprecated High Level REST Client with the new elasticsearch-java 8.x client.
…ntainer throwIfFailed() was calling close() before propagating the error. close() calls BulkIngester.close() with a flushTimeoutMs=3min timeout waiting for in-flight requests to drain. With ES down, this blocked the task thread for up to 3 minutes, preventing the task from transitioning to FAILED until after the test's 2-minute await window expired. The Connect framework calls task.stop() -> client.close() immediately after put() throws, so the defensive close inside throwIfFailed() was redundant. Removing it lets the task fail fast via the standard task lifecycle.
…eadlock
BulkIngester submits afterBulk callbacks to bulkScheduler via scheduler.submit().
Its single scheduler thread can block inside FnCondition.awaitUninterruptibly()
while waiting for a concurrency slot (requestsInFlightCount < maxConcurrentRequests).
When DispatchingTransport shared bulkScheduler for retry tasks (introduced in the
previous commit), that created a deadlock:
1. bulkScheduler thread blocks in sendRequestCondition.awaitUninterruptibly()
waiting for an in-flight slot to free up.
2. Freeing a slot requires result.completeExceptionally() to fire, which requires
the retry task to run.
3. The retry task is queued in bulkScheduler, but bulkScheduler is blocked.
4. Neither side can proceed — the connector task stays RUNNING indefinitely.
Fix: give DispatchingTransport its own dedicated single-threaded retryScheduler so
retry tasks are never blocked by BulkIngester's flush tasks.
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
from
May 29, 2026 03:50
83888d1 to
80672d1
Compare
BulkIngester.backoffPolicy and DispatchingTransport both used config.maxRetries(), causing up to (maxRetries+1)^2 HTTP requests per document: each BulkIngester per-item 429 retry issued a new bulk request that re-entered DispatchingTransport with a fresh retry budget. Removing backoffPolicy gives DispatchingTransport sole ownership of the retry budget. HTTP-level 429s (whole-request) continue to be retried as exceptions by DispatchingTransport; per-item 429s in a 200 response go to the listener's error path (DLQ + task failure), matching pre-migration HLRC behavior.
Yeikel Santana (yeikel)
force-pushed
the
migrate-java-client
branch
4 times, most recently
from
June 1, 2026 01:42
30294de to
4c357d9
Compare
Author
|
Jainam Jain (@jjain1259) Is there anything you can do to help this one move forward? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The High Level REST Client (HLRC) is deprecated and was fully removed in Elasticsearch 9, blocking support for ES 9.x. The connector currently depends on
elasticsearch-rest-high-level-client 7.x.Fixes #847.
Breaking change: This migration drops support for Elasticsearch 7.x, which reached end of life on January 15, 2026. The minimum supported version is now Elasticsearch 8.x.
Solution
Replace HLRC with
co.elastic.clients:elasticsearch-java 8.19.15.Dependencies
elasticsearch-rest-high-level-clientandelasticsearch(HLRC artifacts)co.elastic.clients:elasticsearch-java 8.19.15andelasticsearch-rest-client 8.19.15log4j-bom 2.25.4to align transitive log4j versions pulled in by the new clientelasticsearch-java)Core client
BulkProcessor→BulkIngester<SinkRecordAndOffset>: offset state is carried as context on each bulk operation instead of being looked up in a side mapDispatchingTransport— dispatches async callbacks to a dedicated executor, breaking a lock-ordering deadlock betweenBulkIngester's internal condition and the NIO thread pool. Uses a separateretrySchedulerthread pool to prevent a second deadlock where retry tasks queued onbulkSchedulerwould block behindBulkIngester's own flush tasksBulkIngester.backoffPolicyto giveDispatchingTransportsole ownership of the retry budget; previously both layers retried independently, causing up to(maxRetries+1)²HTTP requests per documentclose()fromthrowIfFailed()— the Connect framework callstask.stop() → client.close()immediately afterput()throws, so the defensive close was redundant and caused up to 3-minute delays before a task transitioned to FAILEDData layer
DataConverter.convertRecord(): returnsBulkOperationinstead ofDocWriteRequestMapping.buildMapping(): returnsMap<String, Object>instead ofXContentBuilderVersionType.EXTERNAL) inlined per operation — no single-call equivalent in the new builder APISSL startup scripts
chmod 777 ${ES_DIR}— script runs aselasticsearchuser which cannot chmod its own install directorysu - elasticsearch << EOFheredoc withexec /usr/local/bin/docker-entrypoint.sh eswrapperfor correct signal forwardingopenssl pkcs12withelasticsearch-certutilfor PKCS12 client cert generationPATHupdate for the bundled JDK is now conditional onkeytoolnot already being presentDoes this solution apply anywhere else?
Test Strategy
Release Plan
Merge to master. No backport needed this is a forward-only migration and is not backwards compatible with ES 7.x. A new major version (16.x) should be considered for this release.
Notes
ci: add GitHub Actions workflowcommit should be dropped before merging it was added only to run the test suite via GitHub Actions since Confluent's Semaphore CI is not accessible from this forkbuild: upgrade testcontainerscommit can be extracted into a standalone PR if preferred