or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

brokers.mddecorators.mddiscovery.mdhttp.mdindex.mdrequests.mdrouters.mdscheduling.mdspecs.mdsystem-utils.md

decorators.mddocs/

0

# Decorators and Routing

1

2

The decorator system provides a unified interface for registering handler functions across different transport types (broker, HTTP, periodic). The `enroute` decorator system automatically handles routing, middleware integration, and request/response processing.

3

4

## Capabilities

5

6

### Main Decorator Interface

7

8

The `enroute` object provides access to all decorator types through a hierarchical interface.

9

10

```python { .api }

11

enroute: Enroute

12

13

class Enroute:

14

broker: BrokerEnroute

15

rest: RestEnroute

16

periodic: PeriodicEnroute

17

```

18

19

### Broker Decorators

20

21

Decorators for message broker handlers supporting commands, queries, and events.

22

23

```python { .api }

24

class BrokerEnroute:

25

command: type[BrokerCommandEnrouteDecorator]

26

query: type[BrokerQueryEnrouteDecorator]

27

event: type[BrokerEventEnrouteDecorator]

28

29

class BrokerCommandEnrouteDecorator:

30

def __init__(self, topic: str, **kwargs): ...

31

topic: str

32

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Command

33

34

class BrokerQueryEnrouteDecorator:

35

def __init__(self, topic: str, **kwargs): ...

36

topic: str

37

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Query

38

39

class BrokerEventEnrouteDecorator:

40

def __init__(self, topic: str, **kwargs): ...

41

topic: str

42

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Event

43

```

44

45

**Usage Examples:**

46

47

```python

48

@enroute.broker.command("user.create")

49

async def create_user(request: Request) -> Response:

50

user_data = await request.content()

51

return Response({"id": "123", "status": "created"})

52

53

@enroute.broker.query("user.get")

54

async def get_user(request: Request) -> Response:

55

user_id = await request.content()

56

return Response({"id": user_id, "name": "John Doe"})

57

58

@enroute.broker.event("user.created")

59

async def handle_user_created(request: Request) -> Response:

60

event_data = await request.content()

61

# Handle event processing

62

return Response({"processed": True})

63

```

64

65

### REST Decorators

66

67

Decorators for HTTP REST endpoint handlers supporting commands and queries.

68

69

```python { .api }

70

class RestEnroute:

71

command: type[RestCommandEnrouteDecorator]

72

query: type[RestQueryEnrouteDecorator]

73

74

class RestCommandEnrouteDecorator:

75

def __init__(self, path: str, method: str = "POST", **kwargs): ...

76

path: str

77

method: str

78

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Command

79

80

class RestQueryEnrouteDecorator:

81

def __init__(self, path: str, method: str = "GET", **kwargs): ...

82

path: str

83

method: str

84

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Query

85

```

86

87

**Usage Examples:**

88

89

```python

90

@enroute.rest.command("/users", method="POST")

91

async def create_user_http(request: Request) -> Response:

92

user_data = await request.content()

93

return Response({"id": "123", "status": "created"})

94

95

@enroute.rest.query("/users/{user_id}", method="GET")

96

async def get_user_http(request: Request) -> Response:

97

params = await request.params()

98

user_id = params["user_id"]

99

return Response({"id": user_id, "name": "John Doe"})

100

101

@enroute.rest.command("/users/{user_id}", method="PUT")

102

async def update_user(request: Request) -> Response:

103

params = await request.params()

104

user_data = await request.content()

105

return Response({"id": params["user_id"], "status": "updated"})

106

```

107

108

### Periodic Decorators

109

110

Decorators for scheduled task handlers using cron expressions.

111

112

```python { .api }

113

class PeriodicEnroute:

114

event: type[PeriodicEventEnrouteDecorator]

115

116

class PeriodicEventEnrouteDecorator:

117

def __init__(self, crontab: Union[str, CronTab], **kwargs): ...

118

crontab: CronTab

119

KIND: EnrouteDecoratorKind = EnrouteDecoratorKind.Event

120

```

121

122

**Usage Examples:**

123

124

```python

125

@enroute.periodic.event("0 */5 * * * *") # Every 5 minutes

126

async def cleanup_task(request: Request) -> Response:

127

# Periodic cleanup logic

128

return Response({"status": "cleanup_completed"})

129

130

@enroute.periodic.event("0 0 * * *") # Daily at midnight

131

async def daily_report(request: Request) -> Response:

132

# Generate daily reports

133

return Response({"report": "generated"})

134

135

# Using CronTab object

136

from minos.networks import CronTab

137

cron = CronTab("0 30 9 * * MON-FRI") # Weekdays at 9:30 AM

138

139

@enroute.periodic.event(cron)

140

async def business_hours_task(request: Request) -> Response:

141

return Response({"status": "executed"})

142

```

143

144

### Handler Metadata and Wrappers

145

146

Classes for managing handler function metadata and execution wrappers.

147

148

```python { .api }

149

class HandlerMeta:

150

def __init__(self, func: Handler, decorators: Optional[set[EnrouteDecorator]] = None, checkers: Optional[set[CheckerMeta]] = None): ...

151

func: Handler

152

decorators: set[EnrouteDecorator]

153

checkers: set[CheckerMeta]

154

wrapper: HandlerWrapper

155

check: type[CheckDecorator]

156

def add_decorator(self, decorator: EnrouteDecorator) -> None: ...

157

158

class HandlerWrapper:

159

"""Wrapper for handler functions with decorator metadata"""

160

161

class CheckerMeta:

162

def __init__(self, func: Checker, max_attempts: int, delay: float): ...

163

func: Checker

164

max_attempts: int

165

delay: float

166

wrapper: CheckerWrapper

167

@staticmethod

168

async def run_async(metas: set[CheckerMeta], *args, **kwargs) -> None: ...

169

@staticmethod

170

def run_sync(metas: set[CheckerMeta], *args, **kwargs) -> bool: ...

171

172

class CheckDecorator:

173

def __init__(self, handler_meta: HandlerMeta, max_attempts: int = 10, delay: Union[float, timedelta] = 0.1): ...

174

max_attempts: int

175

delay: float

176

def __call__(self, func: Union[CheckerWrapper, Checker]) -> CheckerWrapper: ...

177

```

178

179

### Route Collection and Factories

180

181

Utilities for discovering and organizing decorated handlers.

182

183

```python { .api }

184

class EnrouteCollector:

185

def __init__(self, decorated: Any, config: Optional[Config] = None): ...

186

decorated: Any

187

config: Optional[Config]

188

def get_rest_command_query(self) -> dict[str, set[RestEnrouteDecorator]]: ...

189

def get_broker_command_query_event(self) -> dict[str, set[BrokerEnrouteDecorator]]: ...

190

def get_broker_command_query(self) -> dict[str, set[BrokerEnrouteDecorator]]: ...

191

def get_broker_event(self) -> dict[str, set[BrokerEnrouteDecorator]]: ...

192

def get_periodic_event(self) -> dict[str, set[PeriodicEventEnrouteDecorator]]: ...

193

def get_all(self) -> dict[str, set[EnrouteDecorator]]: ...

194

195

class EnrouteFactory:

196

def __init__(self, *classes: Union[str, type], middleware: Optional[Union[str, Callable, list]] = None): ...

197

classes: tuple

198

middleware: list

199

def get_rest_command_query(self, **kwargs) -> dict[RestEnrouteDecorator, Handler]: ...

200

def get_broker_command_query_event(self, **kwargs) -> dict[BrokerEnrouteDecorator, Handler]: ...

201

def get_broker_command_query(self, **kwargs) -> dict[BrokerEnrouteDecorator, Handler]: ...

202

def get_broker_event(self, **kwargs) -> dict[BrokerEnrouteDecorator, Handler]: ...

203

def get_periodic_event(self, **kwargs) -> dict[PeriodicEnrouteDecorator, Handler]: ...

204

def get_all(self, **kwargs) -> dict[EnrouteDecorator, Handler]: ...

205

```

206

207

### Decorator Types and Constants

208

209

```python { .api }

210

from typing import Callable, Union, Optional, Awaitable

211

from enum import Enum, auto

212

213

Handler = Callable[[Request], Union[Optional[Response], Awaitable[Optional[Response]]]]

214

Checker = Callable[[Request], Union[Optional[bool], Awaitable[Optional[bool]]]]

215

216

class EnrouteDecoratorKind(Enum):

217

Command = auto()

218

Query = auto()

219

Event = auto()

220

221

@property

222

def pre_fn_name(self) -> str:

223

"""Returns pre-execution function name mapping"""

224

225

@property

226

def post_fn_name(self) -> str:

227

"""Returns post-execution function name mapping"""

228

```

229

230

### Handler and Checker System

231

232

Core abstractions for request processing and validation with metadata support.

233

234

```python { .api }

235

class Handler:

236

"""Base class for handling decorated function execution"""

237

def __init__(self, fn: Callable, decorators: list[EnrouteDecorator] = None): ...

238

fn: Callable

239

decorators: list[EnrouteDecorator]

240

241

class HandlerMeta:

242

"""Metadata container for handler information"""

243

def __init__(self, fn: Callable): ...

244

245

class HandlerWrapper:

246

"""Wrapper that provides handler execution context"""

247

def __init__(self, handler: Handler): ...

248

async def __call__(self, request: Request) -> Response: ...

249

250

class Checker:

251

"""Base class for request validation logic"""

252

def __init__(self, fn: Callable): ...

253

fn: Callable

254

255

class CheckerMeta:

256

"""Metadata container for checker information"""

257

def __init__(self, fn: Callable): ...

258

259

class CheckerWrapper:

260

"""Wrapper that provides checker execution context"""

261

def __init__(self, checker: Checker): ...

262

async def __call__(self, request: Request) -> bool: ...

263

264

class CheckDecorator:

265

"""Decorator for adding validation checks to handlers"""

266

def __init__(self, max_attempts: int = 1, delay: float = 0.0): ...

267

max_attempts: int

268

delay: float

269

```

270

271

**Usage Examples:**

272

273

```python

274

from minos.networks import Handler, Checker, CheckDecorator

275

276

# Custom handler with metadata

277

handler = Handler(my_function, decorators=[decorator1, decorator2])

278

wrapped = HandlerWrapper(handler)

279

280

# Custom checker for validation

281

checker = Checker(my_validation_function)

282

wrapped_checker = CheckerWrapper(checker)

283

284

# Using check decorator

285

@CheckDecorator(max_attempts=3, delay=0.5)

286

async def validate_input(request: Request) -> bool:

287

return True # validation logic

288

```

289

290

## Advanced Usage

291

292

### Adding Pre/Post Execution Checks

293

294

```python

295

class UserService:

296

@enroute.broker.command("user.create")

297

async def create_user(self, request: Request) -> Response:

298

# Handler implementation

299

pass

300

301

# Add checker with retry logic

302

@create_user.check(max_attempts=3, delay=0.5)

303

async def validate_user_data(self, request: Request) -> bool:

304

user_data = await request.content()

305

return "email" in user_data and "name" in user_data

306

```

307

308

### Middleware Integration

309

310

```python

311

from minos.networks import EnrouteFactory

312

313

# Create factory with middleware

314

factory = EnrouteFactory(

315

UserService,

316

OrderService,

317

middleware=["auth_middleware", "logging_middleware"]

318

)

319

320

# Get handlers with middleware applied

321

handlers = factory.get_all()

322

```

323

324

### Service Class Organization

325

326

```python

327

class UserService:

328

@enroute.broker.command("user.create")

329

async def create_user(self, request: Request) -> Response:

330

return Response({"status": "created"})

331

332

@enroute.broker.query("user.get")

333

async def get_user(self, request: Request) -> Response:

334

return Response({"user": "data"})

335

336

@enroute.rest.command("/users", method="POST")

337

async def create_user_rest(self, request: Request) -> Response:

338

return Response({"status": "created"})

339

340

@enroute.rest.query("/users/{user_id}", method="GET")

341

async def get_user_rest(self, request: Request) -> Response:

342

return Response({"user": "data"})

343

344

@enroute.periodic.event("0 0 * * *")

345

async def daily_cleanup(self, request: Request) -> Response:

346

return Response({"status": "cleaned"})

347

```