0
# Node Management
1
2
Selenium Grid nodes execute WebDriver commands and manage browser sessions. They provide the actual browser automation capabilities and can run locally or remotely across the grid infrastructure.
3
4
## Capabilities
5
6
### Core Node Interface
7
8
The main node interface defines the contract for WebDriver session execution and management.
9
10
```java { .api }
11
/**
12
* Abstract base class for all grid nodes
13
*/
14
abstract class Node {
15
/** Protected constructor with core dependencies */
16
protected Node(Tracer tracer, NodeId id, URI uri, Secret registrationSecret, Duration sessionTimeout);
17
18
/** Create a new WebDriver session on this node */
19
abstract Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest);
20
21
/** Execute a WebDriver command for an existing session */
22
abstract HttpResponse executeWebDriverCommand(HttpRequest req);
23
24
/** Get session information by ID */
25
abstract Session getSession(SessionId id);
26
27
/** Stop and cleanup a session */
28
abstract void stop(SessionId id);
29
30
/** Check if this node owns the specified session */
31
abstract boolean isSessionOwner(SessionId id);
32
33
/** Check if this node supports the given capabilities */
34
abstract boolean isSupporting(Capabilities capabilities);
35
36
/** Get current node status including available slots */
37
abstract NodeStatus getStatus();
38
39
/** Get health check for monitoring node availability */
40
abstract HealthCheck getHealthCheck();
41
42
/** Begin draining this node (stop accepting new sessions) */
43
abstract void drain();
44
45
/** Get the node ID (concrete implementation) */
46
NodeId getId();
47
48
/** Get the node URI (concrete implementation) */
49
URI getUri();
50
}
51
```
52
53
### Local Node Implementation
54
55
Default implementation for running browser sessions in the same process as the node.
56
57
```java { .api }
58
/**
59
* Local node implementation that manages browser sessions directly
60
*/
61
class LocalNode extends Node {
62
/** Builder class for constructing LocalNode instances */
63
static Builder builder(Tracer tracer, EventBus eventBus, URI uri, URI gridUri, Secret registrationSecret);
64
65
/** Create a LocalNode from configuration */
66
static Node create(Config config);
67
68
// Builder pattern for complex construction
69
static class Builder {
70
/** Add a session factory for specific capabilities */
71
Builder add(Capabilities stereotype, SessionFactory factory);
72
73
/** Set maximum number of concurrent sessions */
74
Builder maximumConcurrentSessions(int maxSessions);
75
76
/** Set session timeout */
77
Builder sessionTimeout(Duration timeout);
78
79
/** Set heartbeat period for status updates */
80
Builder heartbeatPeriod(Duration period);
81
82
/** Build the LocalNode instance */
83
LocalNode build();
84
}
85
86
// Implement all abstract methods
87
Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest);
88
HttpResponse executeWebDriverCommand(HttpRequest req);
89
Session getSession(SessionId id);
90
void stop(SessionId id);
91
boolean isSessionOwner(SessionId id);
92
boolean isSupporting(Capabilities capabilities);
93
NodeStatus getStatus();
94
HealthCheck getHealthCheck();
95
void drain();
96
}
97
```
98
99
**Usage Example:**
100
101
```java
102
// Create session factories for different browsers
103
SessionFactory chromeFactory = new ChromeSessionFactory();
104
SessionFactory firefoxFactory = new FirefoxSessionFactory();
105
106
// Build the local node
107
LocalNode node = LocalNode.builder(tracer, eventBus, nodeUri, gridUri, registrationSecret)
108
.add(new ImmutableCapabilities("browserName", "chrome"), chromeFactory)
109
.add(new ImmutableCapabilities("browserName", "firefox"), firefoxFactory)
110
.maximumConcurrentSessions(10)
111
.sessionTimeout(Duration.ofMinutes(5))
112
.heartbeatPeriod(Duration.ofSeconds(30))
113
.build();
114
115
// Register with distributor
116
Distributor distributor = LocalDistributor.create(config);
117
distributor = distributor.add(node);
118
```
119
120
### Remote Node Proxy
121
122
Proxy for accessing nodes running in remote processes via HTTP.
123
124
```java { .api }
125
/**
126
* Remote node proxy for distributed deployments
127
*/
128
class RemoteNode extends Node {
129
RemoteNode(Tracer tracer, HttpClient.Factory httpClientFactory, NodeId id, URI uri, Secret registrationSecret);
130
131
// All methods implemented via HTTP calls to remote node
132
Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest);
133
HttpResponse executeWebDriverCommand(HttpRequest req);
134
Session getSession(SessionId id);
135
void stop(SessionId id);
136
boolean isSessionOwner(SessionId id);
137
boolean isSupporting(Capabilities capabilities);
138
NodeStatus getStatus();
139
HealthCheck getHealthCheck();
140
void drain();
141
}
142
```
143
144
### Relay Node
145
146
Special node type for integrating external WebDriver services.
147
148
```java { .api }
149
/**
150
* Relay node for external WebDriver service integration
151
*/
152
class RelayNode extends Node {
153
RelayNode(Tracer tracer, NodeId id, URI uri, Secret registrationSecret,
154
Duration sessionTimeout, HttpClient.Factory httpClientFactory,
155
Capabilities stereotype, URI serviceUri);
156
157
// Relays commands to external service
158
Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest);
159
HttpResponse executeWebDriverCommand(HttpRequest req);
160
Session getSession(SessionId id);
161
void stop(SessionId id);
162
boolean isSessionOwner(SessionId id);
163
boolean isSupporting(Capabilities capabilities);
164
NodeStatus getStatus();
165
HealthCheck getHealthCheck();
166
void drain();
167
}
168
```
169
170
### Session Management
171
172
Active session interface and default implementation for tracking browser sessions.
173
174
```java { .api }
175
/**
176
* Interface representing an active WebDriver session
177
*/
178
interface ActiveSession {
179
/** Get the session ID */
180
SessionId getId();
181
182
/** Get the session capabilities */
183
Capabilities getCapabilities();
184
185
/** Get the WebDriver instance for this session */
186
WebDriver getWrappedDriver();
187
188
/** Execute a WebDriver command */
189
Response execute(Command command) throws IOException;
190
191
/** Stop the session and cleanup resources */
192
void stop();
193
}
194
195
/**
196
* Default implementation of ActiveSession
197
*/
198
class DefaultActiveSession implements ActiveSession {
199
DefaultActiveSession(WebDriver driver, SessionId id, Capabilities capabilities);
200
201
SessionId getId();
202
Capabilities getCapabilities();
203
WebDriver getWrappedDriver();
204
Response execute(Command command) throws IOException;
205
void stop();
206
}
207
208
/**
209
* Factory for creating WebDriver sessions
210
*/
211
interface SessionFactory {
212
/** Check if this factory can create sessions with the given capabilities */
213
boolean test(Capabilities capabilities);
214
215
/** Create a new WebDriver session */
216
Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sessionRequest);
217
}
218
```
219
220
### Docker Support
221
222
Docker-based session management for containerized browser execution.
223
224
```java { .api }
225
/**
226
* Docker-based WebDriver session implementation
227
*/
228
class DockerSession extends DefaultActiveSession {
229
DockerSession(Container container, WebDriver driver, SessionId id, Capabilities caps);
230
231
/** Get the Docker container for this session */
232
Container getContainer();
233
234
@Override
235
void stop(); // Includes container cleanup
236
}
237
238
/**
239
* Factory for creating Docker-based sessions
240
*/
241
class DockerSessionFactory implements SessionFactory {
242
DockerSessionFactory(Tracer tracer, HttpClient.Factory clientFactory, DockerOptions dockerOptions);
243
244
boolean test(Capabilities capabilities);
245
Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sessionRequest);
246
247
/** Get available Docker images */
248
Set<String> getAvailableImages();
249
}
250
```
251
252
### Configuration Options
253
254
Node-specific configuration settings and command-line flags.
255
256
```java { .api }
257
/**
258
* Configuration options for node behavior
259
*/
260
class NodeOptions {
261
static final String NODE_SECTION = "node";
262
263
/** Get the public-facing URI for this node */
264
URI getPublicUri(Config config);
265
266
/** Get the grid registration URI */
267
URI getGridUri(Config config);
268
269
/** Get maximum number of concurrent sessions */
270
int getMaxSessions(Config config);
271
272
/** Get session timeout duration */
273
Duration getSessionTimeout(Config config);
274
275
/** Get heartbeat period for status updates */
276
Duration getHeartbeatPeriod(Config config);
277
278
/** Get node-specific capabilities */
279
Map<String, Object> getCapabilities(Config config);
280
}
281
282
/**
283
* Command-line flags for node configuration
284
*/
285
class NodeFlags {
286
@Parameter(names = {"--detect-drivers"},
287
description = "Autodetect available WebDriver executables")
288
Boolean detectDrivers = true;
289
290
@Parameter(names = {"--max-sessions"},
291
description = "Maximum number of concurrent sessions")
292
int maxSessions = Runtime.getRuntime().availableProcessors();
293
294
@Parameter(names = {"--session-timeout"},
295
description = "Session timeout in seconds")
296
int sessionTimeout = 300;
297
298
@Parameter(names = {"--heartbeat-period"},
299
description = "Heartbeat period in seconds")
300
int heartbeatPeriod = 60;
301
302
@Parameter(names = {"--override-max-sessions"},
303
description = "Allow overriding max sessions calculation")
304
Boolean overrideMaxSessions = false;
305
}
306
307
/**
308
* Docker-specific configuration options
309
*/
310
class DockerOptions {
311
static final String DOCKER_SECTION = "docker";
312
313
/** Get Docker host URI */
314
URI getDockerUri(Config config);
315
316
/** Get available Docker images mapping */
317
Map<String, String> getDockerImages(Config config);
318
319
/** Get video recording settings */
320
boolean getVideoRecording(Config config);
321
322
/** Get Docker network settings */
323
String getDockerNetwork(Config config);
324
}
325
```
326
327
### Health Monitoring
328
329
Health check interface for monitoring node availability and status.
330
331
```java { .api }
332
/**
333
* Functional interface for node health checks
334
*/
335
@FunctionalInterface
336
interface HealthCheck {
337
/** Perform health check and return result */
338
Result check();
339
340
/** Health check result with availability status and message */
341
class Result {
342
Result(Availability availability, String message);
343
344
/** Get the availability status */
345
Availability getAvailability();
346
347
/** Get descriptive message about health status */
348
String getMessage();
349
}
350
}
351
```
352
353
## Node Lifecycle
354
355
```java
356
// Create and start a node
357
LocalNode node = LocalNode.builder(tracer, eventBus, nodeUri, gridUri, secret)
358
.add(chromeCapabilities, chromeFactory)
359
.build();
360
361
// Node automatically registers with grid and starts accepting sessions
362
363
// Graceful shutdown
364
node.drain(); // Stop accepting new sessions
365
// Wait for existing sessions to complete
366
node.stop(); // Cleanup resources
367
```
368
369
## Error Handling
370
371
```java
372
// Session creation errors
373
Either<WebDriverException, CreateSessionResponse> result = node.newSession(request);
374
375
if (result.isLeft()) {
376
WebDriverException error = result.left();
377
378
// Common errors:
379
// - UnsupportedCapabilitiesException: Capabilities not supported
380
// - SessionNotCreatedException: Browser startup failed
381
// - ResourceUnavailableException: Node at capacity
382
383
System.err.println("Session creation failed: " + error.toString());
384
}
385
386
// Command execution errors
387
try {
388
HttpResponse response = node.executeWebDriverCommand(webdriverRequest);
389
// Process successful response
390
} catch (Exception e) {
391
// Handle communication errors, timeouts, etc.
392
System.err.println("Command execution failed: " + e.getMessage());
393
}
394
```