Skip to content

Commit 9b42f09

Browse files
bhecquetdiemol
andauthored
Prevent grid from creating sessions that are about to timeout in queue (corrects issue #11881) (#12014)
* Add logs * add more logs * Control the status of session request before timeout * Increase request session timeout by 5 seconds This allow the extended waiting to be done without being interrupted by timeoutSessions() method * remove logs LocalNewSessionQueue.java * remove logs * remove logger import * Add tests to check timeout behaviour * timeoutSessions method now checks if session is in queue before deleting it --------- Co-authored-by: Diego Molina <[email protected]>
1 parent 0f8a922 commit 9b42f09

File tree

2 files changed

+144
-8
lines changed

2 files changed

+144
-8
lines changed

java/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,16 @@ private void timeoutSessions() {
164164
readLock.lock();
165165
Set<RequestId> ids;
166166
try {
167-
ids =
168-
requests.entrySet().stream()
169-
.filter(entry -> isTimedOut(now, entry.getValue()))
170-
.map(Map.Entry::getKey)
171-
.collect(ImmutableSet.toImmutableSet());
167+
ids = requests.entrySet().stream()
168+
.filter(
169+
entry ->
170+
queue.stream()
171+
.anyMatch(
172+
sessionRequest ->
173+
sessionRequest.getRequestId().equals(entry.getKey())))
174+
.filter(entry -> isTimedOut(now, entry.getValue()))
175+
.map(Map.Entry::getKey)
176+
.collect(ImmutableSet.toImmutableSet());
172177
} finally {
173178
readLock.unlock();
174179
}
@@ -187,7 +192,6 @@ public HttpResponse addToQueue(SessionRequest request) {
187192
TraceContext context = TraceSessionRequest.extract(tracer, request);
188193
try (Span ignored = context.createSpan("sessionqueue.add_to_queue")) {
189194
contexts.put(request.getRequestId(), context);
190-
191195
Data data = injectIntoQueue(request);
192196

193197
if (isTimedOut(Instant.now(), data)) {
@@ -196,7 +200,13 @@ public HttpResponse addToQueue(SessionRequest request) {
196200

197201
Either<SessionNotCreatedException, CreateSessionResponse> result;
198202
try {
199-
if (data.latch.await(requestTimeout.toMillis(), MILLISECONDS)) {
203+
204+
boolean sessionCreated = data.latch.await(requestTimeout.toMillis(), MILLISECONDS);
205+
if (!(sessionCreated || isRequestInQueue(request.getRequestId()))) {
206+
sessionCreated = data.latch.await(5000, MILLISECONDS);
207+
}
208+
209+
if (sessionCreated) {
200210
result = data.result;
201211
} else {
202212
result = Either.left(new SessionNotCreatedException("New session request timed out"));
@@ -308,6 +318,20 @@ public Optional<SessionRequest> remove(RequestId reqId) {
308318
}
309319
}
310320

321+
private boolean isRequestInQueue(RequestId requestId) {
322+
Lock readLock = lock.readLock();
323+
readLock.lock();
324+
325+
try {
326+
Optional<SessionRequest> result = queue.stream()
327+
.filter(req -> req.getRequestId().equals(requestId))
328+
.findAny();
329+
return result.isPresent();
330+
} finally {
331+
readLock.unlock();
332+
}
333+
}
334+
311335
@Override
312336
public List<SessionRequest> getNextAvailable(Map<Capabilities, Long> stereotypes) {
313337
Require.nonNull("Stereotypes", stereotypes);

java/test/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueueTest.java

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ private void waitUntilAddedToQueue(SessionRequest request) {
170170
@MethodSource("data")
171171
void shouldBeAbleToAddToQueueAndGetValidResponse(Supplier<TestData> supplier) {
172172
setup(supplier);
173-
173+
174174
AtomicBoolean isPresent = new AtomicBoolean(false);
175175

176176
new Thread(
@@ -207,6 +207,118 @@ void shouldBeAbleToAddToQueueAndGetValidResponse(Supplier<TestData> supplier) {
207207
assertThat(isPresent.get()).isTrue();
208208
assertEquals(HTTP_OK, httpResponse.getStatus());
209209
}
210+
211+
212+
@ParameterizedTest
213+
@MethodSource("data")
214+
void shouldBeAbleToAddToQueueWithTimeoutAndGetValidResponse(Supplier<TestData> supplier) {
215+
setup(supplier);
216+
217+
SessionRequest sessionRequestWithTimeout = new SessionRequest(
218+
new RequestId(UUID.randomUUID()),
219+
Instant.now(),
220+
Set.of(W3C),
221+
Set.of(CAPS),
222+
Map.of(),
223+
Map.of());
224+
225+
AtomicBoolean isPresent = new AtomicBoolean(false);
226+
227+
new Thread(() -> {
228+
waitUntilAddedToQueue(sessionRequestWithTimeout);
229+
isPresent.set(true);
230+
231+
Capabilities capabilities = new ImmutableCapabilities("browserName", "chrome");
232+
233+
try {
234+
Thread.sleep(4000); // simulate session waiting in queue
235+
} catch (InterruptedException e) {}
236+
237+
// remove request from queue
238+
Map<Capabilities, Long> stereotypes = new HashMap<>();
239+
stereotypes.put(new ImmutableCapabilities("browserName", "cheese"), 1L);
240+
List<SessionRequest> requests = queue.getNextAvailable(stereotypes);
241+
242+
SessionId sessionId = new SessionId("123");
243+
Session session =
244+
new Session(
245+
sessionId,
246+
URI.create("https://example.com"),
247+
CAPS,
248+
capabilities,
249+
Instant.now());
250+
CreateSessionResponse sessionResponse = new CreateSessionResponse(
251+
session,
252+
JSON.toJson(
253+
ImmutableMap.of(
254+
"value", ImmutableMap.of(
255+
"sessionId", sessionId,
256+
"capabilities", capabilities)))
257+
.getBytes(UTF_8));
258+
259+
try {
260+
Thread.sleep(2000); // simulate session creation delay
261+
} catch (InterruptedException e) {}
262+
queue.complete(sessionRequestWithTimeout.getRequestId(), Either.right(sessionResponse));
263+
}).start();
264+
265+
HttpResponse httpResponse = queue.addToQueue(sessionRequestWithTimeout);
266+
267+
assertThat(isPresent.get()).isTrue();
268+
assertEquals(HTTP_OK, httpResponse.getStatus());
269+
}
270+
271+
272+
@ParameterizedTest
273+
@MethodSource("data")
274+
void shouldBeAbleToAddToQueueWithTimeoutAndTimeoutResponse(Supplier<TestData> supplier) {
275+
setup(supplier);
276+
277+
SessionRequest sessionRequestWithTimeout = new SessionRequest(
278+
new RequestId(UUID.randomUUID()),
279+
Instant.now(),
280+
Set.of(W3C),
281+
Set.of(CAPS),
282+
Map.of(),
283+
Map.of());
284+
285+
AtomicBoolean isPresent = new AtomicBoolean(false);
286+
287+
new Thread(() -> {
288+
waitUntilAddedToQueue(sessionRequestWithTimeout);
289+
isPresent.set(true);
290+
291+
Capabilities capabilities = new ImmutableCapabilities("browserName", "chrome");
292+
293+
try {
294+
Thread.sleep(5500); // simulate session waiting in queue
295+
} catch (InterruptedException e) {}
296+
297+
SessionId sessionId = new SessionId("123");
298+
Session session =
299+
new Session(
300+
sessionId,
301+
URI.create("https://example.com"),
302+
CAPS,
303+
capabilities,
304+
Instant.now());
305+
CreateSessionResponse sessionResponse = new CreateSessionResponse(
306+
session,
307+
JSON.toJson(
308+
ImmutableMap.of(
309+
"value", ImmutableMap.of(
310+
"sessionId", sessionId,
311+
"capabilities", capabilities)))
312+
.getBytes(UTF_8));
313+
314+
queue.complete(sessionRequestWithTimeout.getRequestId(), Either.right(sessionResponse));
315+
}).start();
316+
317+
HttpResponse httpResponse = queue.addToQueue(sessionRequestWithTimeout);
318+
319+
assertThat(isPresent.get()).isTrue();
320+
assertEquals(HTTP_INTERNAL_ERROR, httpResponse.getStatus());
321+
}
210322

211323
@ParameterizedTest
212324
@MethodSource("data")

0 commit comments

Comments
 (0)