jararaca 0.3.11a15__tar.gz → 0.3.12a0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/PKG-INFO +3 -3
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/index.md +143 -20
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/messagebus.md +26 -6
- jararaca-0.3.12a0/docs/retry.md +79 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/scheduler.md +44 -24
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/websocket.md +24 -10
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/pyproject.toml +1 -1
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/cli.py +214 -31
- jararaca-0.3.12a0/src/jararaca/messagebus/worker.py +1416 -0
- jararaca-0.3.12a0/src/jararaca/utils/retry.py +141 -0
- jararaca-0.3.11a15/src/jararaca/messagebus/worker.py +0 -644
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/LICENSE +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/README.md +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/CNAME +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/architecture.md +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/docs/stylesheets/custom.css +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/__main__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/broker_backend/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/broker_backend/mapper.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/di.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/consumers/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/message.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/microservice.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/py.typed +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/reflect/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/reflect/controller_inspect.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/reflect/metadata.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/scheduler/beat_worker.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/scheduler/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/scheduler/types.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/tools/typescript/interface_parser.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/utils/__init__.py +0 -0
- {jararaca-0.3.11a15 → jararaca-0.3.12a0}/src/jararaca/utils/rabbitmq_utils.py +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: jararaca
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.12a0
|
|
4
4
|
Summary: A simple and fast API framework for Python
|
|
5
|
+
Home-page: https://github.com/LuscasLeo/jararaca
|
|
5
6
|
Author: Lucas S
|
|
6
7
|
Author-email: me@luscasleo.dev
|
|
7
8
|
Requires-Python: >=3.11,<4.0
|
|
8
9
|
Classifier: Programming Language :: Python :: 3
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
12
12
|
Provides-Extra: docs
|
|
13
13
|
Provides-Extra: http
|
|
14
14
|
Provides-Extra: opentelemetry
|
|
@@ -9,9 +9,9 @@ Jararaca is a powerful Python microservice framework that provides a comprehensi
|
|
|
9
9
|
- 📦 **Dependency Injection**: Flexible dependency injection system with interceptors
|
|
10
10
|
- 📊 **Database Integration**: SQLAlchemy integration with async support
|
|
11
11
|
- 📡 **Message Bus**: RabbitMQ integration for event-driven architecture
|
|
12
|
-
-
|
|
12
|
+
- ⚡ **Retry Mechanism**: Robust retry system with exponential backoff for resilient operations
|
|
13
13
|
- 🔍 **Query Operations**: Advanced query capabilities with pagination and filtering
|
|
14
|
-
- ⏱️ **Scheduled Tasks**:
|
|
14
|
+
- ⏱️ **Scheduled Tasks**: Distributed cron-based task scheduling with message broker integration
|
|
15
15
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
@@ -33,9 +33,27 @@ Starts a message bus worker that processes asynchronous messages from a message
|
|
|
33
33
|
|
|
34
34
|
**Options:**
|
|
35
35
|
|
|
36
|
-
- `--broker-url`: The URL for the message broker (required)
|
|
37
|
-
- `--backend-url`: The URL for the message broker backend (required)
|
|
38
|
-
- `--handlers`: Comma-separated list of handler names to listen to (optional)
|
|
36
|
+
- `--broker-url`: The URL for the message broker (required) [env: BROKER_URL]
|
|
37
|
+
- `--backend-url`: The URL for the message broker backend (required) [env: BACKEND_URL]
|
|
38
|
+
- `--handlers`: Comma-separated list of handler names to listen to (optional) [env: HANDLERS]
|
|
39
|
+
- `--reload`: Enable auto-reload when Python files change (for development) [env: RELOAD]
|
|
40
|
+
- `--src-dir`: The source directory to watch for changes when --reload is enabled (default: "src") [env: SRC_DIR]
|
|
41
|
+
|
|
42
|
+
**Environment Variables:**
|
|
43
|
+
- `APP_PATH`: The application module path
|
|
44
|
+
- All options support environment variables as indicated above
|
|
45
|
+
|
|
46
|
+
**Example with environment variables:**
|
|
47
|
+
```bash
|
|
48
|
+
export APP_PATH="app.module:app"
|
|
49
|
+
export BROKER_URL="amqp://guest:guest@localhost:5672/?exchange=jararaca&prefetch_count=1"
|
|
50
|
+
export BACKEND_URL="redis://localhost:6379"
|
|
51
|
+
export HANDLERS="send_email,process_payment"
|
|
52
|
+
export RELOAD="true"
|
|
53
|
+
jararaca worker
|
|
54
|
+
```
|
|
55
|
+
- `--reload`: Enable auto-reload when Python files change (for development)
|
|
56
|
+
- `--src-dir`: The source directory to watch for changes when --reload is enabled (default: "src")
|
|
39
57
|
|
|
40
58
|
### `server` - HTTP Server
|
|
41
59
|
|
|
@@ -43,11 +61,39 @@ Starts a message bus worker that processes asynchronous messages from a message
|
|
|
43
61
|
jararaca server APP_PATH [OPTIONS]
|
|
44
62
|
```
|
|
45
63
|
|
|
46
|
-
#### Perfer `uvicorn` for production
|
|
47
|
-
|
|
48
64
|
Starts a FastAPI HTTP server for your microservice.
|
|
49
65
|
|
|
66
|
+
**Options:**
|
|
67
|
+
|
|
68
|
+
- `--host`: Host to bind the server (default: "0.0.0.0") [env: HOST]
|
|
69
|
+
- `--port`: Port to bind the server (default: 8000) [env: PORT]
|
|
70
|
+
|
|
71
|
+
**Environment Variables:**
|
|
72
|
+
- `APP_PATH`: The application module path
|
|
73
|
+
- `HOST`: Host to bind the server
|
|
74
|
+
- `PORT`: Port to bind the server
|
|
75
|
+
|
|
76
|
+
**Example with environment variables:**
|
|
77
|
+
```bash
|
|
78
|
+
export APP_PATH="app.module:app"
|
|
79
|
+
export HOST="127.0.0.1"
|
|
80
|
+
export PORT="8080"
|
|
81
|
+
jararaca server
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Alternative: Using `uvicorn` directly
|
|
85
|
+
|
|
86
|
+
For production environments, you can create an ASGI application and run it with uvicorn:
|
|
87
|
+
|
|
50
88
|
```python
|
|
89
|
+
from fastapi import FastAPI
|
|
90
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
91
|
+
from fastapi.types import Lifespan
|
|
92
|
+
|
|
93
|
+
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
94
|
+
from jararaca.presentation.server import create_http_server
|
|
95
|
+
|
|
96
|
+
|
|
51
97
|
def fastapi_factory(lifespan: Lifespan[FastAPI]) -> FastAPI:
|
|
52
98
|
app = FastAPI(
|
|
53
99
|
lifespan=lifespan,
|
|
@@ -78,26 +124,37 @@ Then run the server with:
|
|
|
78
124
|
uvicorn app_module:asgi_app
|
|
79
125
|
```
|
|
80
126
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
**Options:**
|
|
84
|
-
|
|
85
|
-
- `--host`: Host to bind the server (default: "0.0.0.0")
|
|
86
|
-
- `--port`: Port to bind the server (default: 8000)
|
|
87
|
-
|
|
88
|
-
### `scheduler` - Task Scheduler
|
|
127
|
+
### `beat` - Task Scheduler
|
|
89
128
|
|
|
90
129
|
```bash
|
|
91
|
-
jararaca
|
|
130
|
+
jararaca beat APP_PATH [OPTIONS]
|
|
92
131
|
```
|
|
93
132
|
|
|
94
133
|
Runs scheduled tasks defined in your application using cron expressions.
|
|
95
134
|
|
|
96
135
|
**Options:**
|
|
97
136
|
|
|
98
|
-
- `--interval`: Polling interval in seconds (default: 1)
|
|
137
|
+
- `--interval`: Polling interval in seconds (default: 1) [env: INTERVAL]
|
|
138
|
+
- `--broker-url`: The URL for the message broker (required) [env: BROKER_URL]
|
|
139
|
+
- `--backend-url`: The URL for the message broker backend (required) [env: BACKEND_URL]
|
|
140
|
+
- `--actions`: Comma-separated list of action names to run (optional) [env: ACTIONS]
|
|
141
|
+
- `--reload`: Enable auto-reload when Python files change (for development) [env: RELOAD]
|
|
142
|
+
- `--src-dir`: The source directory to watch for changes when --reload is enabled (default: "src") [env: SRC_DIR]
|
|
99
143
|
|
|
100
|
-
|
|
144
|
+
**Environment Variables:**
|
|
145
|
+
- `APP_PATH`: The application module path
|
|
146
|
+
- All options support environment variables as indicated above
|
|
147
|
+
|
|
148
|
+
**Example with environment variables:**
|
|
149
|
+
```bash
|
|
150
|
+
export APP_PATH="app.module:app"
|
|
151
|
+
export INTERVAL="5"
|
|
152
|
+
export BROKER_URL="amqp://guest:guest@localhost:5672/?exchange=jararaca&prefetch_count=1"
|
|
153
|
+
export BACKEND_URL="redis://localhost:6379"
|
|
154
|
+
export ACTIONS="send_emails,process_payments"
|
|
155
|
+
export RELOAD="true"
|
|
156
|
+
jararaca beat
|
|
157
|
+
```
|
|
101
158
|
|
|
102
159
|
```bash
|
|
103
160
|
jararaca scheduler_v2 APP_PATH [OPTIONS]
|
|
@@ -121,8 +178,14 @@ Generates TypeScript interfaces from your Python models to ensure type safety be
|
|
|
121
178
|
|
|
122
179
|
**Options:**
|
|
123
180
|
|
|
124
|
-
- `--watch`: Watch for file changes and regenerate TypeScript interfaces automatically
|
|
125
|
-
- `--src-dir`: Source directory to watch for changes (default: "src")
|
|
181
|
+
- `--watch`: Watch for file changes and regenerate TypeScript interfaces automatically [env: WATCH]
|
|
182
|
+
- `--src-dir`: Source directory to watch for changes (default: "src") [env: SRC_DIR]
|
|
183
|
+
- `--stdout`: Print generated interfaces to stdout instead of writing to a file [env: STDOUT]
|
|
184
|
+
- `--post-process`: Command to run after generating the interfaces, {file} will be replaced with the output file path [env: POST_PROCESS]
|
|
185
|
+
|
|
186
|
+
**Environment Variables:**
|
|
187
|
+
- `APP_PATH`: The application module path
|
|
188
|
+
- All options support environment variables as indicated above
|
|
126
189
|
|
|
127
190
|
**Example with watch mode:**
|
|
128
191
|
|
|
@@ -132,6 +195,15 @@ jararaca gen-tsi app.module:app interfaces.ts --watch
|
|
|
132
195
|
|
|
133
196
|
This will generate the TypeScript interfaces initially and then watch for any changes to Python files in the src directory, automatically regenerating the interfaces when changes are detected. You can stop watching with Ctrl+C.
|
|
134
197
|
|
|
198
|
+
**Example with environment variables:**
|
|
199
|
+
```bash
|
|
200
|
+
export APP_PATH="app.module:app"
|
|
201
|
+
export FILE_PATH="interfaces.ts"
|
|
202
|
+
export WATCH="true"
|
|
203
|
+
export SRC_DIR="src"
|
|
204
|
+
jararaca gen-tsi
|
|
205
|
+
```
|
|
206
|
+
|
|
135
207
|
**Note:** To use the watch feature, you need to install the watchdog package:
|
|
136
208
|
|
|
137
209
|
```bash
|
|
@@ -152,6 +224,57 @@ jararaca gen-entity ENTITY_NAME FILE_PATH
|
|
|
152
224
|
|
|
153
225
|
Generates a new entity file template with proper naming conventions in different formats (snake_case, PascalCase, kebab-case).
|
|
154
226
|
|
|
227
|
+
**Environment Variables:**
|
|
228
|
+
- `ENTITY_NAME`: The name of the entity to generate
|
|
229
|
+
- `FILE_PATH`: The path where the entity file should be created
|
|
230
|
+
|
|
231
|
+
**Example:**
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Using command line arguments
|
|
235
|
+
jararaca gen-entity User user.py
|
|
236
|
+
|
|
237
|
+
# Using environment variables
|
|
238
|
+
export ENTITY_NAME="User"
|
|
239
|
+
export FILE_PATH="user.py"
|
|
240
|
+
jararaca gen-entity
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `declare` - Declare Message Infrastructure
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
jararaca declare APP_PATH [OPTIONS]
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Declares RabbitMQ infrastructure (exchanges and queues) for message handlers and schedulers without starting the actual consumption processes.
|
|
250
|
+
|
|
251
|
+
**Options:**
|
|
252
|
+
- `--broker-url`: Broker URL (e.g., amqp://guest:guest@localhost/) [env: BROKER_URL]
|
|
253
|
+
- `-i, --interactive-mode`: Enable interactive mode for queue declaration [env: INTERACTIVE_MODE]
|
|
254
|
+
- `-f, --force`: Force recreation by deleting existing exchanges and queues [env: FORCE]
|
|
255
|
+
|
|
256
|
+
**Environment Variables:**
|
|
257
|
+
- `APP_PATH`: The application module path
|
|
258
|
+
- `BROKER_URL`: The broker URL
|
|
259
|
+
- `INTERACTIVE_MODE`: Enable interactive mode
|
|
260
|
+
- `FORCE`: Force recreation of infrastructure
|
|
261
|
+
|
|
262
|
+
**Examples:**
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Declare infrastructure
|
|
266
|
+
jararaca declare myapp:app --broker-url amqp://guest:guest@localhost/
|
|
267
|
+
|
|
268
|
+
# Force recreation of queues and exchanges
|
|
269
|
+
jararaca declare myapp:app --broker-url amqp://guest:guest@localhost/ --force
|
|
270
|
+
|
|
271
|
+
# Using environment variables
|
|
272
|
+
export APP_PATH="myapp:app"
|
|
273
|
+
export BROKER_URL="amqp://guest:guest@localhost/"
|
|
274
|
+
export FORCE="true"
|
|
275
|
+
jararaca declare
|
|
276
|
+
```
|
|
277
|
+
|
|
155
278
|
## Quick Start
|
|
156
279
|
|
|
157
280
|
Here's a basic example of how to create a microservice with Jararaca:
|
|
@@ -29,6 +29,7 @@ graph TB
|
|
|
29
29
|
ack[ack]
|
|
30
30
|
nack[nack]
|
|
31
31
|
retry[retry]
|
|
32
|
+
retry_later[retry_later]
|
|
32
33
|
reject[reject]
|
|
33
34
|
end
|
|
34
35
|
|
|
@@ -42,6 +43,7 @@ graph TB
|
|
|
42
43
|
BusMessageController --> nack
|
|
43
44
|
BusMessageController --> reject
|
|
44
45
|
BusMessageController --> retry
|
|
46
|
+
BusMessageController --> retry_later
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
## Message Structure
|
|
@@ -453,12 +455,30 @@ jararaca worker APP_PATH [OPTIONS]
|
|
|
453
455
|
|
|
454
456
|
Options:
|
|
455
457
|
|
|
456
|
-
- `--url`:
|
|
457
|
-
- `--
|
|
458
|
-
- `--
|
|
459
|
-
- `--
|
|
460
|
-
- `--
|
|
461
|
-
|
|
458
|
+
- `--broker-url`: The URL for the message broker (required) [env: BROKER_URL]
|
|
459
|
+
- `--backend-url`: The URL for the message broker backend (required) [env: BACKEND_URL]
|
|
460
|
+
- `--handlers`: Comma-separated list of handler names to listen to (optional) [env: HANDLERS]
|
|
461
|
+
- `--reload`: Enable auto-reload when Python files change (for development) [env: RELOAD]
|
|
462
|
+
- `--src-dir`: The source directory to watch for changes when --reload is enabled (default: "src") [env: SRC_DIR]
|
|
463
|
+
|
|
464
|
+
Examples:
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
# Standard worker execution
|
|
468
|
+
jararaca worker myapp.main:app --broker-url "amqp://guest:guest@localhost:5672/?exchange=jararaca" --backend-url "redis://localhost:6379"
|
|
469
|
+
|
|
470
|
+
# With auto-reload for development
|
|
471
|
+
jararaca worker myapp.main:app --broker-url "amqp://guest:guest@localhost:5672/?exchange=jararaca" --backend-url "redis://localhost:6379" --reload
|
|
472
|
+
|
|
473
|
+
# Using environment variables
|
|
474
|
+
export APP_PATH="myapp.main:app"
|
|
475
|
+
export BROKER_URL="amqp://guest:guest@localhost:5672/?exchange=jararaca"
|
|
476
|
+
export BACKEND_URL="redis://localhost:6379"
|
|
477
|
+
export RELOAD="true"
|
|
478
|
+
export SRC_DIR="src"
|
|
479
|
+
export RELOAD="true"
|
|
480
|
+
jararaca worker
|
|
481
|
+
```
|
|
462
482
|
|
|
463
483
|
## Conclusion
|
|
464
484
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Retry Mechanism with Exponential Backoff
|
|
2
|
+
|
|
3
|
+
Jararaca implements a robust retry mechanism with exponential backoff for handling transient failures in RabbitMQ connections and operations. This mechanism helps the system gracefully handle temporary network issues, broker unavailability, and other transient failures.
|
|
4
|
+
|
|
5
|
+
## Core Components
|
|
6
|
+
|
|
7
|
+
The retry system consists of these main components:
|
|
8
|
+
|
|
9
|
+
1. `RetryConfig` - Configuration class for customizing retry behavior
|
|
10
|
+
2. `retry_with_backoff` - Utility function to execute operations with retry
|
|
11
|
+
3. `with_retry` - Decorator for applying retry logic to functions
|
|
12
|
+
|
|
13
|
+
## Retry Configuration
|
|
14
|
+
|
|
15
|
+
The `RetryConfig` class allows customization of various retry parameters:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
class RetryConfig:
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
max_retries: int = 5, # Maximum number of retry attempts
|
|
22
|
+
initial_delay: float = 1.0, # Initial delay between retries (seconds)
|
|
23
|
+
max_delay: float = 60.0, # Maximum delay between retries (seconds)
|
|
24
|
+
backoff_factor: float = 2.0, # Multiplier for delay after each retry
|
|
25
|
+
jitter: bool = True, # Add randomness to delay to prevent thundering herd
|
|
26
|
+
):
|
|
27
|
+
...
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Integration with MessageBus Worker
|
|
31
|
+
|
|
32
|
+
The RabbitMQ consumer in the message bus system uses the retry mechanism in several key areas:
|
|
33
|
+
|
|
34
|
+
1. **Connection Establishment**: When establishing a connection to RabbitMQ, the system will automatically retry with increasing backoff periods if the connection fails.
|
|
35
|
+
|
|
36
|
+
2. **Channel Creation**: When creating channels for publishing or consuming messages, failures trigger the retry mechanism.
|
|
37
|
+
|
|
38
|
+
3. **Consumer Setup**: Setting up message consumers uses retry logic to handle temporary failures.
|
|
39
|
+
|
|
40
|
+
## URL Configuration Parameters
|
|
41
|
+
|
|
42
|
+
Retry behavior can be customized through URL parameters when configuring the RabbitMQ connection:
|
|
43
|
+
|
|
44
|
+
| Parameter | Description | Default |
|
|
45
|
+
|-----------|-------------|---------|
|
|
46
|
+
| `connection_retry_max` | Maximum number of connection retry attempts | 5 |
|
|
47
|
+
| `connection_retry_delay` | Initial delay between connection retries (seconds) | 1.0 |
|
|
48
|
+
| `connection_retry_max_delay` | Maximum delay between connection retries (seconds) | 60.0 |
|
|
49
|
+
| `connection_retry_backoff` | Multiplier for delay after each connection retry | 2.0 |
|
|
50
|
+
| `consumer_retry_max` | Maximum number of consumer setup retry attempts | 3 |
|
|
51
|
+
| `consumer_retry_delay` | Initial delay between consumer setup retries (seconds) | 0.5 |
|
|
52
|
+
| `consumer_retry_max_delay` | Maximum delay between consumer setup retries (seconds) | 5.0 |
|
|
53
|
+
| `consumer_retry_backoff` | Multiplier for delay after each consumer setup retry | 2.0 |
|
|
54
|
+
|
|
55
|
+
## Example Usage
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# Configure with custom retry settings in URL:
|
|
59
|
+
broker_url = "amqp://guest:guest@localhost:5672/?exchange=jararaca&prefetch_count=10&connection_retry_max=10&connection_retry_delay=2.0"
|
|
60
|
+
|
|
61
|
+
# Use custom retry configuration in code:
|
|
62
|
+
from jararaca.utils.retry import RetryConfig, retry_with_backoff
|
|
63
|
+
|
|
64
|
+
config = RetryConfig(max_retries=3, initial_delay=1.0, max_delay=30.0)
|
|
65
|
+
|
|
66
|
+
async def connect_with_retry():
|
|
67
|
+
return await retry_with_backoff(
|
|
68
|
+
establish_connection,
|
|
69
|
+
retry_config=config,
|
|
70
|
+
retry_exceptions=(ConnectionError, TimeoutError)
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Benefits
|
|
75
|
+
|
|
76
|
+
1. **Resilience** - The system can recover automatically from transient failures
|
|
77
|
+
2. **Reduced downtime** - Automatic reconnection minimizes service disruption
|
|
78
|
+
3. **Configuration flexibility** - Retry behavior can be tailored to different environments
|
|
79
|
+
4. **Smart backoff** - Exponential backoff with jitter prevents overloading services during recovery
|
|
@@ -12,22 +12,16 @@ The Jararaca scheduler allows you to:
|
|
|
12
12
|
- Distribute scheduled tasks across multiple instances
|
|
13
13
|
- Handle delayed message execution
|
|
14
14
|
|
|
15
|
-
The scheduler
|
|
16
|
-
1. **Basic Scheduler** - Simple scheduler for local execution
|
|
17
|
-
2. **Enhanced Scheduler (V2)** - Distributed scheduler with improved backend support and message broker integration
|
|
15
|
+
The scheduler is implemented through the BeatWorker which provides distributed task scheduling via a message broker:
|
|
18
16
|
|
|
19
17
|
```mermaid
|
|
20
18
|
graph TD
|
|
21
|
-
A[Microservice] --> B[
|
|
22
|
-
B --> C[
|
|
23
|
-
B --> D[
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
D -->
|
|
27
|
-
F --> G[Workers]
|
|
28
|
-
D --> H[Backend Store]
|
|
29
|
-
H --> I[Last Execution Time]
|
|
30
|
-
H --> J[Delayed Messages]
|
|
19
|
+
A[Microservice] --> B[BeatWorker]
|
|
20
|
+
B --> C[Message Broker]
|
|
21
|
+
B --> D[Backend Store]
|
|
22
|
+
C --> E[Message Processing]
|
|
23
|
+
D --> F[Last Execution Time]
|
|
24
|
+
D --> G[Delayed Messages]
|
|
31
25
|
```
|
|
32
26
|
|
|
33
27
|
## Using the Scheduler
|
|
@@ -73,31 +67,57 @@ Jararaca uses standard cron expressions for scheduling. Here are some examples:
|
|
|
73
67
|
- `0 0 * * 0` - Run at midnight every Sunday
|
|
74
68
|
- `0 0 1 * *` - Run at midnight on the first day of every month
|
|
75
69
|
|
|
76
|
-
##
|
|
70
|
+
## Using the BeatWorker Scheduler
|
|
77
71
|
|
|
78
|
-
The
|
|
72
|
+
The BeatWorker scheduler provides distributed task execution through a message broker:
|
|
79
73
|
|
|
80
74
|
```python
|
|
81
75
|
from jararaca import Microservice, ScheduledAction
|
|
76
|
+
from jararaca.scheduler.beat_worker import BeatWorker
|
|
82
77
|
|
|
83
78
|
app = Microservice(
|
|
84
79
|
# Your microservice configuration
|
|
85
80
|
)
|
|
86
81
|
|
|
87
82
|
# Run the scheduler
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
beat_worker = BeatWorker(
|
|
84
|
+
app=app,
|
|
85
|
+
interval=1,
|
|
86
|
+
backend_url="redis://localhost:6379",
|
|
87
|
+
broker_url="amqp://guest:guest@localhost:5672/?exchange=jararaca",
|
|
88
|
+
scheduled_action_names=None # Optional set of action names to run
|
|
89
|
+
)
|
|
90
|
+
beat_worker.run()
|
|
92
91
|
```
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
You can also use the CLI command to run the scheduler:
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
```bash
|
|
96
|
+
# Standard beat scheduler execution
|
|
97
|
+
jararaca beat app_module:app --interval 1 --broker-url "amqp://guest:guest@localhost:5672/?exchange=jararaca" --backend-url "redis://localhost:6379"
|
|
98
|
+
|
|
99
|
+
# With auto-reload for development (automatically restarts when Python files change)
|
|
100
|
+
jararaca beat app_module:app --interval 1 --broker-url "amqp://guest:guest@localhost:5672/?exchange=jararaca" --backend-url "redis://localhost:6379" --reload
|
|
101
|
+
|
|
102
|
+
# Using environment variables
|
|
103
|
+
export APP_PATH="app_module:app"
|
|
104
|
+
export INTERVAL="1"
|
|
105
|
+
export BROKER_URL="amqp://guest:guest@localhost:5672/?exchange=jararaca"
|
|
106
|
+
export BACKEND_URL="redis://localhost:6379"
|
|
107
|
+
export RELOAD="true"
|
|
108
|
+
export SRC_DIR="src"
|
|
109
|
+
jararaca beat
|
|
110
|
+
```
|
|
97
111
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
112
|
+
All command options support environment variables:
|
|
113
|
+
- `APP_PATH`: The application module path [required]
|
|
114
|
+
- `INTERVAL`: Polling interval in seconds [default: 1]
|
|
115
|
+
- `BROKER_URL`: The URL for the message broker [required]
|
|
116
|
+
- `BACKEND_URL`: The URL for the message broker backend [required]
|
|
117
|
+
- `ACTIONS`: Comma-separated list of action names to run [optional]
|
|
118
|
+
- `RELOAD`: Enable auto-reload when Python files change [optional]
|
|
119
|
+
- `SRC_DIR`: The source directory to watch for changes when using reload [default: "src"]
|
|
120
|
+
```
|
|
101
121
|
|
|
102
122
|
app = Microservice(
|
|
103
123
|
# Your microservice configuration
|
|
@@ -57,24 +57,38 @@ class WebSocketMessage(WebSocketMessageBase):
|
|
|
57
57
|
|
|
58
58
|
### 3. WebSocketConnectionManager
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
A Protocol that defines the interface for managing WebSocket connections:
|
|
61
61
|
|
|
62
|
+
```python
|
|
63
|
+
class WebSocketConnectionManager(Protocol):
|
|
64
|
+
async def broadcast(self, message: bytes) -> None: ...
|
|
65
|
+
async def send(self, rooms: list[str], message: WebSocketMessageBase) -> None: ...
|
|
66
|
+
async def join(self, rooms: list[str], websocket: WebSocket) -> None: ...
|
|
67
|
+
async def add_websocket(self, websocket: WebSocket) -> None: ...
|
|
68
|
+
async def remove_websocket(self, websocket: WebSocket) -> None: ...
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The WebSocketConnectionManager:
|
|
62
72
|
- Maintains a registry of active WebSocket connections
|
|
63
73
|
- Groups connections into named rooms
|
|
64
74
|
- Provides methods for broadcasting and sending targeted messages
|
|
65
75
|
|
|
66
|
-
### 4.
|
|
76
|
+
### 4. Context-based WebSocket Access
|
|
67
77
|
|
|
68
|
-
|
|
78
|
+
Jararaca uses context variables to provide access to WebSocket functionality anywhere in your application:
|
|
69
79
|
|
|
70
80
|
```python
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
|
|
81
|
+
from jararaca.presentation.websocket.context import use_ws_manager, use_ws_message_sender
|
|
82
|
+
|
|
83
|
+
# Send a message to specific rooms
|
|
84
|
+
async def notify_users(message_data: dict, room_id: str):
|
|
85
|
+
message = UserNotificationMessage(**message_data)
|
|
86
|
+
await use_ws_message_sender().send([room_id], message)
|
|
87
|
+
|
|
88
|
+
# Or directly from a WebSocketMessage instance
|
|
89
|
+
async def send_update(update_data: dict, room_id: str):
|
|
90
|
+
message = SystemUpdateMessage(**update_data)
|
|
91
|
+
await message.send(room_id)
|
|
78
92
|
```
|
|
79
93
|
|
|
80
94
|
### 5. RedisWebSocketConnectionBackend
|