Skip to content

Commit

Permalink
[grid] improved the new session handling when the queue is empty (#12385
Browse files Browse the repository at this point in the history
)

Co-authored-by: Diego Molina <diemol@users.noreply.github.com>
  • Loading branch information
joerg1985 and diemol committed Jul 21, 2023
1 parent ee32f22 commit b22d08d
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 24 deletions.
17 changes: 1 addition & 16 deletions java/src/org/openqa/selenium/ImmutableCapabilities.java
Expand Up @@ -135,22 +135,7 @@ public ImmutableCapabilities(
}

public ImmutableCapabilities(Capabilities other) {
Require.nonNull("Capabilities", other);

Map<String, Object> delegate = new TreeMap<>();
other
.getCapabilityNames()
.forEach(
name -> {
Require.nonNull("Capability name", name);
Object value = other.getCapability(name);
Require.nonNull("Capability value", value);

setCapability(delegate, name, value);
});

this.delegate = Collections.unmodifiableMap(delegate);
this.hashCode = SharedCapabilitiesMethods.hashCode(this);
this(other.asMap());
}

public ImmutableCapabilities(Map<?, ?> capabilities) {
Expand Down
Expand Up @@ -762,7 +762,7 @@ public void run() {
loop = !inQueue.isEmpty();
} else {
inQueue = null;
loop = true;
loop = !sessionQueue.peekEmpty();
}
while (loop) {
// We deliberately run this outside of a lock: if we're unsuccessful
Expand Down
13 changes: 8 additions & 5 deletions java/src/org/openqa/selenium/grid/node/config/NodeOptions.java
Expand Up @@ -46,6 +46,7 @@
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.PersistentCapabilities;
import org.openqa.selenium.Platform;
import org.openqa.selenium.SessionNotCreatedException;
Expand Down Expand Up @@ -190,7 +191,7 @@ public Duration getHeartbeatPeriod() {

public Map<Capabilities, Collection<SessionFactory>> getSessionFactories(
/* Danger! Java stereotype ahead! */
Function<Capabilities, Collection<SessionFactory>> factoryFactory) {
Function<ImmutableCapabilities, Collection<SessionFactory>> factoryFactory) {

LOG.log(Level.INFO, "Detected {0} available processors", DEFAULT_MAX_SESSIONS);
boolean overrideMaxSessions =
Expand Down Expand Up @@ -336,7 +337,7 @@ private SessionFactory createSessionFactory(String clazz, Capabilities stereotyp
}

private void addDriverConfigs(
Function<Capabilities, Collection<SessionFactory>> factoryFactory,
Function<ImmutableCapabilities, Collection<SessionFactory>> factoryFactory,
ImmutableMultimap.Builder<Capabilities, SessionFactory> sessionFactories) {
Multimap<WebDriverInfo, SessionFactory> driverConfigs = HashMultimap.create();
config
Expand Down Expand Up @@ -459,10 +460,11 @@ private void addDriverConfigs(
.max(Comparator.comparingInt(builder -> builder.score(stereotype)))
.ifPresent(
builder -> {
ImmutableCapabilities immutable = new ImmutableCapabilities(stereotype);
int maxDriverSessions = getDriverMaxSessions(info, driverMaxSessions);
for (int i = 0; i < maxDriverSessions; i++) {
driverConfigs.putAll(
driverInfoConfig, factoryFactory.apply(stereotype));
driverInfoConfig, factoryFactory.apply(immutable));
}
});
});
Expand Down Expand Up @@ -554,7 +556,7 @@ private void addSpecificDrivers(
}

private Map<WebDriverInfo, Collection<SessionFactory>> discoverDrivers(
int maxSessions, Function<Capabilities, Collection<SessionFactory>> factoryFactory) {
int maxSessions, Function<ImmutableCapabilities, Collection<SessionFactory>> factoryFactory) {

if (!config.getBool(NODE_SECTION, "detect-drivers").orElse(DEFAULT_DETECT_DRIVERS)) {
return ImmutableMap.of();
Expand Down Expand Up @@ -595,9 +597,10 @@ private Map<WebDriverInfo, Collection<SessionFactory>> discoverDrivers(
.max(Comparator.comparingInt(builder -> builder.score(caps)))
.ifPresent(
builder -> {
ImmutableCapabilities immutable = new ImmutableCapabilities(caps);
int maxDriverSessions = getDriverMaxSessions(info, maxSessions);
for (int i = 0; i < maxDriverSessions; i++) {
toReturn.putAll(info, factoryFactory.apply(caps));
toReturn.putAll(info, factoryFactory.apply(immutable));
}
});
});
Expand Down
Expand Up @@ -25,7 +25,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.grid.config.Config;
import org.openqa.selenium.grid.data.DefaultSlotMatcher;
import org.openqa.selenium.grid.data.SlotMatcher;
Expand Down Expand Up @@ -101,7 +101,7 @@ private static Collection<SessionFactory> createSessionFactory(
HttpClient.Factory clientFactory,
Duration sessionTimeout,
List<DriverService.Builder<?, ?>> builders,
Capabilities stereotype) {
ImmutableCapabilities stereotype) {
ImmutableList.Builder<SessionFactory> toReturn = ImmutableList.builder();
SlotMatcher slotMatcher = new DefaultSlotMatcher();
String webDriverExecutablePath =
Expand Down
Expand Up @@ -96,6 +96,13 @@ private RequestId requestIdFrom(Map<String, String> params) {
return new RequestId(UUID.fromString(params.get("requestId")));
}

/**
* A fast-path to detect if the queue is empty, returns false if there is no fast-path available.
*
* @return true if the queue is empty, false if it is not empty or unknown
*/
public abstract boolean peekEmpty();

public abstract HttpResponse addToQueue(SessionRequest request);

public abstract boolean retryAddToQueue(SessionRequest request);
Expand Down
Expand Up @@ -185,6 +185,17 @@ private boolean isTimedOut(Instant now, Data data) {
return data.endTime.isBefore(now);
}

@Override
public boolean peekEmpty() {
Lock readLock = lock.readLock();
readLock.lock();
try {
return requests.isEmpty() && queue.isEmpty() ;
} finally {
readLock.unlock();
}
}

@Override
public HttpResponse addToQueue(SessionRequest request) {
Require.nonNull("New session request", request);
Expand Down
Expand Up @@ -90,6 +90,12 @@ public static NewSessionQueue create(Config config) {
}
}

@Override
public boolean peekEmpty() {
// we have no fast-path, assume we might be not empty
return false;
}

@Override
public HttpResponse addToQueue(SessionRequest request) {
HttpRequest upstream = new HttpRequest(POST, "/se/grid/newsessionqueue/session");
Expand Down

0 comments on commit b22d08d

Please sign in to comment.