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

session-distribution.mddocs/

0

# Session Distribution

1

2

The session distribution system manages WebDriver session creation and routing across available grid nodes, providing load balancing, capacity management, and slot selection strategies.

3

4

## Capabilities

5

6

### Core Distributor Interface

7

8

The main distributor interface handles session creation requests and node management.

9

10

```java { .api }

11

/**

12

* Abstract base class for session distributors

13

*/

14

abstract class Distributor {

15

/** Protected constructor with required dependencies */

16

protected Distributor(Tracer tracer, HttpClient.Factory httpClientFactory, Secret registrationSecret);

17

18

/** Create a new WebDriver session */

19

abstract Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);

20

21

/** Add a node to the grid */

22

abstract Distributor add(Node node);

23

24

/** Drain sessions from a node (stop accepting new sessions) */

25

abstract boolean drain(NodeId nodeId);

26

27

/** Remove a node from the grid */

28

abstract void remove(NodeId nodeId);

29

30

/** Get current distributor status and statistics */

31

abstract DistributorStatus getStatus();

32

}

33

```

34

35

### Local Distributor Implementation

36

37

Default in-process distributor implementation with full session management.

38

39

```java { .api }

40

/**

41

* Local distributor implementation for single-process or hub deployments

42

*/

43

@ManagedService

44

class LocalDistributor extends Distributor {

45

/** Factory method to create distributor from configuration */

46

static Distributor create(Config config);

47

48

// Implement all abstract methods from Distributor

49

Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);

50

Distributor add(Node node);

51

boolean drain(NodeId nodeId);

52

void remove(NodeId nodeId);

53

DistributorStatus getStatus();

54

55

// JMX management attributes

56

@ManagedAttribute

57

int getNodeCount();

58

59

@ManagedAttribute

60

int getSessionCount();

61

62

@ManagedAttribute

63

long getSessionsCreated();

64

65

@ManagedAttribute

66

Map<String, Object> getSlotStereotypes();

67

}

68

```

69

70

**Usage Example:**

71

72

```java

73

Config config = new MemoizedConfig(new MapConfig(Map.of(

74

"distributor", Map.of(

75

"reject-unsupported-caps", true,

76

"healthcheck-interval", "120s"

77

)

78

)));

79

80

Distributor distributor = LocalDistributor.create(config);

81

82

// Add nodes to the distributor

83

Node chromeNode = createChromeNode();

84

Node firefoxNode = createFirefoxNode();

85

86

Distributor updatedDistributor = distributor

87

.add(chromeNode)

88

.add(firefoxNode);

89

90

// Create a new session

91

SessionRequest request = new SessionRequest(

92

new RequestId(UUID.randomUUID()),

93

Instant.now().plus(Duration.ofMinutes(5)), // timeout

94

Set.of(W3C), // dialects

95

new ImmutableCapabilities("browserName", "chrome")

96

);

97

98

Either<SessionNotCreatedException, CreateSessionResponse> result =

99

updatedDistributor.newSession(request);

100

101

if (result.isRight()) {

102

CreateSessionResponse response = result.right();

103

System.out.println("Session created: " + response.getSession().getId());

104

} else {

105

SessionNotCreatedException error = result.left();

106

System.err.println("Session creation failed: " + error.getMessage());

107

}

108

```

109

110

### Slot Selection Strategy

111

112

Functional interface for customizing how slots are selected for session creation.

113

114

```java { .api }

115

/**

116

* Strategy interface for selecting appropriate slots for session requests

117

*/

118

@FunctionalInterface

119

interface SlotSelector {

120

/**

121

* Select slots that can handle the requested capabilities

122

* @param capabilities The desired session capabilities

123

* @param nodes Available nodes with their current status

124

* @param slotMatcher Function to test capability matching

125

* @return Set of slot IDs that can fulfill the request

126

*/

127

Set<SlotId> selectSlot(Capabilities capabilities, Set<NodeStatus> nodes, SlotMatcher slotMatcher);

128

}

129

130

/**

131

* Default slot selection implementation using round-robin with load balancing

132

*/

133

class DefaultSlotSelector implements SlotSelector {

134

Set<SlotId> selectSlot(Capabilities capabilities, Set<NodeStatus> nodes, SlotMatcher slotMatcher);

135

}

136

```

137

138

**Custom Slot Selector Example:**

139

140

```java

141

// Custom selector that prefers nodes with lower load

142

SlotSelector loadBasedSelector = (capabilities, nodes, slotMatcher) -> {

143

return nodes.stream()

144

.filter(node -> node.hasCapacity(capabilities, slotMatcher))

145

.sorted(Comparator.comparing(NodeStatus::getLoad))

146

.flatMap(node -> node.getSlots().stream())

147

.filter(slot -> slot.isSupporting(capabilities, slotMatcher))

148

.map(Slot::getId)

149

.limit(1)

150

.collect(Collectors.toSet());

151

};

152

```

153

154

### Remote Distributor Client

155

156

Client for accessing distributors running in remote processes.

157

158

```java { .api }

159

/**

160

* Remote distributor client for distributed grid deployments

161

*/

162

class RemoteDistributor extends Distributor {

163

RemoteDistributor(Tracer tracer, HttpClient.Factory httpClientFactory,

164

URI distributorUri, Secret registrationSecret);

165

166

// Implement all abstract methods via HTTP calls

167

Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);

168

Distributor add(Node node);

169

boolean drain(NodeId nodeId);

170

void remove(NodeId nodeId);

171

DistributorStatus getStatus();

172

}

173

```

174

175

### Configuration Options

176

177

Configuration settings specific to the distributor component.

178

179

```java { .api }

180

/**

181

* Configuration options for distributor behavior

182

*/

183

class DistributorOptions {

184

static final String DISTRIBUTOR_SECTION = "distributor";

185

186

/** Get implementation class for the distributor */

187

String getDistributorImplementation(Config config);

188

189

/** Get health check interval for nodes */

190

Duration getHealthCheckInterval(Config config);

191

192

/** Whether to reject requests with unsupported capabilities */

193

boolean shouldRejectUnsupportedCaps(Config config);

194

195

/** Get slot matcher implementation */

196

SlotMatcher getSlotMatcher(Config config);

197

198

/** Get slot selector implementation */

199

SlotSelector getSlotSelector(Config config);

200

}

201

202

/**

203

* Command-line flags for distributor configuration

204

*/

205

class DistributorFlags {

206

@Parameter(names = {"--reject-unsupported-caps"},

207

description = "Reject session requests with unsupported capabilities")

208

Boolean rejectUnsupportedCaps;

209

210

@Parameter(names = {"--healthcheck-interval"},

211

description = "How often to check node health")

212

int healthCheckInterval = 120;

213

214

@Parameter(names = {"--slot-matcher"},

215

description = "Full class name of SlotMatcher implementation")

216

String slotMatcher = "org.openqa.selenium.grid.data.DefaultSlotMatcher";

217

218

@Parameter(names = {"--slot-selector"},

219

description = "Full class name of SlotSelector implementation")

220

String slotSelector = "org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector";

221

}

222

```

223

224

## Request/Response Models

225

226

```java { .api }

227

/**

228

* Request to create a new WebDriver session

229

*/

230

class SessionRequest {

231

SessionRequest(RequestId requestId, Instant enqueued, Set<Dialect> downstreamDialects, Capabilities desiredCapabilities);

232

RequestId getRequestId();

233

Instant getEnqueued();

234

Set<Dialect> getDownstreamDialects();

235

Capabilities getDesiredCapabilities();

236

}

237

238

/**

239

* Response containing created session information

240

*/

241

class CreateSessionResponse {

242

CreateSessionResponse(Session session, byte[] downstreamEncodedResponse);

243

Session getSession();

244

byte[] getDownstreamEncodedResponse();

245

}

246

247

/**

248

* Current status of the distributor

249

*/

250

class DistributorStatus {

251

DistributorStatus(Set<NodeStatus> nodes);

252

Set<NodeStatus> getNodes();

253

boolean hasCapacity();

254

boolean hasCapacity(Capabilities capabilities);

255

}

256

```

257

258

## Error Handling

259

260

```java

261

// Session creation can fail for several reasons

262

Either<SessionNotCreatedException, CreateSessionResponse> result = distributor.newSession(request);

263

264

if (result.isLeft()) {

265

SessionNotCreatedException error = result.left();

266

267

// Common reasons for failure:

268

// - No nodes available with matching capabilities

269

// - All matching nodes at capacity

270

// - Request timeout exceeded

271

// - Node health check failure

272

273

System.err.println("Session creation failed: " + error.getMessage());

274

}

275

```