jararaca 0.2.33__tar.gz → 0.3.27__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.
Potentially problematic release.
This version of jararaca might be problematic. Click here for more details.
- jararaca-0.3.27/PKG-INFO +159 -0
- jararaca-0.3.27/README.md +121 -0
- jararaca-0.3.27/docs/CNAME +1 -0
- jararaca-0.3.27/docs/architecture.md +372 -0
- jararaca-0.3.27/docs/expose-type.md +221 -0
- jararaca-0.3.27/docs/http-rpc.md +564 -0
- jararaca-0.3.27/docs/index.md +675 -0
- jararaca-0.3.27/docs/interceptors.md +210 -0
- jararaca-0.3.27/docs/messagebus.md +485 -0
- jararaca-0.3.27/docs/retry.md +79 -0
- jararaca-0.3.27/docs/scheduler.md +239 -0
- jararaca-0.3.27/docs/stylesheets/custom.css +5 -0
- jararaca-0.3.27/docs/websocket.md +362 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/pyproject.toml +53 -4
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/__init__.py +274 -16
- jararaca-0.3.27/src/jararaca/broker_backend/__init__.py +102 -0
- jararaca-0.3.27/src/jararaca/broker_backend/mapper.py +21 -0
- jararaca-0.3.27/src/jararaca/broker_backend/redis_broker_backend.py +162 -0
- jararaca-0.3.27/src/jararaca/cli.py +1022 -0
- jararaca-0.3.27/src/jararaca/core/uow.py +99 -0
- jararaca-0.3.27/src/jararaca/messagebus/__init__.py +3 -0
- jararaca-0.3.27/src/jararaca/messagebus/bus_message_controller.py +67 -0
- jararaca-0.3.27/src/jararaca/messagebus/decorators.py +176 -0
- jararaca-0.3.27/src/jararaca/messagebus/implicit_headers.py +45 -0
- jararaca-0.3.27/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +185 -0
- jararaca-0.3.27/src/jararaca/messagebus/interceptors/publisher_interceptor.py +38 -0
- jararaca-0.3.27/src/jararaca/messagebus/message.py +27 -0
- jararaca-0.3.27/src/jararaca/messagebus/publisher.py +78 -0
- jararaca-0.3.27/src/jararaca/messagebus/worker.py +1778 -0
- jararaca-0.3.27/src/jararaca/microservice.py +418 -0
- jararaca-0.3.27/src/jararaca/observability/decorators.py +235 -0
- jararaca-0.3.27/src/jararaca/observability/hooks.py +86 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/observability/interceptor.py +4 -2
- jararaca-0.3.27/src/jararaca/observability/providers/otel.py +323 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/persistence/base.py +2 -1
- jararaca-0.3.27/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +224 -0
- jararaca-0.3.27/src/jararaca/persistence/interceptors/constants.py +1 -0
- jararaca-0.3.27/src/jararaca/persistence/interceptors/decorators.py +45 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/persistence/sort_filter.py +2 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/persistence/utilities.py +58 -22
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/decorators.py +148 -22
- jararaca-0.3.27/src/jararaca/presentation/server.py +196 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/websocket/context.py +30 -4
- jararaca-0.3.27/src/jararaca/presentation/websocket/redis.py +376 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/websocket/types.py +2 -2
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/websocket/websocket_interceptor.py +63 -16
- jararaca-0.3.27/src/jararaca/reflect/controller_inspect.py +75 -0
- {jararaca-0.2.33/src/jararaca/tools → jararaca-0.3.27/src/jararaca/reflect}/metadata.py +25 -5
- jararaca-0.3.27/src/jararaca/rpc/http/__init__.py +97 -0
- jararaca-0.3.27/src/jararaca/rpc/http/backends/__init__.py +10 -0
- jararaca-0.3.27/src/jararaca/rpc/http/backends/httpx.py +71 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/rpc/http/decorators.py +302 -6
- jararaca-0.3.27/src/jararaca/scheduler/beat_worker.py +802 -0
- jararaca-0.3.27/src/jararaca/scheduler/decorators.py +131 -0
- jararaca-0.3.27/src/jararaca/scheduler/types.py +7 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/tools/app_config/interceptor.py +4 -2
- jararaca-0.3.27/src/jararaca/tools/typescript/decorators.py +141 -0
- jararaca-0.3.27/src/jararaca/tools/typescript/interface_parser.py +1682 -0
- jararaca-0.3.27/src/jararaca/utils/rabbitmq_utils.py +346 -0
- jararaca-0.3.27/src/jararaca/utils/retry.py +141 -0
- jararaca-0.2.33/PKG-INFO +0 -278
- jararaca-0.2.33/README.md +0 -243
- jararaca-0.2.33/docs/Architecture/Observability/Decorators.md +0 -0
- jararaca-0.2.33/docs/Architecture/Observability/Interceptors.md +0 -0
- jararaca-0.2.33/docs/Architecture/Presentation/Decorators.md +0 -0
- jararaca-0.2.33/docs/Architecture/RPC/RestClients/Decorators.md +0 -0
- jararaca-0.2.33/docs/Architecture/RPC/RestClients/Middlewared.md +0 -0
- jararaca-0.2.33/docs/Architecture/Schedule/Decorators.md +0 -0
- jararaca-0.2.33/docs/Architecture/Websocket/Decorators.md +0 -0
- jararaca-0.2.33/docs/Architecture/Websocket/Interceptors.md +0 -0
- jararaca-0.2.33/docs/Concept/Adapters.md +0 -0
- jararaca-0.2.33/docs/Concept/Hexagonal Architecture.md +0 -0
- jararaca-0.2.33/docs/Concept/Ports.md +0 -0
- jararaca-0.2.33/docs/index.md +0 -518
- jararaca-0.2.33/src/jararaca/cli.py +0 -251
- jararaca-0.2.33/src/jararaca/core/uow.py +0 -66
- jararaca-0.2.33/src/jararaca/messagebus/__init__.py +0 -3
- jararaca-0.2.33/src/jararaca/messagebus/decorators.py +0 -134
- jararaca-0.2.33/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -76
- jararaca-0.2.33/src/jararaca/messagebus/publisher.py +0 -41
- jararaca-0.2.33/src/jararaca/messagebus/types.py +0 -30
- jararaca-0.2.33/src/jararaca/messagebus/worker.py +0 -376
- jararaca-0.2.33/src/jararaca/microservice.py +0 -243
- jararaca-0.2.33/src/jararaca/observability/decorators.py +0 -93
- jararaca-0.2.33/src/jararaca/observability/providers/otel.py +0 -182
- jararaca-0.2.33/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -64
- jararaca-0.2.33/src/jararaca/presentation/server.py +0 -117
- jararaca-0.2.33/src/jararaca/presentation/websocket/redis.py +0 -155
- jararaca-0.2.33/src/jararaca/rpc/http/backends/httpx.py +0 -41
- jararaca-0.2.33/src/jararaca/scheduler/decorators.py +0 -63
- jararaca-0.2.33/src/jararaca/scheduler/scheduler.py +0 -154
- jararaca-0.2.33/src/jararaca/tools/typescript/interface_parser.py +0 -821
- {jararaca-0.2.33 → jararaca-0.3.27}/LICENSE +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/__main__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/di.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.2.33/src/jararaca/messagebus/interceptors → jararaca-0.3.27/src/jararaca/messagebus/consumers}/__init__.py +0 -0
- {jararaca-0.2.33/src/jararaca/observability/providers → jararaca-0.3.27/src/jararaca/messagebus/interceptors}/__init__.py +0 -0
- {jararaca-0.2.33/src/jararaca/persistence/interceptors → jararaca-0.3.27/src/jararaca/observability/providers}/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.2.33/src/jararaca/presentation → jararaca-0.3.27/src/jararaca/persistence/interceptors}/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.2.33/src/jararaca/presentation/websocket → jararaca-0.3.27/src/jararaca/presentation}/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.2.33/src/jararaca/rpc → jararaca-0.3.27/src/jararaca/presentation/websocket}/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/py.typed +0 -0
- {jararaca-0.2.33/src/jararaca/rpc/http → jararaca-0.3.27/src/jararaca/reflect}/__init__.py +0 -0
- {jararaca-0.2.33/src/jararaca/rpc/http/backends → jararaca-0.3.27/src/jararaca/rpc}/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.2.33 → jararaca-0.3.27}/src/jararaca/tools/app_config/decorators.py +0 -0
- /jararaca-0.2.33/docs/Architecture/Message Bus/Decorators.md → /jararaca-0.3.27/src/jararaca/tools/typescript/__init__.py +0 -0
- /jararaca-0.2.33/docs/Architecture/Message Bus/Interceptors.md → /jararaca-0.3.27/src/jararaca/utils/__init__.py +0 -0
jararaca-0.3.27/PKG-INFO
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: jararaca
|
|
3
|
+
Version: 0.3.27
|
|
4
|
+
Summary: A simple and fast API framework for Python
|
|
5
|
+
Home-page: https://github.com/LuscasLeo/jararaca
|
|
6
|
+
Author: Lucas S
|
|
7
|
+
Author-email: me@luscasleo.dev
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Provides-Extra: docs
|
|
13
|
+
Provides-Extra: http
|
|
14
|
+
Provides-Extra: opentelemetry
|
|
15
|
+
Provides-Extra: watch
|
|
16
|
+
Requires-Dist: aio-pika (>=9.4.3,<10.0.0)
|
|
17
|
+
Requires-Dist: croniter (>=3.0.3,<4.0.0)
|
|
18
|
+
Requires-Dist: fastapi (>=0.113.0,<0.114.0)
|
|
19
|
+
Requires-Dist: frozendict (>=2.4.6,<3.0.0)
|
|
20
|
+
Requires-Dist: mako (>=1.3.5,<2.0.0)
|
|
21
|
+
Requires-Dist: opentelemetry-api (>=1.38.0,<2.0.0) ; extra == "opentelemetry"
|
|
22
|
+
Requires-Dist: opentelemetry-distro (>=0.59b0,<0.60) ; extra == "opentelemetry"
|
|
23
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
24
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
25
|
+
Requires-Dist: opentelemetry-sdk (>=1.38.0,<2.0.0) ; extra == "opentelemetry"
|
|
26
|
+
Requires-Dist: redis (>=5.0.8,<6.0.0)
|
|
27
|
+
Requires-Dist: sqlalchemy (>=2.0.34,<3.0.0)
|
|
28
|
+
Requires-Dist: types-croniter (>=3.0.3.20240731,<4.0.0.0)
|
|
29
|
+
Requires-Dist: types-redis (>=4.6.0.20240903,<5.0.0.0)
|
|
30
|
+
Requires-Dist: urllib3 (>=2.3.0,<3.0.0)
|
|
31
|
+
Requires-Dist: uvicorn (>=0.30.6,<0.31.0)
|
|
32
|
+
Requires-Dist: uvloop (>=0.20.0,<0.21.0)
|
|
33
|
+
Requires-Dist: watchdog (>=3.0.0,<4.0.0) ; extra == "watch"
|
|
34
|
+
Requires-Dist: websockets (>=13.0.1,<14.0.0)
|
|
35
|
+
Project-URL: Repository, https://github.com/LuscasLeo/jararaca
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
<img src="https://raw.githubusercontent.com/LuscasLeo/jararaca/main/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg" alt="Jararaca Logo" width="250" float="right">
|
|
39
|
+
|
|
40
|
+
# Jararaca Microservice Framework
|
|
41
|
+
|
|
42
|
+
## Overview
|
|
43
|
+
|
|
44
|
+
Jararaca is an async-first microservice framework designed to simplify the development of distributed systems. It provides a comprehensive set of tools for building robust, scalable, and maintainable microservices with a focus on developer experience and type safety.
|
|
45
|
+
|
|
46
|
+
## Key Features
|
|
47
|
+
|
|
48
|
+
### REST API Development
|
|
49
|
+
- Easy-to-use interfaces for building REST APIs
|
|
50
|
+
- Automatic request/response validation
|
|
51
|
+
- Type-safe endpoints with FastAPI integration
|
|
52
|
+
- Automatic OpenAPI documentation generation
|
|
53
|
+
|
|
54
|
+
### Message Bus Integration
|
|
55
|
+
- Topic-based message bus for event-driven architecture
|
|
56
|
+
- Support for both worker and publisher patterns
|
|
57
|
+
- Built-in message serialization and deserialization
|
|
58
|
+
- Easy integration with AIO Pika for RabbitMQ
|
|
59
|
+
|
|
60
|
+
### Distributed WebSocket
|
|
61
|
+
- Room-based WebSocket communication
|
|
62
|
+
- Distributed broadcasting across multiple backend instances
|
|
63
|
+
- Automatic message synchronization between instances
|
|
64
|
+
- Built-in connection management and room handling
|
|
65
|
+
|
|
66
|
+
### Task Scheduling
|
|
67
|
+
- Cron-based task scheduling
|
|
68
|
+
- Support for overlapping and non-overlapping tasks
|
|
69
|
+
- Distributed task execution
|
|
70
|
+
- Easy integration with message bus for task distribution
|
|
71
|
+
|
|
72
|
+
### TypeScript Integration
|
|
73
|
+
- Automatic TypeScript interface generation
|
|
74
|
+
- Command-line tool for generating TypeScript types
|
|
75
|
+
- Support for REST endpoints, WebSocket events, and message bus payloads
|
|
76
|
+
- Type-safe frontend-backend communication
|
|
77
|
+
- **`@ExposeType` decorator** - Explicitly expose types for TypeScript generation without needing them in endpoints
|
|
78
|
+
|
|
79
|
+
### Hexagonal Architecture
|
|
80
|
+
- Clear separation of concerns
|
|
81
|
+
- Business logic isolation from infrastructure
|
|
82
|
+
- Easy testing and maintainability
|
|
83
|
+
- Dependency injection for flexible component management
|
|
84
|
+
|
|
85
|
+
### Observability
|
|
86
|
+
- Built-in OpenTelemetry integration
|
|
87
|
+
- Distributed tracing support
|
|
88
|
+
- Logging and metrics collection
|
|
89
|
+
- Performance monitoring capabilities
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
### Installation
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install jararaca
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Basic Usage
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from jararaca import Microservice, create_http_server
|
|
103
|
+
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
104
|
+
|
|
105
|
+
# Define your microservice
|
|
106
|
+
app = Microservice(
|
|
107
|
+
providers=[
|
|
108
|
+
# Add your providers here
|
|
109
|
+
],
|
|
110
|
+
controllers=[
|
|
111
|
+
# Add your controllers here
|
|
112
|
+
],
|
|
113
|
+
interceptors=[
|
|
114
|
+
# Add your interceptors here
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Create HTTP server
|
|
119
|
+
http_app = HttpMicroservice(app)
|
|
120
|
+
web_app = create_http_server(app)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Running the Service
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Run as HTTP server
|
|
127
|
+
jararaca server app:http_app
|
|
128
|
+
|
|
129
|
+
# Run as message bus worker
|
|
130
|
+
jararaca worker app:app
|
|
131
|
+
|
|
132
|
+
# Run as scheduler
|
|
133
|
+
jararaca scheduler app:app
|
|
134
|
+
|
|
135
|
+
# Generate TypeScript interfaces
|
|
136
|
+
jararaca gen-tsi app.main:app app.ts
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
For detailed documentation, please visit our [documentation site](https://luscasleo.github.io/jararaca/).
|
|
142
|
+
|
|
143
|
+
## Examples
|
|
144
|
+
|
|
145
|
+
Check out the [examples directory](examples/) for complete working examples of:
|
|
146
|
+
- REST API implementation
|
|
147
|
+
- WebSocket usage
|
|
148
|
+
- Message bus integration
|
|
149
|
+
- Task scheduling
|
|
150
|
+
- TypeScript interface generation
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
Contributions are welcome! Please read our [contributing guidelines](.github/CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
159
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<img src="https://raw.githubusercontent.com/LuscasLeo/jararaca/main/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg" alt="Jararaca Logo" width="250" float="right">
|
|
2
|
+
|
|
3
|
+
# Jararaca Microservice Framework
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Jararaca is an async-first microservice framework designed to simplify the development of distributed systems. It provides a comprehensive set of tools for building robust, scalable, and maintainable microservices with a focus on developer experience and type safety.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
### REST API Development
|
|
12
|
+
- Easy-to-use interfaces for building REST APIs
|
|
13
|
+
- Automatic request/response validation
|
|
14
|
+
- Type-safe endpoints with FastAPI integration
|
|
15
|
+
- Automatic OpenAPI documentation generation
|
|
16
|
+
|
|
17
|
+
### Message Bus Integration
|
|
18
|
+
- Topic-based message bus for event-driven architecture
|
|
19
|
+
- Support for both worker and publisher patterns
|
|
20
|
+
- Built-in message serialization and deserialization
|
|
21
|
+
- Easy integration with AIO Pika for RabbitMQ
|
|
22
|
+
|
|
23
|
+
### Distributed WebSocket
|
|
24
|
+
- Room-based WebSocket communication
|
|
25
|
+
- Distributed broadcasting across multiple backend instances
|
|
26
|
+
- Automatic message synchronization between instances
|
|
27
|
+
- Built-in connection management and room handling
|
|
28
|
+
|
|
29
|
+
### Task Scheduling
|
|
30
|
+
- Cron-based task scheduling
|
|
31
|
+
- Support for overlapping and non-overlapping tasks
|
|
32
|
+
- Distributed task execution
|
|
33
|
+
- Easy integration with message bus for task distribution
|
|
34
|
+
|
|
35
|
+
### TypeScript Integration
|
|
36
|
+
- Automatic TypeScript interface generation
|
|
37
|
+
- Command-line tool for generating TypeScript types
|
|
38
|
+
- Support for REST endpoints, WebSocket events, and message bus payloads
|
|
39
|
+
- Type-safe frontend-backend communication
|
|
40
|
+
- **`@ExposeType` decorator** - Explicitly expose types for TypeScript generation without needing them in endpoints
|
|
41
|
+
|
|
42
|
+
### Hexagonal Architecture
|
|
43
|
+
- Clear separation of concerns
|
|
44
|
+
- Business logic isolation from infrastructure
|
|
45
|
+
- Easy testing and maintainability
|
|
46
|
+
- Dependency injection for flexible component management
|
|
47
|
+
|
|
48
|
+
### Observability
|
|
49
|
+
- Built-in OpenTelemetry integration
|
|
50
|
+
- Distributed tracing support
|
|
51
|
+
- Logging and metrics collection
|
|
52
|
+
- Performance monitoring capabilities
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install jararaca
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Basic Usage
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from jararaca import Microservice, create_http_server
|
|
66
|
+
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
67
|
+
|
|
68
|
+
# Define your microservice
|
|
69
|
+
app = Microservice(
|
|
70
|
+
providers=[
|
|
71
|
+
# Add your providers here
|
|
72
|
+
],
|
|
73
|
+
controllers=[
|
|
74
|
+
# Add your controllers here
|
|
75
|
+
],
|
|
76
|
+
interceptors=[
|
|
77
|
+
# Add your interceptors here
|
|
78
|
+
],
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Create HTTP server
|
|
82
|
+
http_app = HttpMicroservice(app)
|
|
83
|
+
web_app = create_http_server(app)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Running the Service
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Run as HTTP server
|
|
90
|
+
jararaca server app:http_app
|
|
91
|
+
|
|
92
|
+
# Run as message bus worker
|
|
93
|
+
jararaca worker app:app
|
|
94
|
+
|
|
95
|
+
# Run as scheduler
|
|
96
|
+
jararaca scheduler app:app
|
|
97
|
+
|
|
98
|
+
# Generate TypeScript interfaces
|
|
99
|
+
jararaca gen-tsi app.main:app app.ts
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Documentation
|
|
103
|
+
|
|
104
|
+
For detailed documentation, please visit our [documentation site](https://luscasleo.github.io/jararaca/).
|
|
105
|
+
|
|
106
|
+
## Examples
|
|
107
|
+
|
|
108
|
+
Check out the [examples directory](examples/) for complete working examples of:
|
|
109
|
+
- REST API implementation
|
|
110
|
+
- WebSocket usage
|
|
111
|
+
- Message bus integration
|
|
112
|
+
- Task scheduling
|
|
113
|
+
- TypeScript interface generation
|
|
114
|
+
|
|
115
|
+
## Contributing
|
|
116
|
+
|
|
117
|
+
Contributions are welcome! Please read our [contributing guidelines](.github/CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jararaca.luscasleo.dev
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# Jararaca Architecture
|
|
2
|
+
|
|
3
|
+
## Core Concept: Unified Runtime Interface
|
|
4
|
+
|
|
5
|
+
Jararaca implements a unified runtime interface that allows different types of applications (REST API, Message Bus Worker, and Scheduler) to share the same utilities and context. This means that utilities like `@use_session` can be used consistently across different runtime contexts, even though they run as separate processes.
|
|
6
|
+
|
|
7
|
+
## Runtime Types
|
|
8
|
+
|
|
9
|
+
1. **REST API Runtime**
|
|
10
|
+
|
|
11
|
+
- Handles HTTP requests and WebSocket connections
|
|
12
|
+
- Executes REST controllers
|
|
13
|
+
- Uses `@RestController` decorator for route definitions
|
|
14
|
+
|
|
15
|
+
2. **Message Bus Worker Runtime**
|
|
16
|
+
|
|
17
|
+
- Processes asynchronous messages and events
|
|
18
|
+
- Handles tasks and events through `@MessageBusController`
|
|
19
|
+
- Manages message queues and event processing
|
|
20
|
+
|
|
21
|
+
3. **Scheduler Runtime**
|
|
22
|
+
- Executes scheduled tasks at specified intervals
|
|
23
|
+
- Uses `@ScheduledAction` decorator for task definitions
|
|
24
|
+
- Manages cron-based job execution
|
|
25
|
+
|
|
26
|
+
## Application Structure
|
|
27
|
+
|
|
28
|
+
The application structure follows a hierarchical pattern:
|
|
29
|
+
|
|
30
|
+
1. **Microservice Declaration**
|
|
31
|
+
|
|
32
|
+
- Uses `@Microservice` class for configuration
|
|
33
|
+
- Declares providers, controllers, and interceptors
|
|
34
|
+
- No execution happens at declaration time
|
|
35
|
+
- Configuration is shared across all runtimes
|
|
36
|
+
|
|
37
|
+
2. **Application Implementation**
|
|
38
|
+
|
|
39
|
+
- **REST Controllers** (`@RestController`)
|
|
40
|
+
|
|
41
|
+
- Handle HTTP endpoints
|
|
42
|
+
- Run in REST API runtime
|
|
43
|
+
- Support middleware and dependency injection
|
|
44
|
+
|
|
45
|
+
- **Events and Tasks** (`@MessageBusController`)
|
|
46
|
+
|
|
47
|
+
- Handle asynchronous operations
|
|
48
|
+
- Run in Message Bus Worker runtime
|
|
49
|
+
- Support message publishing and consumption
|
|
50
|
+
|
|
51
|
+
- **Scheduled Jobs** (`@ScheduledAction`)
|
|
52
|
+
- Execute at specified intervals
|
|
53
|
+
- Run in Scheduler runtime
|
|
54
|
+
- Support cron-based scheduling
|
|
55
|
+
|
|
56
|
+
## Architecture Diagram
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
graph LR
|
|
60
|
+
subgraph "Runtime Layer"
|
|
61
|
+
REST[REST API Runtime]
|
|
62
|
+
Worker[Message Bus Worker Runtime]
|
|
63
|
+
Scheduler[Scheduler Runtime]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subgraph "Application Layer"
|
|
67
|
+
Microservice[Microservice Declaration]
|
|
68
|
+
RESTController[REST Controllers]
|
|
69
|
+
MessageBus[Events & Tasks]
|
|
70
|
+
ScheduledJobs[Scheduled Jobs]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
subgraph "Shared Utilities"
|
|
74
|
+
Session[use_session]
|
|
75
|
+
Publisher[use_publisher]
|
|
76
|
+
WS[use_ws_manager]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Microservice --> REST
|
|
80
|
+
Microservice --> Worker
|
|
81
|
+
Microservice --> Scheduler
|
|
82
|
+
|
|
83
|
+
REST --> RESTController
|
|
84
|
+
Worker --> MessageBus
|
|
85
|
+
Scheduler --> ScheduledJobs
|
|
86
|
+
|
|
87
|
+
RESTController --> Session
|
|
88
|
+
MessageBus --> Session
|
|
89
|
+
ScheduledJobs --> Session
|
|
90
|
+
|
|
91
|
+
RESTController --> Publisher
|
|
92
|
+
MessageBus --> Publisher
|
|
93
|
+
ScheduledJobs --> Publisher
|
|
94
|
+
|
|
95
|
+
RESTController --> WS
|
|
96
|
+
MessageBus --> WS
|
|
97
|
+
ScheduledJobs --> WS
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Key Features
|
|
101
|
+
|
|
102
|
+
1. **Shared Context**
|
|
103
|
+
|
|
104
|
+
- All runtimes share the same context and utilities
|
|
105
|
+
- Consistent access to services like database sessions
|
|
106
|
+
- Unified dependency injection system
|
|
107
|
+
|
|
108
|
+
2. **Declarative Configuration**
|
|
109
|
+
|
|
110
|
+
- Configuration is defined once in `Microservice`
|
|
111
|
+
- Runtime-specific settings are handled separately
|
|
112
|
+
- Easy to maintain and modify
|
|
113
|
+
|
|
114
|
+
3. **Process Isolation**
|
|
115
|
+
|
|
116
|
+
- Each runtime runs as a separate process
|
|
117
|
+
- Clear separation of concerns
|
|
118
|
+
- Independent scaling and deployment
|
|
119
|
+
|
|
120
|
+
4. **Unified Utilities**
|
|
121
|
+
- Common utilities like `@use_session` work across all runtimes
|
|
122
|
+
- Consistent API for database access, message publishing, etc.
|
|
123
|
+
- Reduced code duplication
|
|
124
|
+
|
|
125
|
+
## Usage Example
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from jararaca import (
|
|
129
|
+
AIOPikaConnectionFactory,
|
|
130
|
+
AIOSQAConfig,
|
|
131
|
+
AIOSqlAlchemySessionInterceptor,
|
|
132
|
+
AppConfigurationInterceptor,
|
|
133
|
+
HttpMicroservice,
|
|
134
|
+
MessageBusPublisherInterceptor,
|
|
135
|
+
Microservice,
|
|
136
|
+
ProviderSpec,
|
|
137
|
+
RedisWebSocketConnectionBackend,
|
|
138
|
+
Token,
|
|
139
|
+
WebSocketInterceptor,
|
|
140
|
+
create_http_server,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Define your application configuration
|
|
145
|
+
class AppConfig:
|
|
146
|
+
DATABASE_URL: str
|
|
147
|
+
REDIS_URL: str
|
|
148
|
+
AMQP_URL: str
|
|
149
|
+
|
|
150
|
+
# Create the microservice with all necessary components
|
|
151
|
+
app = Microservice(
|
|
152
|
+
providers=[
|
|
153
|
+
ProviderSpec(
|
|
154
|
+
provide=Token(Redis, "REDIS"),
|
|
155
|
+
use_factory=lambda config: Redis.from_url(config.REDIS_URL, decode_responses=False),
|
|
156
|
+
after_interceptors=True,
|
|
157
|
+
),
|
|
158
|
+
],
|
|
159
|
+
controllers=[
|
|
160
|
+
TasksController, # Your controller class
|
|
161
|
+
],
|
|
162
|
+
interceptors=[
|
|
163
|
+
# Configuration interceptor
|
|
164
|
+
AppConfigurationInterceptor(
|
|
165
|
+
global_configs=[
|
|
166
|
+
(Token(AppConfig, "APP_CONFIG"), AppConfig),
|
|
167
|
+
]
|
|
168
|
+
),
|
|
169
|
+
# Message bus interceptor
|
|
170
|
+
AppFactoryWithAppConfig(
|
|
171
|
+
lambda config: MessageBusPublisherInterceptor(
|
|
172
|
+
connection_factory=AIOPikaConnectionFactory(
|
|
173
|
+
url=config.AMQP_URL,
|
|
174
|
+
exchange="jararaca_ex",
|
|
175
|
+
),
|
|
176
|
+
)
|
|
177
|
+
),
|
|
178
|
+
# Database session interceptor
|
|
179
|
+
AppFactoryWithAppConfig(
|
|
180
|
+
lambda config: AIOSqlAlchemySessionInterceptor(
|
|
181
|
+
AIOSQAConfig(
|
|
182
|
+
connection_name="default",
|
|
183
|
+
url=config.DATABASE_URL,
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
),
|
|
187
|
+
# WebSocket interceptor
|
|
188
|
+
AppFactoryWithAppConfig(
|
|
189
|
+
lambda config: WebSocketInterceptor(
|
|
190
|
+
backend=RedisWebSocketConnectionBackend(
|
|
191
|
+
send_pubsub_channel="jararaca:websocket:send",
|
|
192
|
+
broadcast_pubsub_channel="jararaca:websocket:broadcast",
|
|
193
|
+
conn=Redis.from_url(config.REDIS_URL, decode_responses=False),
|
|
194
|
+
)
|
|
195
|
+
),
|
|
196
|
+
),
|
|
197
|
+
],
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Create HTTP server for REST API runtime
|
|
201
|
+
http_app = create_http_server(
|
|
202
|
+
HttpMicroservice(
|
|
203
|
+
app=app,
|
|
204
|
+
factory=fastapi_factory,
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class HelloTask(Message):
|
|
210
|
+
MESSAGE_TYPE = "task"
|
|
211
|
+
MESSAGE_TOPIC = "task.topic.name"
|
|
212
|
+
|
|
213
|
+
message: str
|
|
214
|
+
|
|
215
|
+
# Example controller showing unified utilities across runtimes
|
|
216
|
+
@MessageBusController()
|
|
217
|
+
@RestController("/tasks")
|
|
218
|
+
class TasksController:
|
|
219
|
+
def __init__(self, redis: Annotated[Redis, Token(Redis, "REDIS")]):
|
|
220
|
+
self.redis = redis
|
|
221
|
+
self.tasks_crud = CRUDOperations(TaskEntity, use_session)
|
|
222
|
+
|
|
223
|
+
@Post("/")
|
|
224
|
+
async def create_task(self, task: CreateTaskSchema) -> Identifiable[TaskSchema]:
|
|
225
|
+
# Use session in REST context
|
|
226
|
+
task_entity = await self.tasks_crud.create(task)
|
|
227
|
+
await use_ws_manager().broadcast(b"New Task Created")
|
|
228
|
+
await use_publisher().publish(task_entity.to_identifiable(TaskSchema), topic="task")
|
|
229
|
+
return task_entity.to_identifiable(TaskSchema)
|
|
230
|
+
|
|
231
|
+
@MessageHandler(HelloTask)
|
|
232
|
+
async def process_task(self, message: MessageOf[HelloTask]) -> None:
|
|
233
|
+
# Use session in Message Bus context
|
|
234
|
+
print(message.message)
|
|
235
|
+
|
|
236
|
+
@ScheduledAction("* * * * * */5")
|
|
237
|
+
async def scheduled_task(self) -> None:
|
|
238
|
+
# Use session in Scheduler context
|
|
239
|
+
pending_tasks = await use_session().execute(select(TaskEntity))
|
|
240
|
+
for task in pending_tasks:
|
|
241
|
+
await use_publisher().publish(task.to_identifiable(TaskSchema), topic="task")
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Context Hooks and Interceptors
|
|
245
|
+
|
|
246
|
+
Jararaca provides a powerful system of context hooks (like `use_session`, `use_publisher`, `use_ws_manager`) that are managed through Python's `ContextVar` system. These hooks are configured separately for each execution context and are provided by interceptors configured in the `Microservice` instance.
|
|
247
|
+
|
|
248
|
+
> **Important Note on Interceptor Order**
|
|
249
|
+
> The order of interceptors in the `Microservice` instance matters significantly. Interceptors are executed in the order they are defined, meaning:
|
|
250
|
+
>
|
|
251
|
+
> - The first interceptor in the list will set up its context before the subsequent ones
|
|
252
|
+
> - This order affects how dependencies between different context hooks are resolved
|
|
253
|
+
> - For example, if a database session is needed by a message publisher, the session interceptor should be configured before the publisher interceptor
|
|
254
|
+
|
|
255
|
+
### How Context Hooks Work
|
|
256
|
+
|
|
257
|
+
1. **Context Isolation**
|
|
258
|
+
|
|
259
|
+
- Each execution (HTTP request, message processing, scheduled job) gets its own isolated context
|
|
260
|
+
- Context hooks provide access to resources specific to that execution
|
|
261
|
+
- Resources are automatically cleaned up when the execution completes
|
|
262
|
+
|
|
263
|
+
2. **Interceptor-Based Provision**
|
|
264
|
+
- Interceptors are responsible for setting up and managing the context
|
|
265
|
+
- They are configured in the `Microservice` instance
|
|
266
|
+
- Each interceptor handles a specific type of resource
|
|
267
|
+
|
|
268
|
+
### Example: Database Session Management
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
# The AIOSqlAlchemySessionInterceptor manages database sessions
|
|
272
|
+
class AIOSqlAlchemySessionInterceptor(AppInterceptor):
|
|
273
|
+
def __init__(self, config: AIOSQAConfig):
|
|
274
|
+
self.config = config
|
|
275
|
+
self.engine = create_async_engine(self.config.url)
|
|
276
|
+
self.sessionmaker = async_sessionmaker(self.engine)
|
|
277
|
+
|
|
278
|
+
@asynccontextmanager
|
|
279
|
+
async def intercept(self, app_context: AppContext) -> AsyncGenerator[None, None]:
|
|
280
|
+
# Creates a new session for this execution
|
|
281
|
+
async with self.sessionmaker() as session:
|
|
282
|
+
# Provides the session to the context
|
|
283
|
+
with provide_session(self.config.connection_name, session):
|
|
284
|
+
try:
|
|
285
|
+
yield
|
|
286
|
+
await session.commit()
|
|
287
|
+
except Exception as e:
|
|
288
|
+
await session.rollback()
|
|
289
|
+
raise e
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Context Hook Lifecycle
|
|
293
|
+
|
|
294
|
+
1. **Configuration**
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
app = Microservice(
|
|
298
|
+
interceptors=[
|
|
299
|
+
AIOSqlAlchemySessionInterceptor(
|
|
300
|
+
AIOSQAConfig(
|
|
301
|
+
connection_name="default",
|
|
302
|
+
url=config.DATABASE_URL,
|
|
303
|
+
)
|
|
304
|
+
),
|
|
305
|
+
# Other interceptors...
|
|
306
|
+
]
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
2. **Execution**
|
|
311
|
+
|
|
312
|
+
- When a request/message/job starts, interceptors are activated
|
|
313
|
+
- Each interceptor sets up its context using `ContextVar`
|
|
314
|
+
- The context is available throughout the execution
|
|
315
|
+
|
|
316
|
+
3. **Cleanup**
|
|
317
|
+
- When execution completes, interceptors clean up resources
|
|
318
|
+
- Context is automatically reset
|
|
319
|
+
- Resources are properly closed/released
|
|
320
|
+
|
|
321
|
+
### Available Context Hooks
|
|
322
|
+
|
|
323
|
+
1. **Database Sessions** (`use_session`)
|
|
324
|
+
|
|
325
|
+
- Provided by `AIOSqlAlchemySessionInterceptor`
|
|
326
|
+
- Creates isolated database sessions per execution
|
|
327
|
+
- Handles transaction management automatically
|
|
328
|
+
|
|
329
|
+
2. **Message Publishing** (`use_publisher`)
|
|
330
|
+
|
|
331
|
+
- Provided by `MessageBusPublisherInterceptor`
|
|
332
|
+
- Manages message publishing context
|
|
333
|
+
- Ensures proper message delivery
|
|
334
|
+
|
|
335
|
+
3. **WebSocket Management** (`use_ws_manager`)
|
|
336
|
+
- Provided by `WebSocketInterceptor`
|
|
337
|
+
- Handles WebSocket connections and broadcasting
|
|
338
|
+
- Manages connection state
|
|
339
|
+
|
|
340
|
+
### Usage in Different Contexts
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
# In a REST Controller
|
|
344
|
+
@RestController("/tasks")
|
|
345
|
+
@MessageBusController()
|
|
346
|
+
class TasksController:
|
|
347
|
+
@Get("/")
|
|
348
|
+
async def get_tasks(self):
|
|
349
|
+
# Gets a session specific to this HTTP request
|
|
350
|
+
session = use_session()
|
|
351
|
+
return await session.execute(select(TaskEntity))
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
@MessageHandler(SomeTask)
|
|
355
|
+
async def process_task(self, message: MessageOf[SomeTask]):
|
|
356
|
+
# Gets a session specific to this message processing
|
|
357
|
+
session = use_session()
|
|
358
|
+
|
|
359
|
+
# In a Scheduled Job
|
|
360
|
+
@ScheduledAction("* * * * *")
|
|
361
|
+
async def scheduled_task(self):
|
|
362
|
+
# Gets a session specific to this job execution
|
|
363
|
+
session = use_session()
|
|
364
|
+
await session.execute(select(TaskEntity))
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
This system ensures that:
|
|
368
|
+
|
|
369
|
+
- Each execution has its own isolated resources
|
|
370
|
+
- Resources are properly managed and cleaned up
|
|
371
|
+
- The same utilities can be used consistently across different runtime contexts
|
|
372
|
+
- Dependencies are properly injected and managed
|