Skip to content

Commit

Permalink
Add slotMatcher parameter to node
Browse files Browse the repository at this point in the history
 and where DefaultSlotMatcher is used without alternatives
  • Loading branch information
bhecquet committed Jun 21, 2023
1 parent a04a22f commit 63a4d13
Show file tree
Hide file tree
Showing 23 changed files with 169 additions and 72 deletions.
3 changes: 2 additions & 1 deletion java/src/org/openqa/selenium/grid/commands/Hub.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ protected Handlers createHandlers(Config config) {
distributorOptions.getHealthCheckInterval(),
distributorOptions.shouldRejectUnsupportedCaps(),
newSessionRequestOptions.getSessionRequestRetryInterval(),
distributorOptions.getNewSessionThreadPoolSize());
distributorOptions.getNewSessionThreadPoolSize(),
distributorOptions.getSlotMatcher());
handler.addHandler(distributor);

Router router = new Router(tracer, clientFactory, sessions, queue, distributor);
Expand Down
3 changes: 2 additions & 1 deletion java/src/org/openqa/selenium/grid/commands/Standalone.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ protected Handlers createHandlers(Config config) {
distributorOptions.getHealthCheckInterval(),
distributorOptions.shouldRejectUnsupportedCaps(),
newSessionRequestOptions.getSessionRequestRetryInterval(),
distributorOptions.getNewSessionThreadPoolSize());
distributorOptions.getNewSessionThreadPoolSize(),
distributorOptions.getSlotMatcher());
combinedHandler.addHandler(distributor);

Routable router =
Expand Down
7 changes: 4 additions & 3 deletions java/src/org/openqa/selenium/grid/data/Slot.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.json.JsonInput;
import org.openqa.selenium.grid.data.SlotMatcher;

public class Slot implements Serializable {

Expand All @@ -37,12 +38,12 @@ public class Slot implements Serializable {
private final Instant lastStarted;
private final SlotMatcher slotMatcher;

public Slot(SlotId id, Capabilities stereotype, Instant lastStarted, Session session) {
public Slot(SlotId id, Capabilities stereotype, Instant lastStarted, Session session, SlotMatcher slotMatcher) {
this.id = Require.nonNull("Slot ID", id);
this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype));
this.lastStarted = Require.nonNull("Last started", lastStarted);
this.session = session;
this.slotMatcher = new DefaultSlotMatcher();
this.slotMatcher = slotMatcher;
}

private static Slot fromJson(JsonInput input) {
Expand Down Expand Up @@ -78,7 +79,7 @@ private static Slot fromJson(JsonInput input) {
}
input.endObject();

return new Slot(id, stereotype, lastStarted, session);
return new Slot(id, stereotype, lastStarted, session, new DefaultSlotMatcher());
}

private Map<String, Object> toJson() {
Expand Down
18 changes: 13 additions & 5 deletions java/src/org/openqa/selenium/grid/distributor/GridModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import org.openqa.selenium.grid.data.SessionClosedEvent;
import org.openqa.selenium.grid.data.Slot;
import org.openqa.selenium.grid.data.SlotId;
import org.openqa.selenium.grid.data.SlotMatcher;
import org.openqa.selenium.grid.data.DefaultSlotMatcher;
import org.openqa.selenium.grid.server.EventBusOptions;
import org.openqa.selenium.internal.Debug;
import org.openqa.selenium.internal.Require;
Expand All @@ -65,18 +67,22 @@ public class GridModel {
private final Map<NodeId, Instant> nodePurgeTimes = new ConcurrentHashMap<>();
private final Map<NodeId, Integer> nodeHealthCount = new ConcurrentHashMap<>();
private final EventBus events;
private final SlotMatcher slotMatcher;

public GridModel(EventBus events) {
public GridModel(EventBus events, SlotMatcher slotMatcher) {
this.events = Require.nonNull("Event bus", events);
this.slotMatcher = Require.nonNull("Slot matcher", slotMatcher);

this.events.addListener(NodeDrainStarted.listener(nodeId -> setAvailability(nodeId, DRAINING)));
this.events.addListener(SessionClosedEvent.listener(this::release));
}

public static GridModel create(Config config) {
EventBus bus = new EventBusOptions(config).getEventBus();
//SlotMatcher slotMatcher = new DistributorOptions(config).getSlotMatcher();
SlotMatcher slotMatcher = new DefaultSlotMatcher();

return new GridModel(bus);
return new GridModel(bus, slotMatcher);
}

public void add(NodeStatus node) {
Expand Down Expand Up @@ -381,7 +387,7 @@ public void release(SessionId id) {

if (id.equals(slot.getSession().getId())) {
Slot released =
new Slot(slot.getId(), slot.getStereotype(), slot.getLastStarted(), null);
new Slot(slot.getId(), slot.getStereotype(), slot.getLastStarted(), null, slotMatcher);
amend(node.getAvailability(), node, released);
return;
}
Expand All @@ -405,7 +411,8 @@ public void reserve(NodeStatus status, Slot slot) {
status.getExternalUri(),
slot.getStereotype(),
slot.getStereotype(),
now));
now),
slotMatcher);

amend(UP, status, reserved);
}
Expand Down Expand Up @@ -451,7 +458,8 @@ public void setSession(SlotId slotId, Session session) {
slot.getId(),
slot.getStereotype(),
session == null ? slot.getLastStarted() : session.getStartTime(),
session);
session,
slotMatcher);

amend(node.getAvailability(), node, updated);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.openqa.selenium.grid.data.SessionRequestCapability;
import org.openqa.selenium.grid.data.Slot;
import org.openqa.selenium.grid.data.SlotId;
import org.openqa.selenium.grid.data.SlotMatcher;
import org.openqa.selenium.grid.data.TraceSessionRequest;
import org.openqa.selenium.grid.distributor.Distributor;
import org.openqa.selenium.grid.distributor.GridModel;
Expand Down Expand Up @@ -179,7 +180,8 @@ public LocalDistributor(
Duration healthcheckInterval,
boolean rejectUnsupportedCaps,
Duration sessionRequestRetryInterval,
int newSessionThreadPoolSize) {
int newSessionThreadPoolSize,
SlotMatcher slotMatcher) {
super(tracer, clientFactory, registrationSecret);
this.tracer = Require.nonNull("Tracer", tracer);
this.bus = Require.nonNull("Event bus", bus);
Expand All @@ -189,7 +191,7 @@ public LocalDistributor(
this.slotSelector = Require.nonNull("Slot selector", slotSelector);
this.registrationSecret = Require.nonNull("Registration secret", registrationSecret);
this.healthcheckInterval = Require.nonNull("Health check interval", healthcheckInterval);
this.model = new GridModel(bus);
this.model = new GridModel(bus, slotMatcher);
this.nodes = new ConcurrentHashMap<>();
this.rejectUnsupportedCaps = rejectUnsupportedCaps;
Require.nonNull("Session request interval", sessionRequestRetryInterval);
Expand Down Expand Up @@ -263,7 +265,8 @@ public static Distributor create(Config config) {
distributorOptions.getHealthCheckInterval(),
distributorOptions.shouldRejectUnsupportedCaps(),
newSessionQueueOptions.getSessionRequestRetryInterval(),
distributorOptions.getNewSessionThreadPoolSize());
distributorOptions.getNewSessionThreadPoolSize(),
distributorOptions.getSlotMatcher());
}

@Override
Expand Down
10 changes: 10 additions & 0 deletions java/src/org/openqa/selenium/grid/node/config/NodeFlags.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_SESSION_TIMEOUT;
import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_USE_SELENIUM_MANAGER;
import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_VNC_ENV_VAR;
import static org.openqa.selenium.grid.node.config.NodeOptions.DEFAULT_SLOT_MATCHER;
import static org.openqa.selenium.grid.node.config.NodeOptions.NODE_SECTION;
import static org.openqa.selenium.grid.node.config.NodeOptions.OVERRIDE_MAX_SESSIONS;

Expand Down Expand Up @@ -68,6 +69,15 @@ public class NodeFlags implements HasRoles {
@ConfigValue(section = NODE_SECTION, name = "override-max-sessions", example = "false")
public Boolean overrideMaxSessions = OVERRIDE_MAX_SESSIONS;

@Parameter(
names = {"--slot-matcher"},
description =
"Full classname of non-default slot matcher to use. This is used to determine whether a"
+ " Node can support a particular session. The class provided here should be the same as the one"
+ " used for distributor options")
@ConfigValue(section = NODE_SECTION, name = "slot-matcher", example = DEFAULT_SLOT_MATCHER)
private String slotMatcher = DEFAULT_SLOT_MATCHER;

@Parameter(
names = {"--session-timeout"},
description =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.openqa.selenium.grid.config.ConfigException;
import org.openqa.selenium.grid.node.Node;
import org.openqa.selenium.grid.node.SessionFactory;
import org.openqa.selenium.grid.data.SlotMatcher;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.json.JsonOutput;
Expand All @@ -81,6 +82,8 @@ public class NodeOptions {
static final int DEFAULT_REGISTER_PERIOD = 120;
static final String DEFAULT_NODE_IMPLEMENTATION =
"org.openqa.selenium.grid.node.local.LocalNodeFactory";
static final String DEFAULT_SLOT_MATCHER =
"org.openqa.selenium.grid.data.DefaultSlotMatcher";
private static final Logger LOG = Logger.getLogger(NodeOptions.class.getName());
private static final Json JSON = new Json();
private static final Platform CURRENT_PLATFORM = Platform.getCurrent();
Expand Down Expand Up @@ -170,6 +173,11 @@ public Duration getRegisterCycle() {
return Duration.ofSeconds(seconds);
}

public SlotMatcher getSlotMatcher() {
return config.getClass(
NODE_SECTION, "slot-matcher", SlotMatcher.class, DEFAULT_SLOT_MATCHER);
}

public Duration getRegisterPeriod() {
// If the user sets 0 or less, we default to 1s.
int seconds =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ public Map<Capabilities, Collection<SessionFactory>> getDockerSessionFactories(
videoImage,
assetsPath,
networkName,
info.isPresent()));
info.isPresent(),
options.getSlotMatcher()));
}
LOG.info(
String.format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public DockerSessionFactory(
Image videoImage,
DockerAssetsPath assetsPath,
String networkName,
boolean runningInDocker) {
boolean runningInDocker,
SlotMatcher slotMatcher) {
this.tracer = Require.nonNull("Tracer", tracer);
this.clientFactory = Require.nonNull("HTTP client", clientFactory);
this.sessionTimeout = Require.nonNull("Session timeout", sessionTimeout);
Expand All @@ -129,7 +130,7 @@ public DockerSessionFactory(
this.videoImage = videoImage;
this.assetsPath = assetsPath;
this.runningInDocker = runningInDocker;
this.slotMatcher = new DefaultSlotMatcher();
this.slotMatcher = slotMatcher;
}

@Override
Expand Down
19 changes: 16 additions & 3 deletions java/src/org/openqa/selenium/grid/node/local/LocalNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
import org.openqa.selenium.grid.data.Session;
import org.openqa.selenium.grid.data.Slot;
import org.openqa.selenium.grid.data.SlotId;
import org.openqa.selenium.grid.data.SlotMatcher;
import org.openqa.selenium.grid.data.DefaultSlotMatcher;
import org.openqa.selenium.grid.jmx.JMXHelper;
import org.openqa.selenium.grid.jmx.ManagedAttribute;
import org.openqa.selenium.grid.jmx.ManagedService;
Expand Down Expand Up @@ -119,6 +121,7 @@ public class LocalNode extends Node {
private static final Logger LOG = Logger.getLogger(LocalNode.class.getName());

private final EventBus bus;
private final SlotMatcher slotMatcher;
private final URI externalUri;
private final URI gridUri;
private final Duration heartbeatPeriod;
Expand Down Expand Up @@ -153,7 +156,8 @@ protected LocalNode(
Duration heartbeatPeriod,
List<SessionSlot> factories,
Secret registrationSecret,
boolean managedDownloadsEnabled) {
boolean managedDownloadsEnabled,
SlotMatcher slotMatcher) {
super(tracer, new NodeId(UUID.randomUUID()), uri, registrationSecret);

this.bus = Require.nonNull("Event bus", bus);
Expand All @@ -171,6 +175,7 @@ protected LocalNode(
this.cdpEnabled = cdpEnabled;
this.bidiEnabled = bidiEnabled;
this.managedDownloadsEnabled = managedDownloadsEnabled;
this.slotMatcher = slotMatcher;

this.healthCheck =
healthCheck == null
Expand Down Expand Up @@ -855,7 +860,8 @@ public NodeStatus getStatus() {
new SlotId(getId(), slot.getId()),
slot.getStereotype(),
lastStarted,
session);
session,
slotMatcher);
})
.collect(toImmutableSet());

Expand Down Expand Up @@ -940,6 +946,7 @@ public static class Builder {
private HealthCheck healthCheck;
private Duration heartbeatPeriod = Duration.ofSeconds(NodeOptions.DEFAULT_HEARTBEAT_PERIOD);
private boolean managedDownloadsEnabled = false;
private SlotMatcher slotMatcher = new DefaultSlotMatcher();

private Builder(Tracer tracer, EventBus bus, URI uri, URI gridUri, Secret registrationSecret) {
this.tracer = Require.nonNull("Tracer", tracer);
Expand Down Expand Up @@ -994,6 +1001,11 @@ public Builder enableManagedDownloads(boolean enable) {
return this;
}

public Builder slotMatcher(SlotMatcher slotMatcher) {
this.slotMatcher = slotMatcher;
return this;
}

public LocalNode build() {
return new LocalNode(
tracer,
Expand All @@ -1010,7 +1022,8 @@ public LocalNode build() {
heartbeatPeriod,
factories.build(),
registrationSecret,
managedDownloadsEnabled);
managedDownloadsEnabled,
slotMatcher);
}

public Advanced advanced() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ public static Node create(Config config) {
.enableCdp(nodeOptions.isCdpEnabled())
.enableBiDi(nodeOptions.isBiDiEnabled())
.enableManagedDownloads(nodeOptions.isManagedDownloadsEnabled())
.heartbeatPeriod(nodeOptions.getHeartbeatPeriod());
.heartbeatPeriod(nodeOptions.getHeartbeatPeriod())
.slotMatcher(nodeOptions.getSlotMatcher());

List<DriverService.Builder<?, ?>> builders = new ArrayList<>();
ServiceLoader.load(DriverService.Builder.class).forEach(builders::add);

nodeOptions
.getSessionFactories(
caps -> createSessionFactory(tracer, clientFactory, sessionTimeout, builders, caps))
caps -> createSessionFactory(tracer, clientFactory, sessionTimeout, builders, caps, nodeOptions.getSlotMatcher()))
.forEach((caps, factories) -> factories.forEach(factory -> builder.add(caps, factory)));

if (config.getAll("docker", "configs").isPresent()) {
Expand All @@ -101,9 +102,9 @@ private static Collection<SessionFactory> createSessionFactory(
HttpClient.Factory clientFactory,
Duration sessionTimeout,
List<DriverService.Builder<?, ?>> builders,
Capabilities stereotype) {
Capabilities stereotype,
SlotMatcher slotMatcher) {
ImmutableList.Builder<SessionFactory> toReturn = ImmutableList.builder();
SlotMatcher slotMatcher = new DefaultSlotMatcher();
String webDriverExecutablePath =
String.valueOf(stereotype.asMap().getOrDefault("se:webDriverExecutable", ""));

Expand Down
Loading

0 comments on commit 63a4d13

Please sign in to comment.