-
Notifications
You must be signed in to change notification settings - Fork 26k
Defer circuit breaker release until transport write completes #143136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
drempapis
merged 70 commits into
elastic:main
from
drempapis:fix/release-breaker-after-send-response
Mar 19, 2026
Merged
Changes from 63 commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
bb7e126
initial commit
drempapis 85ffe67
Merge remote-tracking branch 'origin/main' into fix/release-breaker-a…
drempapis 80991f2
update after review
drempapis 4348a8d
update code
drempapis 843fc64
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 3f6f581
[CI] Auto commit changes from spotless
6574cc6
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 4184b9a
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 7a6b29e
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis e8f0e02
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis b85733b
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 5a37cde
update codee
drempapis a26a1ec
update after review
drempapis 9487e49
update after review
drempapis 69d1e54
update after review
drempapis 1ae96d2
update after review
drempapis 5444e46
update after review
drempapis ea8a10d
udpate
drempapis 2fc3ee0
update code
drempapis dc07e82
update
drempapis 9b700a8
update
drempapis 1b6361f
update after review
drempapis 2a1ef9a
update after review
drempapis d89663e
update after review
drempapis b16d813
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 4f5b108
[CI] Auto commit changes from spotless
8773f77
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 876f3e8
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 832b08c
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 2205ab4
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 3ce47fa
update after review
drempapis f9d7e43
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 320cedf
[CI] Auto commit changes from spotless
b75717d
update after review
drempapis c15da98
update after review
drempapis a027e21
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 47082a4
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis b8da157
update after review
drempapis 4e8a993
Merge branch 'fix/release-breaker-after-send-response' of github.com:…
drempapis 0507aaf
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 391165c
Update newNetworkBytesStream method signature
drempapis b825df8
Fix mock behavior for newNetworkBytesStream method
drempapis a74f69d
Fix merge conflict in TransportService.java
drempapis 7797454
Remove default implementation for newNetworkBytesStream
drempapis 2a4f7c9
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 10cf010
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 00767dd
[CI] Auto commit changes from spotless
cf59664
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 929532e
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis e8023db
update after review
drempapis 506a922
update after review
drempapis ff2a4c9
update after review
drempapis 8e78ca8
update after review
drempapis 94a89c5
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis cf6c215
update after review
drempapis c7a08d1
[CI] Auto commit changes from spotless
3682c19
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis e2233ce
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 97e14de
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 3f41823
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis ac496e3
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis a63d189
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 1cd903c
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 82badc8
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis 3fade55
update naming and small fixes after review
drempapis a89f2d2
update after review
drempapis 27a750d
update after review
drempapis 3be8c42
update after review
drempapis cc26220
update class name
drempapis 1fcac86
Merge branch 'main' into fix/release-breaker-after-send-response
drempapis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
198 changes: 198 additions & 0 deletions
198
server/src/test/java/org/elasticsearch/action/search/AsBytesResponseTests.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
| package org.elasticsearch.action.search; | ||
|
|
||
| import org.elasticsearch.action.ActionListener; | ||
| import org.elasticsearch.common.io.stream.StreamInput; | ||
| import org.elasticsearch.common.io.stream.StreamOutput; | ||
| import org.elasticsearch.common.settings.Settings; | ||
| import org.elasticsearch.test.ESTestCase; | ||
| import org.elasticsearch.test.transport.MockTransport; | ||
| import org.elasticsearch.threadpool.TestThreadPool; | ||
| import org.elasticsearch.threadpool.ThreadPool; | ||
| import org.elasticsearch.transport.BytesTransportResponse; | ||
| import org.elasticsearch.transport.TestDirectResponseChannel; | ||
| import org.elasticsearch.transport.TestTransportChannel; | ||
| import org.elasticsearch.transport.TestTransportChannels; | ||
| import org.elasticsearch.transport.TransportResponse; | ||
| import org.elasticsearch.transport.TransportService; | ||
| import org.junit.After; | ||
| import org.junit.Before; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Collections; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.concurrent.atomic.AtomicReference; | ||
|
|
||
| import static org.elasticsearch.cluster.node.DiscoveryNodeUtils.builder; | ||
| import static org.hamcrest.Matchers.equalTo; | ||
| import static org.hamcrest.Matchers.instanceOf; | ||
| import static org.hamcrest.Matchers.notNullValue; | ||
|
|
||
| public class AsBytesResponseTests extends ESTestCase { | ||
|
|
||
| private ThreadPool threadPool; | ||
| private TransportService transportService; | ||
|
|
||
| @Override | ||
| @Before | ||
| public void setUp() throws Exception { | ||
| super.setUp(); | ||
|
drempapis marked this conversation as resolved.
Outdated
|
||
| threadPool = new TestThreadPool(getTestName()); | ||
| var mockTransport = new MockTransport(); | ||
| transportService = mockTransport.createTransportService( | ||
| Settings.EMPTY, | ||
| threadPool, | ||
| TransportService.NOOP_TRANSPORT_INTERCEPTOR, | ||
| address -> builder("test-node").build(), | ||
| null, | ||
| Collections.emptySet() | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| @After | ||
| public void tearDown() throws Exception { | ||
| transportService.close(); | ||
| ThreadPool.terminate(threadPool, 30, TimeUnit.SECONDS); | ||
| super.tearDown(); | ||
| } | ||
|
|
||
| public void testNetworkPathBytesResponseRoundTrip() throws Exception { | ||
| var sentResponse = new AtomicReference<TransportResponse>(); | ||
|
|
||
| var channel = new TestTransportChannel(ActionListener.wrap(resp -> { | ||
| resp.mustIncRef(); | ||
| sentResponse.set(resp); | ||
| }, e -> fail("unexpected failure: " + e))); | ||
|
|
||
| var original = new SimpleTestResponse("test"); | ||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, channel, null); | ||
|
drempapis marked this conversation as resolved.
Outdated
|
||
|
|
||
| listener.onResponse(original); | ||
|
|
||
| assertThat(sentResponse.get(), instanceOf(BytesTransportResponse.class)); | ||
| var bytesResp = (BytesTransportResponse) sentResponse.get(); | ||
| try (StreamInput in = bytesResp.streamInput()) { | ||
| var deserialized = new SimpleTestResponse(in); | ||
| assertThat(deserialized.value, equalTo("test")); | ||
| } finally { | ||
| bytesResp.decRef(); | ||
| } | ||
| } | ||
|
|
||
| public void testNetworkPathSerializationFailureSendsFailure() { | ||
| var sentException = new AtomicReference<Exception>(); | ||
|
|
||
| var channel = new TestTransportChannel( | ||
| ActionListener.wrap(resp -> fail("should not succeed when serialization fails"), sentException::set) | ||
| ); | ||
|
|
||
| ActionListener<FailingTestResponse> listener = SearchTransportService.asBytesResponse(transportService, channel, null); | ||
|
|
||
| listener.onResponse(new FailingTestResponse()); | ||
|
|
||
| assertThat(sentException.get(), notNullValue()); | ||
| assertThat(sentException.get(), instanceOf(IOException.class)); | ||
| } | ||
|
|
||
| public void testNetworkPathOnFailureForwardsFailure() { | ||
| var sentException = new AtomicReference<Exception>(); | ||
|
|
||
| var channel = new TestTransportChannel(ActionListener.wrap(resp -> fail("should not succeed"), sentException::set)); | ||
|
|
||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, channel, null); | ||
|
|
||
| listener.onFailure(new RuntimeException("upstream failure")); | ||
|
|
||
| assertThat(sentException.get(), notNullValue()); | ||
| } | ||
|
|
||
| public void testDirectPathForwardsOriginalResponse() { | ||
| var sentResponse = new AtomicReference<TransportResponse>(); | ||
|
|
||
| var channel = new TestDirectResponseChannel(ActionListener.wrap(sentResponse::set, e -> fail("unexpected failure: " + e))); | ||
|
|
||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, channel, null); | ||
|
|
||
| var original = new SimpleTestResponse("direct-test"); | ||
| listener.onResponse(original); | ||
|
|
||
| assertSame("direct path must forward the original response, not BytesTransportResponse", original, sentResponse.get()); | ||
|
drempapis marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| public void testDirectPathOnFailureForwardsFailure() { | ||
| var sentException = new AtomicReference<Exception>(); | ||
|
|
||
| var channel = new TestDirectResponseChannel(ActionListener.wrap(resp -> fail("should not succeed"), sentException::set)); | ||
|
|
||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, channel, null); | ||
|
|
||
| listener.onFailure(new RuntimeException("upstream failure")); | ||
|
|
||
| assertThat(sentException.get(), notNullValue()); | ||
| } | ||
|
|
||
| public void testTaskTransportChannelUnwrapsToDirectPath() { | ||
| var sentResponse = new AtomicReference<TransportResponse>(); | ||
|
|
||
| var directChannel = new TestDirectResponseChannel(ActionListener.wrap(sentResponse::set, e -> fail("unexpected failure: " + e))); | ||
| var taskChannel = TestTransportChannels.newTaskTransportChannel(directChannel, () -> {}); | ||
|
|
||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, taskChannel, null); | ||
|
|
||
| var original = new SimpleTestResponse("task-wrapped-test"); | ||
| listener.onResponse(original); | ||
|
|
||
| assertSame("task-wrapped direct channel must forward original response, not BytesTransportResponse", original, sentResponse.get()); | ||
| sentResponse.get().decRef(); | ||
| } | ||
|
|
||
| public void testTaskTransportChannelUnwrapsToNetworkPath() { | ||
| var sentResponse = new AtomicReference<TransportResponse>(); | ||
|
|
||
| var networkChannel = new TestTransportChannel(ActionListener.wrap(resp -> { | ||
| resp.mustIncRef(); | ||
| sentResponse.set(resp); | ||
| }, e -> fail("unexpected failure: " + e))); | ||
| var taskChannel = TestTransportChannels.newTaskTransportChannel(networkChannel, () -> {}); | ||
|
|
||
| ActionListener<SimpleTestResponse> listener = SearchTransportService.asBytesResponse(transportService, taskChannel, null); | ||
|
|
||
| listener.onResponse(new SimpleTestResponse("task-network-test")); | ||
|
|
||
| assertThat(sentResponse.get(), instanceOf(BytesTransportResponse.class)); | ||
| sentResponse.get().decRef(); | ||
| } | ||
|
|
||
| static class SimpleTestResponse extends TransportResponse { | ||
| final String value; | ||
|
|
||
| SimpleTestResponse(String value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| SimpleTestResponse(StreamInput in) throws IOException { | ||
| this.value = in.readString(); | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(StreamOutput out) throws IOException { | ||
| out.writeString(value); | ||
| } | ||
| } | ||
|
|
||
| static class FailingTestResponse extends TransportResponse { | ||
| @Override | ||
| public void writeTo(StreamOutput out) throws IOException { | ||
| throw new IOException("simulated serialization failure"); | ||
| } | ||
| } | ||
|
|
||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.