Skip to content

Commit c34fc94

Browse files
committed
Revert "[grid] close HttpClients after the session is gone #12558"
This reverts commit e8c77b8.
1 parent f6e5471 commit c34fc94

File tree

1 file changed

+20
-65
lines changed

1 file changed

+20
-65
lines changed

java/src/org/openqa/selenium/grid/router/HandleSession.java

Lines changed: 20 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,19 @@
2626
import static org.openqa.selenium.remote.tracing.Tags.HTTP_REQUEST_EVENT;
2727
import static org.openqa.selenium.remote.tracing.Tags.HTTP_RESPONSE;
2828

29+
import com.google.common.cache.Cache;
30+
import com.google.common.cache.CacheBuilder;
31+
import com.google.common.cache.RemovalListener;
2932
import com.google.common.collect.ImmutableMap;
3033
import java.net.URL;
31-
import java.time.Instant;
32-
import java.time.temporal.ChronoUnit;
33-
import java.util.Iterator;
34+
import java.time.Duration;
3435
import java.util.concurrent.Callable;
35-
import java.util.concurrent.ConcurrentHashMap;
36-
import java.util.concurrent.ConcurrentMap;
3736
import java.util.concurrent.Executors;
3837
import java.util.concurrent.ScheduledExecutorService;
3938
import java.util.concurrent.TimeUnit;
40-
import java.util.logging.Level;
41-
import java.util.logging.Logger;
4239
import org.openqa.selenium.NoSuchSessionException;
4340
import org.openqa.selenium.concurrent.GuardedRunnable;
41+
import org.openqa.selenium.grid.data.Session;
4442
import org.openqa.selenium.grid.sessionmap.SessionMap;
4543
import org.openqa.selenium.grid.web.ReverseProxyHandler;
4644
import org.openqa.selenium.internal.Require;
@@ -60,60 +58,24 @@
6058

6159
class HandleSession implements HttpHandler {
6260

63-
private static final Logger LOG = Logger.getLogger(HandleSession.class.getName());
64-
65-
private static class CacheEntry {
66-
private final SessionId sessionId;
67-
private final HttpClient httpClient;
68-
// volatile as the ConcurrentMap will not take care of synchronization
69-
private volatile Instant lastUse;
70-
71-
public CacheEntry(SessionId sessionId, HttpClient httpClient) {
72-
this.sessionId = sessionId;
73-
this.httpClient = httpClient;
74-
this.lastUse = Instant.now();
75-
}
76-
}
77-
7861
private final Tracer tracer;
7962
private final HttpClient.Factory httpClientFactory;
8063
private final SessionMap sessions;
81-
private final ConcurrentMap<URL, CacheEntry> httpClients;
64+
private final Cache<URL, HttpClient> httpClients;
8265

8366
HandleSession(Tracer tracer, HttpClient.Factory httpClientFactory, SessionMap sessions) {
8467
this.tracer = Require.nonNull("Tracer", tracer);
8568
this.httpClientFactory = Require.nonNull("HTTP client factory", httpClientFactory);
8669
this.sessions = Require.nonNull("Sessions", sessions);
8770

88-
this.httpClients = new ConcurrentHashMap<>();
89-
90-
Runnable cleanUpHttpClients =
91-
() -> {
92-
Instant revalidateBefore = Instant.now().minus(1, ChronoUnit.MINUTES);
93-
Iterator<CacheEntry> iterator = httpClients.values().iterator();
94-
95-
while (iterator.hasNext()) {
96-
CacheEntry entry = iterator.next();
97-
98-
if (!entry.lastUse.isBefore(revalidateBefore)) {
99-
// the session was recently used
100-
return;
101-
}
102-
103-
try {
104-
sessions.get(entry.sessionId);
105-
} catch (NoSuchSessionException e) {
106-
// the session is dead, remove it from the cache
107-
iterator.remove();
108-
109-
try {
110-
entry.httpClient.close();
111-
} catch (Exception ex) {
112-
LOG.log(Level.WARNING, "failed to close a stale httpclient", ex);
113-
}
114-
}
115-
}
116-
};
71+
this.httpClients =
72+
CacheBuilder.newBuilder()
73+
// this timeout must be bigger than default connection + read timeout, to ensure we do
74+
// not close HttpClients which might have requests waiting for responses
75+
.expireAfterAccess(Duration.ofMinutes(4))
76+
.removalListener(
77+
(RemovalListener<URL, HttpClient>) removal -> removal.getValue().close())
78+
.build();
11779

11880
ScheduledExecutorService cleanUpHttpClientsCacheService =
11981
Executors.newSingleThreadScheduledExecutor(
@@ -124,7 +86,7 @@ public CacheEntry(SessionId sessionId, HttpClient httpClient) {
12486
return thread;
12587
});
12688
cleanUpHttpClientsCacheService.scheduleAtFixedRate(
127-
GuardedRunnable.guard(cleanUpHttpClients), 1, 1, TimeUnit.MINUTES);
89+
GuardedRunnable.guard(httpClients::cleanUp), 1, 1, TimeUnit.MINUTES);
12890
}
12991

13092
@Override
@@ -203,18 +165,11 @@ public HttpResponse execute(HttpRequest req) {
203165
private Callable<HttpHandler> loadSessionId(Tracer tracer, Span span, SessionId id) {
204166
return span.wrap(
205167
() -> {
206-
CacheEntry cacheEntry =
207-
httpClients.computeIfAbsent(
208-
Urls.fromUri(sessions.getUri(id)),
209-
(sessionUrl) -> {
210-
ClientConfig config =
211-
ClientConfig.defaultConfig().baseUrl(sessionUrl).withRetries();
212-
HttpClient httpClient = httpClientFactory.createClient(config);
213-
214-
return new CacheEntry(id, httpClient);
215-
});
216-
cacheEntry.lastUse = Instant.now();
217-
return new ReverseProxyHandler(tracer, cacheEntry.httpClient);
168+
Session session = sessions.get(id);
169+
URL url = Urls.fromUri(session.getUri());
170+
ClientConfig config = ClientConfig.defaultConfig().baseUrl(url).withRetries();
171+
HttpClient client = httpClients.get(url, () -> httpClientFactory.createClient(config));
172+
return new ReverseProxyHandler(tracer, client);
218173
});
219174
}
220175
}

0 commit comments

Comments
 (0)