or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-commands.mdconfiguration.mdindex.mdnode-management.mdrequest-routing.mdsecurity.mdsession-distribution.mdsession-queuing.mdsession-storage.md

node-management.mddocs/

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

```