or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication-and-security.mdclassic-mode.mdcli-tools.mdconnection-factory.mdindex.mdregistry-and-discovery.mdservers.mdservices-protocols.mdstreams-and-channels.mdutilities.md

registry-and-discovery.mddocs/

0

# Registry and Service Discovery

1

2

Service registry and discovery system for automatic service location and management. The registry enables services to advertise their availability and clients to automatically discover and connect to services by name, supporting both UDP and TCP protocols.

3

4

## Capabilities

5

6

### Registry Servers

7

8

Server implementations for hosting service registries that track available RPyC services.

9

10

```python { .api }

11

class UDPRegistryServer:

12

"""

13

UDP-based registry server for service discovery.

14

Lightweight, broadcast-enabled registry suitable for LAN environments.

15

"""

16

17

def __init__(self, host='0.0.0.0', port=18811, pruning_timeout=3, allow_listing=True):

18

"""

19

Initialize UDP registry server.

20

21

Parameters:

22

- host (str): Host address to bind to

23

- port (int): UDP port to bind to (default 18811)

24

- pruning_timeout (float): Timeout for pruning stale services

25

- allow_listing (bool): Allow service listing requests

26

"""

27

28

def start(self):

29

"""Start the registry server"""

30

31

def close(self):

32

"""Close the registry server"""

33

34

class TCPRegistryServer:

35

"""

36

TCP-based registry server for service discovery.

37

More reliable than UDP, suitable for WAN environments.

38

"""

39

40

def __init__(self, port=18811, pruning_timeout=3, allow_listing=True):

41

"""

42

Initialize TCP registry server.

43

44

Parameters:

45

- port (int): TCP port to bind to (default 18811)

46

- pruning_timeout (float): Timeout for pruning stale services

47

- allow_listing (bool): Allow service listing requests

48

"""

49

50

def start(self):

51

"""Start the registry server"""

52

53

def close(self):

54

"""Close the registry server"""

55

```

56

57

### Registry Clients

58

59

Client implementations for registering services and querying service registries.

60

61

```python { .api }

62

class UDPRegistryClient:

63

"""

64

UDP registry client for service registration and discovery.

65

"""

66

67

def __init__(self, ip='255.255.255.255', port=18811):

68

"""

69

Initialize UDP registry client.

70

71

Parameters:

72

- ip (str): Registry server IP (default broadcast)

73

- port (int): Registry server port

74

"""

75

76

def register(self, alias, port, interface=''):

77

"""

78

Register service with registry.

79

80

Parameters:

81

- alias (str): Service name/alias

82

- port (int): Service port

83

- interface (str): Network interface (optional)

84

"""

85

86

def unregister(self, port):

87

"""

88

Unregister service from registry.

89

90

Parameters:

91

- port (int): Service port to unregister

92

"""

93

94

def discover(self, name):

95

"""

96

Discover services by name.

97

98

Parameters:

99

- name (str): Service name to discover

100

101

Returns:

102

list: List of (host, port) tuples

103

"""

104

105

def list_services(self):

106

"""

107

List all available services.

108

109

Returns:

110

dict: Dictionary mapping service names to (host, port) tuples

111

"""

112

113

class TCPRegistryClient:

114

"""

115

TCP registry client for service registration and discovery.

116

"""

117

118

def __init__(self, ip='127.0.0.1', port=18811):

119

"""

120

Initialize TCP registry client.

121

122

Parameters:

123

- ip (str): Registry server IP

124

- port (int): Registry server port

125

"""

126

127

def register(self, alias, port, interface=''):

128

"""

129

Register service with registry.

130

131

Parameters:

132

- alias (str): Service name/alias

133

- port (int): Service port

134

- interface (str): Network interface (optional)

135

"""

136

137

def unregister(self, port):

138

"""

139

Unregister service from registry.

140

141

Parameters:

142

- port (int): Service port to unregister

143

"""

144

145

def discover(self, name):

146

"""

147

Discover services by name.

148

149

Parameters:

150

- name (str): Service name to discover

151

152

Returns:

153

list: List of (host, port) tuples

154

"""

155

156

def list_services(self):

157

"""

158

List all available services.

159

160

Returns:

161

dict: Dictionary mapping service names to (host, port) tuples

162

"""

163

```

164

165

### Service Registration Decorators

166

167

Decorators and utilities for automatic service registration.

168

169

```python { .api }

170

def register_service(service_class, port, registrar=None, auto_register=True):

171

"""

172

Register service class with registry for automatic discovery.

173

174

Parameters:

175

- service_class: Service class to register

176

- port (int): Port the service will run on

177

- registrar: Registry client (optional, uses default)

178

- auto_register (bool): Automatically register on server start

179

180

Returns:

181

Configured server with registry integration

182

"""

183

```

184

185

## Examples

186

187

### Setting Up UDP Registry

188

189

```python

190

from rpyc.utils.registry import UDPRegistryServer

191

import threading

192

193

# Start UDP registry server

194

registry = UDPRegistryServer(host='0.0.0.0', port=18811)

195

registry_thread = threading.Thread(target=registry.start)

196

registry_thread.start()

197

198

print("UDP Registry running on port 18811")

199

```

200

201

### Registering Services

202

203

```python

204

import rpyc

205

from rpyc.utils.server import ThreadedServer

206

from rpyc.utils.registry import UDPRegistryClient

207

208

class CalculatorService(rpyc.Service):

209

SERVICE_NAME = "CALCULATOR"

210

211

@rpyc.exposed

212

def add(self, a, b):

213

return a + b

214

215

@rpyc.exposed

216

def multiply(self, a, b):

217

return a * b

218

219

# Create registry client

220

registry = UDPRegistryClient()

221

222

# Create server with registry integration

223

server = ThreadedServer(

224

CalculatorService,

225

port=12345,

226

registrar=registry,

227

auto_register=True

228

)

229

230

print("Calculator service starting with registry integration")

231

server.start()

232

```

233

234

### Service Discovery and Connection

235

236

```python

237

import rpyc

238

from rpyc.utils.registry import UDPRegistryClient

239

240

# Create registry client

241

registry = UDPRegistryClient()

242

243

# Discover available services

244

services = registry.list_services()

245

print("Available services:", services)

246

247

# Discover specific service

248

calculator_endpoints = registry.discover("CALCULATOR")

249

if calculator_endpoints:

250

host, port = calculator_endpoints[0]

251

print(f"Found CALCULATOR service at {host}:{port}")

252

253

# Connect to discovered service

254

conn = rpyc.connect(host, port)

255

result = conn.root.add(5, 3)

256

print(f"5 + 3 = {result}")

257

conn.close()

258

else:

259

print("CALCULATOR service not found")

260

```

261

262

### TCP Registry with Multiple Services

263

264

```python

265

from rpyc.utils.registry import TCPRegistryServer, TCPRegistryClient

266

import rpyc

267

from rpyc.utils.server import ThreadedServer

268

import threading

269

270

# Start TCP registry server

271

def run_registry():

272

registry = TCPRegistryServer(port=18811)

273

registry.start()

274

275

registry_thread = threading.Thread(target=run_registry)

276

registry_thread.daemon = True

277

registry_thread.start()

278

279

# Service definitions

280

class DataService(rpyc.Service):

281

SERVICE_NAME = "DATA_PROCESSOR"

282

283

@rpyc.exposed

284

def process_data(self, data):

285

return [x * 2 for x in data]

286

287

class AuthService(rpyc.Service):

288

SERVICE_NAME = "AUTHENTICATOR"

289

290

@rpyc.exposed

291

def validate_token(self, token):

292

return token == "valid_token"

293

294

# Create registry client

295

registry_client = TCPRegistryClient()

296

297

# Start multiple services with registry

298

services = [

299

(DataService, 12001),

300

(AuthService, 12002)

301

]

302

303

servers = []

304

for service_class, port in services:

305

server = ThreadedServer(

306

service_class,

307

port=port,

308

registrar=registry_client,

309

auto_register=True

310

)

311

servers.append(server)

312

313

# Start server in background

314

server_thread = threading.Thread(target=server.start)

315

server_thread.daemon = True

316

server_thread.start()

317

318

print(f"{service_class.SERVICE_NAME} started on port {port}")

319

320

# Client discovery and usage

321

import time

322

time.sleep(1) # Wait for services to register

323

324

# List all services

325

all_services = registry_client.list_services()

326

print("All registered services:", all_services)

327

328

# Use discovered services

329

data_endpoints = registry_client.discover("DATA_PROCESSOR")

330

if data_endpoints:

331

host, port = data_endpoints[0]

332

conn = rpyc.connect(host, port)

333

result = conn.root.process_data([1, 2, 3, 4])

334

print("Processed data:", result)

335

conn.close()

336

337

auth_endpoints = registry_client.discover("AUTHENTICATOR")

338

if auth_endpoints:

339

host, port = auth_endpoints[0]

340

conn = rpyc.connect(host, port)

341

is_valid = conn.root.validate_token("valid_token")

342

print("Token validation:", is_valid)

343

conn.close()

344

```

345

346

### Registry with Service Health Monitoring

347

348

```python

349

from rpyc.utils.registry import UDPRegistryClient

350

import rpyc

351

import time

352

import threading

353

354

class MonitoredService(rpyc.Service):

355

SERVICE_NAME = "MONITORED_SERVICE"

356

357

def __init__(self):

358

self.start_time = time.time()

359

self.request_count = 0

360

361

@rpyc.exposed

362

def get_status(self):

363

uptime = time.time() - self.start_time

364

return {

365

'uptime': uptime,

366

'requests_served': self.request_count,

367

'status': 'healthy'

368

}

369

370

@rpyc.exposed

371

def process_request(self, data):

372

self.request_count += 1

373

return f"Processed: {data}"

374

375

# Service with periodic re-registration (health check)

376

def maintain_registration(service_port, registry_client):

377

while True:

378

try:

379

# Re-register every 30 seconds to show service is healthy

380

registry_client.register("MONITORED_SERVICE", service_port)

381

time.sleep(30)

382

except Exception as e:

383

print(f"Registration failed: {e}")

384

time.sleep(5)

385

386

# Start service

387

registry = UDPRegistryClient()

388

server = ThreadedServer(MonitoredService, port=12345)

389

390

# Start registration maintenance

391

registration_thread = threading.Thread(

392

target=maintain_registration,

393

args=(12345, registry)

394

)

395

registration_thread.daemon = True

396

registration_thread.start()

397

398

# Start server

399

server_thread = threading.Thread(target=server.start)

400

server_thread.daemon = True

401

server_thread.start()

402

403

print("Monitored service with health check registration started")

404

405

# Monitor service health

406

while True:

407

try:

408

services = registry.discover("MONITORED_SERVICE")

409

if services:

410

host, port = services[0]

411

conn = rpyc.connect(host, port)

412

status = conn.root.get_status()

413

print(f"Service health: {status}")

414

conn.close()

415

else:

416

print("Service not available")

417

418

time.sleep(10)

419

except KeyboardInterrupt:

420

break

421

except Exception as e:

422

print(f"Health check failed: {e}")

423

time.sleep(5)

424

```

425

426

## Constants

427

428

```python { .api }

429

REGISTRY_PORT = 18811 # Default registry port

430

DEFAULT_PRUNING_TIMEOUT = 3 # Default service timeout (seconds)

431

UDP_BROADCAST_ADDRESS = '255.255.255.255' # Default UDP broadcast address

432

```

433

434

## Exceptions

435

436

```python { .api }

437

class RegistryError(Exception):

438

"""Base exception for registry operations"""

439

440

class ServiceNotFoundError(RegistryError):

441

"""Raised when requested service is not found"""

442

443

class RegistrationError(RegistryError):

444

"""Raised when service registration fails"""

445

```