Skip to content

Commit 7175349

Browse files
committed
[grid] cancel pending request on client timeout
1 parent db343b9 commit 7175349

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

java/src/org/openqa/selenium/netty/server/SeleniumHandler.java

+16-5
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
import io.netty.channel.ChannelHandlerContext;
2121
import io.netty.channel.SimpleChannelInboundHandler;
22+
import java.util.concurrent.CompletableFuture;
2223
import java.util.concurrent.ExecutorService;
2324
import java.util.concurrent.Executors;
25+
import java.util.concurrent.Future;
2426
import org.openqa.selenium.internal.Require;
2527
import org.openqa.selenium.remote.ErrorFilter;
2628
import org.openqa.selenium.remote.http.HttpHandler;
@@ -31,18 +33,27 @@ class SeleniumHandler extends SimpleChannelInboundHandler<HttpRequest> {
3133

3234
private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
3335
private final HttpHandler seleniumHandler;
36+
private Future<?> lastOne;
3437

3538
public SeleniumHandler(HttpHandler seleniumHandler) {
3639
super(HttpRequest.class);
3740
this.seleniumHandler = Require.nonNull("HTTP handler", seleniumHandler).with(new ErrorFilter());
41+
this.lastOne = CompletableFuture.completedFuture(null);
3842
}
3943

4044
@Override
4145
protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) {
42-
EXECUTOR.submit(
43-
() -> {
44-
HttpResponse res = seleniumHandler.execute(msg);
45-
ctx.writeAndFlush(res);
46-
});
46+
lastOne =
47+
EXECUTOR.submit(
48+
() -> {
49+
HttpResponse res = seleniumHandler.execute(msg);
50+
ctx.writeAndFlush(res);
51+
});
52+
}
53+
54+
@Override
55+
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
56+
lastOne.cancel(true);
57+
super.channelInactive(ctx);
4758
}
4859
}

java/test/org/openqa/selenium/netty/server/NettyServerTest.java

+43
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,20 @@
2828

2929
import com.google.common.collect.ImmutableMap;
3030
import java.net.URL;
31+
import java.time.Duration;
32+
import java.util.concurrent.CountDownLatch;
33+
import java.util.concurrent.TimeUnit;
3134
import java.util.concurrent.atomic.AtomicInteger;
35+
import org.junit.jupiter.api.Assertions;
3236
import org.junit.jupiter.api.Test;
37+
import org.openqa.selenium.TimeoutException;
3338
import org.openqa.selenium.grid.config.CompoundConfig;
3439
import org.openqa.selenium.grid.config.Config;
3540
import org.openqa.selenium.grid.config.MapConfig;
3641
import org.openqa.selenium.grid.server.BaseServerOptions;
3742
import org.openqa.selenium.grid.server.Server;
3843
import org.openqa.selenium.net.PortProber;
44+
import org.openqa.selenium.remote.http.ClientConfig;
3945
import org.openqa.selenium.remote.http.HttpClient;
4046
import org.openqa.selenium.remote.http.HttpRequest;
4147
import org.openqa.selenium.remote.http.HttpResponse;
@@ -141,6 +147,43 @@ void shouldNotBindToHost() {
141147
assertEquals("anyRandomHost", server.getUrl().getHost());
142148
}
143149

150+
@Test
151+
void doesInterruptPending() throws Exception {
152+
CountDownLatch interrupted = new CountDownLatch(1);
153+
Config cfg = new MapConfig(ImmutableMap.of());
154+
BaseServerOptions options = new BaseServerOptions(cfg);
155+
156+
Server<?> server =
157+
new NettyServer(
158+
options,
159+
req -> {
160+
try {
161+
Thread.sleep(800);
162+
} catch (InterruptedException ex) {
163+
interrupted.countDown();
164+
}
165+
return new HttpResponse();
166+
})
167+
.start();
168+
ClientConfig config =
169+
ClientConfig.defaultConfig()
170+
.readTimeout(Duration.ofMillis(400))
171+
.baseUri(server.getUrl().toURI());
172+
173+
// provoke a client timeout
174+
Assertions.assertThrows(
175+
TimeoutException.class,
176+
() -> {
177+
try (HttpClient client = HttpClient.Factory.createDefault().createClient(config)) {
178+
HttpRequest request = new HttpRequest(DELETE, "/session");
179+
request.setHeader("Accept", "*/*");
180+
client.execute(request);
181+
}
182+
});
183+
184+
assertTrue(interrupted.await(1000, TimeUnit.MILLISECONDS), "The handling was interrupted");
185+
}
186+
144187
private void outputHeaders(HttpResponse res) {
145188
res.forEachHeader((name, value) -> System.out.printf("%s -> %s\n", name, value));
146189
}

0 commit comments

Comments
 (0)