jararaca 0.2.37a11__tar.gz → 0.2.37a12__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.

Files changed (87) hide show
  1. jararaca-0.2.37a12/PKG-INFO +154 -0
  2. jararaca-0.2.37a12/README.md +120 -0
  3. jararaca-0.2.37a12/docs/CNAME +1 -0
  4. jararaca-0.2.37a12/docs/architecture.md +372 -0
  5. jararaca-0.2.37a12/docs/index.md +535 -0
  6. jararaca-0.2.37a12/docs/messagebus.md +465 -0
  7. jararaca-0.2.37a12/docs/stylesheets/custom.css +5 -0
  8. jararaca-0.2.37a12/docs/websocket.md +348 -0
  9. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/pyproject.toml +2 -1
  10. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/cli.py +78 -4
  11. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/worker.py +11 -11
  12. jararaca-0.2.37a11/PKG-INFO +0 -278
  13. jararaca-0.2.37a11/README.md +0 -243
  14. jararaca-0.2.37a11/docs/Architecture/Message Bus/Decorators.md +0 -0
  15. jararaca-0.2.37a11/docs/Architecture/Message Bus/Interceptors.md +0 -0
  16. jararaca-0.2.37a11/docs/Architecture/Observability/Decorators.md +0 -0
  17. jararaca-0.2.37a11/docs/Architecture/Observability/Interceptors.md +0 -0
  18. jararaca-0.2.37a11/docs/Architecture/Presentation/Decorators.md +0 -0
  19. jararaca-0.2.37a11/docs/Architecture/RPC/RestClients/Decorators.md +0 -0
  20. jararaca-0.2.37a11/docs/Architecture/RPC/RestClients/Middlewared.md +0 -0
  21. jararaca-0.2.37a11/docs/Architecture/Schedule/Decorators.md +0 -0
  22. jararaca-0.2.37a11/docs/Architecture/Websocket/Decorators.md +0 -0
  23. jararaca-0.2.37a11/docs/Architecture/Websocket/Interceptors.md +0 -0
  24. jararaca-0.2.37a11/docs/Concept/Adapters.md +0 -0
  25. jararaca-0.2.37a11/docs/Concept/Hexagonal Architecture.md +0 -0
  26. jararaca-0.2.37a11/docs/Concept/Ports.md +0 -0
  27. jararaca-0.2.37a11/docs/index.md +0 -518
  28. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/LICENSE +0 -0
  29. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
  30. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
  31. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/docs/assets/tracing_example.png +0 -0
  32. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/__init__.py +0 -0
  33. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/__main__.py +0 -0
  34. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/common/__init__.py +0 -0
  35. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/core/__init__.py +0 -0
  36. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/core/providers.py +0 -0
  37. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/core/uow.py +0 -0
  38. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/di.py +0 -0
  39. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/files/entity.py.mako +0 -0
  40. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/lifecycle.py +0 -0
  41. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/__init__.py +0 -0
  42. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/bus_message_controller.py +0 -0
  43. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/decorators.py +0 -0
  44. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
  45. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
  46. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/publisher.py +0 -0
  47. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/messagebus/types.py +0 -0
  48. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/microservice.py +0 -0
  49. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/observability/decorators.py +0 -0
  50. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/observability/interceptor.py +0 -0
  51. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/observability/providers/__init__.py +0 -0
  52. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/observability/providers/otel.py +0 -0
  53. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/base.py +0 -0
  54. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/exports.py +0 -0
  55. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/interceptors/__init__.py +0 -0
  56. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
  57. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/session.py +0 -0
  58. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/sort_filter.py +0 -0
  59. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/persistence/utilities.py +0 -0
  60. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/__init__.py +0 -0
  61. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/decorators.py +0 -0
  62. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/hooks.py +0 -0
  63. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/http_microservice.py +0 -0
  64. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/server.py +0 -0
  65. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/__init__.py +0 -0
  66. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/base_types.py +0 -0
  67. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/context.py +0 -0
  68. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/decorators.py +0 -0
  69. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/redis.py +0 -0
  70. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/types.py +0 -0
  71. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
  72. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/py.typed +0 -0
  73. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/__init__.py +0 -0
  74. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/__init__.py +0 -0
  75. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/backends/__init__.py +0 -0
  76. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/backends/httpx.py +0 -0
  77. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/backends/otel.py +0 -0
  78. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/decorators.py +0 -0
  79. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/rpc/http/httpx.py +0 -0
  80. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/scheduler/__init__.py +0 -0
  81. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/scheduler/decorators.py +0 -0
  82. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/scheduler/scheduler.py +0 -0
  83. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/tools/app_config/__init__.py +0 -0
  84. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/tools/app_config/decorators.py +0 -0
  85. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/tools/app_config/interceptor.py +0 -0
  86. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/tools/metadata.py +0 -0
  87. {jararaca-0.2.37a11 → jararaca-0.2.37a12}/src/jararaca/tools/typescript/interface_parser.py +0 -0
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.3
2
+ Name: jararaca
3
+ Version: 0.2.37a12
4
+ Summary: A simple and fast API framework for Python
5
+ Author: Lucas S
6
+ Author-email: me@luscasleo.dev
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Provides-Extra: docs
13
+ Provides-Extra: http
14
+ Provides-Extra: opentelemetry
15
+ Requires-Dist: aio-pika (>=9.4.3,<10.0.0)
16
+ Requires-Dist: croniter (>=3.0.3,<4.0.0)
17
+ Requires-Dist: fastapi (>=0.113.0,<0.114.0)
18
+ Requires-Dist: mako (>=1.3.5,<2.0.0)
19
+ Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
20
+ Requires-Dist: opentelemetry-distro (>=0.49b2,<0.50) ; extra == "opentelemetry"
21
+ Requires-Dist: opentelemetry-exporter-otlp (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
22
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
23
+ Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
24
+ Requires-Dist: redis (>=5.0.8,<6.0.0)
25
+ Requires-Dist: sqlalchemy (>=2.0.34,<3.0.0)
26
+ Requires-Dist: types-croniter (>=3.0.3.20240731,<4.0.0.0)
27
+ Requires-Dist: types-redis (>=4.6.0.20240903,<5.0.0.0)
28
+ Requires-Dist: uvicorn (>=0.30.6,<0.31.0)
29
+ Requires-Dist: uvloop (>=0.20.0,<0.21.0)
30
+ Requires-Dist: websockets (>=13.0.1,<14.0.0)
31
+ Project-URL: Repository, https://github.com/LuscasLeo/jararaca
32
+ Description-Content-Type: text/markdown
33
+
34
+ <img src="https://raw.githubusercontent.com/LuscasLeo/jararaca/main/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg" alt="Jararaca Logo" width="250" float="right">
35
+
36
+ # Jararaca Microservice Framework
37
+
38
+ ## Overview
39
+
40
+ 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.
41
+
42
+ ## Key Features
43
+
44
+ ### REST API Development
45
+ - Easy-to-use interfaces for building REST APIs
46
+ - Automatic request/response validation
47
+ - Type-safe endpoints with FastAPI integration
48
+ - Automatic OpenAPI documentation generation
49
+
50
+ ### Message Bus Integration
51
+ - Topic-based message bus for event-driven architecture
52
+ - Support for both worker and publisher patterns
53
+ - Built-in message serialization and deserialization
54
+ - Easy integration with AIO Pika for RabbitMQ
55
+
56
+ ### Distributed WebSocket
57
+ - Room-based WebSocket communication
58
+ - Distributed broadcasting across multiple backend instances
59
+ - Automatic message synchronization between instances
60
+ - Built-in connection management and room handling
61
+
62
+ ### Task Scheduling
63
+ - Cron-based task scheduling
64
+ - Support for overlapping and non-overlapping tasks
65
+ - Distributed task execution
66
+ - Easy integration with message bus for task distribution
67
+
68
+ ### TypeScript Integration
69
+ - Automatic TypeScript interface generation
70
+ - Command-line tool for generating TypeScript types
71
+ - Support for REST endpoints, WebSocket events, and message bus payloads
72
+ - Type-safe frontend-backend communication
73
+
74
+ ### Hexagonal Architecture
75
+ - Clear separation of concerns
76
+ - Business logic isolation from infrastructure
77
+ - Easy testing and maintainability
78
+ - Dependency injection for flexible component management
79
+
80
+ ### Observability
81
+ - Built-in OpenTelemetry integration
82
+ - Distributed tracing support
83
+ - Logging and metrics collection
84
+ - Performance monitoring capabilities
85
+
86
+ ## Quick Start
87
+
88
+ ### Installation
89
+
90
+ ```bash
91
+ pip install jararaca
92
+ ```
93
+
94
+ ### Basic Usage
95
+
96
+ ```python
97
+ from jararaca import Microservice, create_http_server
98
+ from jararaca.presentation.http_microservice import HttpMicroservice
99
+
100
+ # Define your microservice
101
+ app = Microservice(
102
+ providers=[
103
+ # Add your providers here
104
+ ],
105
+ controllers=[
106
+ # Add your controllers here
107
+ ],
108
+ interceptors=[
109
+ # Add your interceptors here
110
+ ],
111
+ )
112
+
113
+ # Create HTTP server
114
+ http_app = HttpMicroservice(app)
115
+ web_app = create_http_server(app)
116
+ ```
117
+
118
+ ### Running the Service
119
+
120
+ ```bash
121
+ # Run as HTTP server
122
+ jararaca server app:http_app
123
+
124
+ # Run as message bus worker
125
+ jararaca worker app:app
126
+
127
+ # Run as scheduler
128
+ jararaca scheduler app:app
129
+
130
+ # Generate TypeScript interfaces
131
+ jararaca gen-tsi app.main:app app.ts
132
+ ```
133
+
134
+ ## Documentation
135
+
136
+ For detailed documentation, please visit our [documentation site](https://luscasleo.github.io/jararaca/).
137
+
138
+ ## Examples
139
+
140
+ Check out the [examples directory](examples/) for complete working examples of:
141
+ - REST API implementation
142
+ - WebSocket usage
143
+ - Message bus integration
144
+ - Task scheduling
145
+ - TypeScript interface generation
146
+
147
+ ## Contributing
148
+
149
+ 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.
150
+
151
+ ## License
152
+
153
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
154
+
@@ -0,0 +1,120 @@
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
+
41
+ ### Hexagonal Architecture
42
+ - Clear separation of concerns
43
+ - Business logic isolation from infrastructure
44
+ - Easy testing and maintainability
45
+ - Dependency injection for flexible component management
46
+
47
+ ### Observability
48
+ - Built-in OpenTelemetry integration
49
+ - Distributed tracing support
50
+ - Logging and metrics collection
51
+ - Performance monitoring capabilities
52
+
53
+ ## Quick Start
54
+
55
+ ### Installation
56
+
57
+ ```bash
58
+ pip install jararaca
59
+ ```
60
+
61
+ ### Basic Usage
62
+
63
+ ```python
64
+ from jararaca import Microservice, create_http_server
65
+ from jararaca.presentation.http_microservice import HttpMicroservice
66
+
67
+ # Define your microservice
68
+ app = Microservice(
69
+ providers=[
70
+ # Add your providers here
71
+ ],
72
+ controllers=[
73
+ # Add your controllers here
74
+ ],
75
+ interceptors=[
76
+ # Add your interceptors here
77
+ ],
78
+ )
79
+
80
+ # Create HTTP server
81
+ http_app = HttpMicroservice(app)
82
+ web_app = create_http_server(app)
83
+ ```
84
+
85
+ ### Running the Service
86
+
87
+ ```bash
88
+ # Run as HTTP server
89
+ jararaca server app:http_app
90
+
91
+ # Run as message bus worker
92
+ jararaca worker app:app
93
+
94
+ # Run as scheduler
95
+ jararaca scheduler app:app
96
+
97
+ # Generate TypeScript interfaces
98
+ jararaca gen-tsi app.main:app app.ts
99
+ ```
100
+
101
+ ## Documentation
102
+
103
+ For detailed documentation, please visit our [documentation site](https://luscasleo.github.io/jararaca/).
104
+
105
+ ## Examples
106
+
107
+ Check out the [examples directory](examples/) for complete working examples of:
108
+ - REST API implementation
109
+ - WebSocket usage
110
+ - Message bus integration
111
+ - Task scheduling
112
+ - TypeScript interface generation
113
+
114
+ ## Contributing
115
+
116
+ 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.
117
+
118
+ ## License
119
+
120
+ 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