Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d18f79f
Add logs
bhecquet Sep 28, 2023
5e023c7
Prevent a session to be created while its timeout has expired
bhecquet Sep 28, 2023
26976c2
restore missing "remove"
bhecquet Sep 29, 2023
62de717
Close timedout session on creation to prevent them to be staled
bhecquet Sep 29, 2023
0b8b6a4
Correct stopping of expired sessions
bhecquet Sep 29, 2023
868d9e2
Remove logs for final commit
bhecquet Oct 2, 2023
1b1e061
Merge branch 'SeleniumHQ:trunk' into driver_sessions_staled
bhecquet Oct 2, 2023
18a706e
removed a test that is now useless as request session timeout is now …
bhecquet Oct 2, 2023
2d5efbb
Merge branch 'driver_sessions_staled' of https://github.com/bhecquet/…
bhecquet Oct 2, 2023
19d823c
Simplify session stopping if timeout expires
bhecquet Oct 2, 2023
2c84bee
Add some tests
bhecquet Oct 2, 2023
7adaac9
remove logs
bhecquet Oct 2, 2023
40ae455
Return value directly
bhecquet Oct 3, 2023
89d9851
remove unused method
bhecquet Oct 3, 2023
944618c
Removed hard coded value
bhecquet Oct 3, 2023
37c23aa
correct according to comments
bhecquet Oct 4, 2023
708da75
Correct according to comments
bhecquet Oct 4, 2023
3d09867
Remove spaces
bhecquet Oct 4, 2023
0afa089
remove spaces
bhecquet Oct 4, 2023
93fc4f0
Remove unused import
bhecquet Oct 4, 2023
5a80fcd
Add comments to tell why session is valid
bhecquet Oct 6, 2023
f1dbec8
Merge branch 'driver_sessions_staled' of https://github.com/bhecquet/…
bhecquet Oct 6, 2023
e3d4296
fix linter issues
titusfortner Oct 6, 2023
9af02d4
Add a test when session time out
bhecquet Oct 11, 2023
6185818
test improved
bhecquet Oct 11, 2023
c8e122a
Merge branch 'trunk' into driver_sessions_staled
diemol Oct 17, 2023
91503bb
Merge branch 'trunk' into driver_sessions_staled
diemol Oct 17, 2023
9129264
Running format script
diemol Oct 17, 2023
b81fc7f
Merge branch 'trunk' into driver_sessions_staled
diemol Oct 17, 2023
7d2def6
Merge branch 'trunk' into driver_sessions_staled
diemol Oct 18, 2023
b41ac69
Merge branch 'trunk' into driver_sessions_staled
diemol Oct 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -838,8 +839,42 @@ private void handleNewSessionRequest(SessionRequest sessionRequest) {
}
}

sessionQueue.complete(reqId, response);
// 'complete' will return 'true' if the session has not timed out during the creation
// process: it's still a valid session as it can be used by the client
boolean isSessionValid = sessionQueue.complete(reqId, response);
// If the session request has timed out, tell the Node to remove the session, so that does
// not stall
if (!isSessionValid && response.isRight()) {
LOG.log(
Debug.getDebugLogLevel(),
"Session for request {0} has been created but it has timed out, stopping it to avoid"
+ " stalled browser",
reqId.toString());
URI nodeURI = response.right().getSession().getUri();
Node node = getNodeFromURI(nodeURI);
if (node != null) {
node.stop(response.right().getSession().getId());
}
}
}
}
}

protected Node getNodeFromURI(URI uri) {
Lock readLock = this.lock.readLock();
readLock.lock();
try {
Optional<NodeStatus> nodeStatus =
model.getSnapshot().stream()
.filter(node -> node.getExternalUri().equals(uri))
.findFirst();
if (nodeStatus.isPresent()) {
return nodes.get(nodeStatus.get().getNodeId());
} else {
return null;
}
} finally {
readLock.unlock();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private RequestId requestIdFrom(Map<String, String> params) {

public abstract List<SessionRequest> getNextAvailable(Map<Capabilities, Long> stereotypes);

public abstract void complete(
public abstract boolean complete(
RequestId reqId, Either<SessionNotCreatedException, CreateSessionResponse> result);

public abstract int clearQueue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.openqa.selenium.grid.sessionqueue;

import static java.util.Collections.singletonMap;
import static org.openqa.selenium.remote.http.Contents.asJson;
import static org.openqa.selenium.remote.tracing.HttpTracing.newSpanAsChildOf;
import static org.openqa.selenium.remote.tracing.Tags.HTTP_REQUEST;
import static org.openqa.selenium.remote.tracing.Tags.HTTP_RESPONSE;
Expand Down Expand Up @@ -50,9 +52,14 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException {
HTTP_REQUEST.accept(span, req);

CreateSessionResponse response = Contents.fromJson(req, CreateSessionResponse.class);
queue.complete(requestId, Either.right(response));

HttpResponse res = new HttpResponse();
// 'complete' will return 'true' if the session has not timed out during the creation process:
// it's still a valid session as it can be used by the client
boolean isSessionValid = queue.complete(requestId, Either.right(response));

HttpResponse res =
new HttpResponse().setContent(asJson(singletonMap("value", isSessionValid)));

HTTP_RESPONSE.accept(span, res);
return res;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.openqa.selenium.grid.sessionqueue;

import static java.util.Collections.singletonMap;
import static org.openqa.selenium.remote.http.Contents.asJson;
import static org.openqa.selenium.remote.tracing.HttpTracing.newSpanAsChildOf;
import static org.openqa.selenium.remote.tracing.Tags.HTTP_REQUEST;
import static org.openqa.selenium.remote.tracing.Tags.HTTP_RESPONSE;
Expand Down Expand Up @@ -52,9 +54,13 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException {

String message = Contents.fromJson(req, String.class);
SessionNotCreatedException exception = new SessionNotCreatedException(message);
queue.complete(requestId, Either.left(exception));

HttpResponse res = new HttpResponse();
// 'complete' will return 'true' if the session has not timed out during the creation process:
// it's still a valid session as it can be used by the client
boolean isSessionValid = queue.complete(requestId, Either.left(exception));

HttpResponse res =
new HttpResponse().setContent(asJson(singletonMap("value", isSessionValid)));
HTTP_RESPONSE.accept(span, res);
return res;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,6 @@ public HttpResponse addToQueue(SessionRequest request) {
try {

boolean sessionCreated = data.latch.await(requestTimeout.toMillis(), MILLISECONDS);
if (!(sessionCreated || isRequestInQueue(request.getRequestId()))) {
sessionCreated = data.latch.await(5000, MILLISECONDS);
}

if (sessionCreated) {
result = data.result;
Expand Down Expand Up @@ -293,6 +290,12 @@ public boolean retryAddToQueue(SessionRequest request) {
if (!requests.containsKey(request.getRequestId())) {
return false;
}
if (isTimedOut(Instant.now(), requests.get(request.getRequestId()))) {
// as we try to re-add a session request that has already expired, force session timeout
failDueToTimeout(request.getRequestId());
// return true to avoid handleNewSessionRequest to call 'complete' an other time
return true;
}

if (queue.contains(request)) {
// No need to re-add this
Expand Down Expand Up @@ -330,19 +333,6 @@ public Optional<SessionRequest> remove(RequestId reqId) {
}
}

private boolean isRequestInQueue(RequestId requestId) {
Lock readLock = lock.readLock();
readLock.lock();

try {
Optional<SessionRequest> result =
queue.stream().filter(req -> req.getRequestId().equals(requestId)).findAny();
return result.isPresent();
} finally {
readLock.unlock();
}
}

@Override
public List<SessionRequest> getNextAvailable(Map<Capabilities, Long> stereotypes) {
Require.nonNull("Stereotypes", stereotypes);
Expand Down Expand Up @@ -378,8 +368,9 @@ public List<SessionRequest> getNextAvailable(Map<Capabilities, Long> stereotypes
}
}

/** Returns true if the session is still valid (not timed out) */
@Override
public void complete(
public boolean complete(
RequestId reqId, Either<SessionNotCreatedException, CreateSessionResponse> result) {
Require.nonNull("New session request", reqId);
Require.nonNull("Result", result);
Expand All @@ -388,14 +379,17 @@ public void complete(
Lock readLock = lock.readLock();
readLock.lock();
Data data;
boolean isSessionTimedOut = false;
try {
data = requests.get(reqId);
} finally {
readLock.unlock();
}

if (data == null) {
return;
return false;
} else {
isSessionTimedOut = isTimedOut(Instant.now(), data);
}

Lock writeLock = lock.writeLock();
Expand All @@ -409,6 +403,8 @@ public void complete(
}

data.setResult(result);

return !isSessionTimedOut;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public List<SessionRequest> getNextAvailable(Map<Capabilities, Long> stereotypes
}

@Override
public void complete(
public boolean complete(
RequestId reqId, Either<SessionNotCreatedException, CreateSessionResponse> result) {
Require.nonNull("Request ID", reqId);
Require.nonNull("Result", result);
Expand All @@ -171,7 +171,8 @@ public void complete(
}

HttpTracing.inject(tracer, tracer.getCurrentContext(), upstream);
client.with(addSecret).execute(upstream);
HttpResponse response = client.with(addSecret).execute(upstream);
return Values.get(response, Boolean.class);
}

@Override
Expand Down
Loading