Skip to content

Commit 2fd24ae

Browse files
committed
[grid] Pinging relay service to update healthcheck
Fixes #10011
1 parent 9c95b92 commit 2fd24ae

4 files changed

Lines changed: 65 additions & 13 deletions

File tree

java/src/org/openqa/selenium/grid/node/local/LocalNode.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.openqa.selenium.grid.node.local;
1919

2020
import static com.google.common.collect.ImmutableSet.toImmutableSet;
21+
import static org.openqa.selenium.grid.data.Availability.DOWN;
2122
import static org.openqa.selenium.grid.data.Availability.DRAINING;
2223
import static org.openqa.selenium.grid.data.Availability.UP;
2324
import static org.openqa.selenium.grid.node.CapabilityResponseEncoder.getEncoder;
@@ -93,6 +94,7 @@
9394
import java.util.HashMap;
9495
import java.util.List;
9596
import java.util.Map;
97+
import java.util.Optional;
9698
import java.util.Set;
9799
import java.util.UUID;
98100
import java.util.concurrent.ExecutionException;
@@ -144,10 +146,12 @@ private LocalNode(
144146
Require.nonNull("Registration secret", registrationSecret);
145147

146148
this.healthCheck = healthCheck == null ?
147-
() -> new HealthCheck.Result(
148-
isDraining() ? DRAINING : UP,
149-
String.format("%s is %s", uri, isDraining() ? "draining" : "up")) :
150-
healthCheck;
149+
() -> {
150+
NodeStatus status = getStatus();
151+
return new HealthCheck.Result(
152+
status.getAvailability(),
153+
String.format("%s is %s", uri, status.getAvailability()));
154+
} : healthCheck;
151155

152156
this.currentSessions = CacheBuilder.newBuilder()
153157
.expireAfterAccess(sessionTimeout)
@@ -552,12 +556,22 @@ public NodeStatus getStatus() {
552556
})
553557
.collect(toImmutableSet());
554558

559+
Availability availability = isDraining() ? DRAINING : UP;
560+
561+
// Check status in case this Node is a RelayNode
562+
Optional<SessionSlot> relaySlot = factories.stream()
563+
.filter(SessionSlot::hasRelayFactory)
564+
.findFirst();
565+
if (relaySlot.isPresent() && !relaySlot.get().isRelayServiceUp()) {
566+
availability = DOWN;
567+
}
568+
555569
return new NodeStatus(
556570
getId(),
557571
externalUri,
558572
maxSessionCount,
559573
slots,
560-
isDraining() ? DRAINING : UP,
574+
availability,
561575
heartbeatPeriod,
562576
getNodeVersion(),
563577
getOsInfo());

java/src/org/openqa/selenium/grid/node/local/SessionSlot.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.openqa.selenium.grid.data.SessionClosedEvent;
3030
import org.openqa.selenium.grid.node.ActiveSession;
3131
import org.openqa.selenium.grid.node.SessionFactory;
32+
import org.openqa.selenium.grid.node.relay.RelaySessionFactory;
3233
import org.openqa.selenium.internal.Either;
3334
import org.openqa.selenium.internal.Require;
3435
import org.openqa.selenium.remote.SessionId;
@@ -163,4 +164,13 @@ private boolean isSlotSupportingCdp(Capabilities stereotype) {
163164
.filter(webDriverInfo -> webDriverInfo.isSupporting(stereotype))
164165
.anyMatch(WebDriverInfo::isSupportingCdp);
165166
}
167+
168+
public boolean hasRelayFactory() {
169+
return factory instanceof RelaySessionFactory;
170+
}
171+
172+
public boolean isRelayServiceUp() {
173+
return hasRelayFactory() && ((RelaySessionFactory) factory).isServiceUp();
174+
}
175+
166176
}

java/src/org/openqa/selenium/grid/node/relay/RelayOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public Map<Capabilities, Collection<SessionFactory>> getSessionFactories(
161161
tracer,
162162
clientFactory,
163163
getServiceUri(),
164+
getServiceStatusUri(),
164165
stereotype));
165166
}
166167
LOG.info(String.format("Mapping %s, %d times", stereotype, maxSessions));

java/src/org/openqa/selenium/grid/node/relay/RelaySessionFactory.java

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import static org.openqa.selenium.remote.tracing.EventAttribute.setValue;
3030
import static org.openqa.selenium.remote.tracing.Tags.EXCEPTION;
3131

32-
import com.google.common.annotations.VisibleForTesting;
33-
3432
import org.openqa.selenium.Capabilities;
3533
import org.openqa.selenium.ImmutableCapabilities;
3634
import org.openqa.selenium.SessionNotCreatedException;
@@ -39,6 +37,7 @@
3937
import org.openqa.selenium.grid.node.ActiveSession;
4038
import org.openqa.selenium.grid.node.ProtocolConvertingSession;
4139
import org.openqa.selenium.grid.node.SessionFactory;
40+
import org.openqa.selenium.internal.Debug;
4241
import org.openqa.selenium.internal.Either;
4342
import org.openqa.selenium.internal.Require;
4443
import org.openqa.selenium.remote.Command;
@@ -47,7 +46,13 @@
4746
import org.openqa.selenium.remote.ProtocolHandshake;
4847
import org.openqa.selenium.remote.Response;
4948
import org.openqa.selenium.remote.SessionId;
49+
import org.openqa.selenium.remote.http.AddSeleniumUserAgent;
50+
import org.openqa.selenium.remote.http.ClientConfig;
51+
import org.openqa.selenium.remote.http.Contents;
5052
import org.openqa.selenium.remote.http.HttpClient;
53+
import org.openqa.selenium.remote.http.HttpMethod;
54+
import org.openqa.selenium.remote.http.HttpRequest;
55+
import org.openqa.selenium.remote.http.HttpResponse;
5156
import org.openqa.selenium.remote.tracing.EventAttributeValue;
5257
import org.openqa.selenium.remote.tracing.Span;
5358
import org.openqa.selenium.remote.tracing.Status;
@@ -61,6 +66,7 @@
6166
import java.util.Map;
6267
import java.util.Objects;
6368
import java.util.Set;
69+
import java.util.logging.Level;
6470
import java.util.logging.Logger;
6571

6672
public class RelaySessionFactory implements SessionFactory {
@@ -70,16 +76,19 @@ public class RelaySessionFactory implements SessionFactory {
7076
private final Tracer tracer;
7177
private final HttpClient.Factory clientFactory;
7278
private final URL serviceUrl;
79+
private final URL serviceStatusUrl;
7380
private final Capabilities stereotype;
7481

7582
public RelaySessionFactory(
7683
Tracer tracer,
7784
HttpClient.Factory clientFactory,
7885
URI serviceUri,
86+
URI serviceStatusUri,
7987
Capabilities stereotype) {
8088
this.tracer = Require.nonNull("Tracer", tracer);
8189
this.clientFactory = Require.nonNull("HTTP client", clientFactory);
82-
this.serviceUrl = createServiceUrl(Require.nonNull("Service URL", serviceUri));
90+
this.serviceUrl = createUrlFromUri(Require.nonNull("Service URL", serviceUri));
91+
this.serviceStatusUrl = createUrlFromUri(serviceStatusUri);
8392
this.stereotype = ImmutableCapabilities
8493
.copyOf(Require.nonNull("Stereotype", stereotype));
8594
}
@@ -186,14 +195,32 @@ public void stop() {
186195
}
187196
}
188197

189-
@VisibleForTesting
190-
URL getServiceUrl() {
191-
return serviceUrl;
198+
public boolean isServiceUp() {
199+
if (serviceStatusUrl == null) {
200+
// If no status endpoint was configured, we assume the server is up.
201+
return true;
202+
}
203+
try {
204+
ClientConfig config = ClientConfig.defaultConfig()
205+
.baseUri(serviceStatusUrl.toURI())
206+
.filter(new AddSeleniumUserAgent());
207+
HttpClient client = clientFactory.createClient(config);
208+
HttpResponse response = client
209+
.execute(new HttpRequest(HttpMethod.GET, serviceStatusUrl.toString()));
210+
LOG.log(Debug.getDebugLogLevel(), Contents.string(response));
211+
return response.getStatus() == 200;
212+
} catch (Exception e) {
213+
LOG.log(Level.WARNING, "Error checking service status " + serviceStatusUrl, e);
214+
}
215+
return false;
192216
}
193217

194-
private URL createServiceUrl(URI serviceUri) {
218+
private URL createUrlFromUri(URI uri) {
219+
if (uri == null) {
220+
return null;
221+
}
195222
try {
196-
return serviceUri.toURL();
223+
return uri.toURL();
197224
} catch (MalformedURLException e) {
198225
throw new RuntimeException(e.getMessage(), e);
199226
}

0 commit comments

Comments
 (0)