feat(opensearch) #34610: ES-DECOMMISSION markers, OpenSearchExceptionMapper, and neutral utility conversions#35824
Conversation
…eption mapper - Introduce `@ESCoupled` annotation (com.dotcms.content.index) to mark ES-vendor-coupled classes for Phase 3 decommission review; searchable via reflection and grep as a structured backlog marker - Apply @ESCoupled to 8 classes: ElasticsearchStatusExceptionMapper, BulkActionListener, WorkflowAPIImpl, ESContentTool, ContentletAPI, ContentletAPIPreHook, ContentletAPIPostHook, ContentletAPIInterceptor - Add OpenSearchExceptionMapper (@Provider) as the OS counterpart of ElasticsearchStatusExceptionMapper; uses exception.status() for exact HTTP code mapping instead of string matching - Remove ReindexActionListeners inner class from DotRunnableThread (implemented ActionListener<BulkResponse> — ES vendor type) Part of #34610 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ea8835f to
b9dcda1
Compare
…ral classes - CreateJsonWebTokenResource: org.elasticsearch.common.collect.Map → java.util.Map - HttpRequestDataUtil: remove org.elasticsearch.common.network.InetAddresses; replace two-step isInetAddress+createByteArray with single NetUtil.createByteArrayFromIpAddressString null check (Netty already on classpath, returns null for invalid addresses); also removes now-unused io.vavr.control.Try import - SearchHits (domain): remove unused org.elasticsearch.common.Nullable import - ContentsWebAPI: remove unused org.elasticsearch.search.SearchHits import and dead variable declaration SearchHits hits = null Part of #34610 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…se, add remove[]
The annotation's purpose is Phase 3 decommission review; encoding the phase
as a field was redundant. trackedIn is tracked in issue comments, not here.
New shape:
@ESCoupled(reason = "...", remove = {"methodA", "methodB"})
- remove[] lists specific methods/inner classes to delete at Phase 3
- omit remove[] when the entire class is to be decommissioned
- Updated all 8 existing usages accordingly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kflowAPIImpl Replace vendor-specific QueryPhaseExecutionException instanceof check with message-based isPaginationLimitReached() helper. Both ES and OS emit "Result window is too large" when a query exceeds max_result_window (10 000), so the detection is vendor-neutral. Removes the org.elasticsearch import and the @ESCoupled annotation — WorkflowAPIImpl is now ES-free. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t null remoteAddr NetUtil.createByteArrayFromIpAddressString throws NPE when passed null. request.getRemoteAddr() can be null in test contexts. The original code was protected by Try.of() which caught the NPE; the new code must null-check before delegating to Netty. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ormatBytes in TotalSizeSiteSearchIndicesMetricType Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and formatBytes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exclude WorkflowAPIImpl from this PR — the QueryPhaseExecutionException replacement will be handled in a dedicated PR that introduces a neutral DotIndexWindowLimitException thrown by the factory layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove @ESCoupled annotation and extra blank line — WorkflowAPIImpl is excluded from this PR. Vendor-neutral exception handling tracked separately in #35827. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Guard exception.error().reason() with Optional to avoid NPE when OpenSearchException carries no server-side error body (e.g. transport errors) - Add testTruncationNotRounding to document that formatBytes truncates (string slice), not rounds: 1.99 GB → "1.9gb" is intentional Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Claude finished @fabrizzio-dotCMS's task in 3m 9s —— View job ReviewA few items worth a second look — the rest looks clean. 🔴
|
…COMMISSION comments Remove ESCoupled.java annotation class and replace all usages with inline // ES-DECOMMISSION: comments that preserve the decommission context and remain greppable via: grep -r "ES-DECOMMISSION" Affected classes (7): - ESContentTool — bridge methods esSearch/esSearchRaw - ElasticsearchStatusExceptionMapper — full class, replaced by OpenSearchExceptionMapper - BulkActionListener — full class, replaced by IndexBulkListener - ContentletAPI — deprecated method signatures esSearch/esSearchRaw - ContentletAPIInterceptor — same as ContentletAPI - ContentletAPIPostHook — hook methods for deprecated signatures - ContentletAPIPreHook — hook methods for deprecated signatures Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…IImpl Add ES-DECOMMISSION comment explaining why QueryPhaseExecutionException was not migrated to OS 3.x in this branch: no typed equivalent exists in the OpenSearch Java client — detection at this call-site would require message parsing. Deferred to Phase 3 alongside ContentletAPI cleanup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ES-specific QPE branch Replace the if/else that branched on QueryPhaseExecutionException with a single generic Logger.warnAndDebug call covering both the window-limit and any other unexpected search failure. Reason: the QPE branch never fires via the REST client (which wraps all server errors as ElasticsearchStatusException), and no typed OS equivalent exists in OpenSearch Java client 3.x. A comment documents the decision to defer full vendor-neutral handling to Phase 3 at the factory layer. Also removes the now-unused QPE import. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Advances the ES→OpenSearch migration by introducing greppable
// ES-DECOMMISSION:inline comments to mark ES-vendor-coupled classes for Phase 3 decommission review, addsOpenSearchExceptionMapperas the vendor-neutral JAX-RS replacement forElasticsearchStatusExceptionMapper, and removes ES vendor imports from several neutral utility classes.Changes
ES-DECOMMISSION markers
7 classes annotated inline with decommission context and rationale:
ElasticsearchStatusExceptionMapperOpenSearchExceptionMapperis the OS replacementBulkActionListenerIndexBulkListenerESContentToolesSearch/esSearchRawreference ES-specific search typesContentletAPIesSearch/esSearchRawmethod signaturesContentletAPIPreHookContentletAPIPostHookContentletAPIInterceptorContentletAPIGreppable via:
grep -r "ES-DECOMMISSION"New:
OpenSearchExceptionMapper@Providercounterpart toElasticsearchStatusExceptionMapperexception.status()for exact HTTP code passthrough instead of string matchingOptional-guardsexception.error().reason()for cases with no server-side error body (e.g. transport errors)WorkflowAPIImpl— simplified catch blockQueryPhaseExecutionExceptioninstanceof branch (never fires via the REST client; no typed OS equivalent in OpenSearch Java client 3.x)Logger.warnAndDebugmessage that covers both the window-limit case and any other unexpected search failureQuick wins — zero functional change
HttpRequestDataUtilInetAddresses(ES) withNetUtil.createByteArrayFromIpAddressString(Netty); null-guard forgetRemoteAddr()TotalSizeSiteSearchIndicesMetricTypeByteSizeValue(ES) with neutralformatBytes()helper (binary units, 1 decimal place)SearchHits(domain)@NullableimportContentsWebAPISearchHitsimport and dead variableCreateJsonWebTokenResourceorg.elasticsearch.common.collect.Mapwithjava.util.MapDotRunnableThreadReindexActionListenersinner class (implemented ESActionListener<BulkResponse>)Testing
TotalSizeSiteSearchIndicesMetricTypeTest.testTruncationNotRounding— documents thatformatBytestruncates (not rounds):1.99 GB → "1.9gb"is intentional./mvnw compile -pl :dotcms-core -DskipTests— verifies no compilation errorsBreaking Changes
None. All ES-DECOMMISSION markers are comments only; no behavior changed.
OpenSearchExceptionMapperis additive.Closes #34610
🤖 Generated with Claude Code