jararaca 0.3.11a8__tar.gz → 0.3.11a9__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.11a8 → jararaca-0.3.11a9}/PKG-INFO +1 -1
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/pyproject.toml +1 -1
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/cli.py +72 -350
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/decorators.py +1 -1
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker.py +28 -32
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker_v2.py +36 -26
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/microservice.py +76 -16
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler_v2.py +8 -19
- jararaca-0.3.11a9/src/jararaca/utils/rabbitmq_utils.py +392 -0
- jararaca-0.3.11a8/src/jararaca/utils/rabbitmq_utils.py +0 -170
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/LICENSE +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/README.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/CNAME +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/architecture.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/index.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/messagebus.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/scheduler.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/stylesheets/custom.css +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/websocket.md +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/__main__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/mapper.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/di.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/consumers/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/message.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/py.typed +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/controller_inspect.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/metadata.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/types.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/typescript/interface_parser.py +0 -0
- {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/utils/__init__.py +0 -0
|
@@ -8,7 +8,7 @@ import time
|
|
|
8
8
|
from codecs import StreamWriter
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any
|
|
11
|
-
from urllib.parse import urlparse, urlunsplit
|
|
11
|
+
from urllib.parse import parse_qs, urlparse, urlunsplit
|
|
12
12
|
|
|
13
13
|
import aio_pika
|
|
14
14
|
import click
|
|
@@ -17,10 +17,12 @@ from mako.template import Template
|
|
|
17
17
|
|
|
18
18
|
from jararaca.messagebus import worker as worker_v1
|
|
19
19
|
from jararaca.messagebus import worker_v2 as worker_v2_mod
|
|
20
|
-
from jararaca.messagebus.decorators import
|
|
20
|
+
from jararaca.messagebus.decorators import MessageBusController, MessageHandler
|
|
21
21
|
from jararaca.microservice import Microservice
|
|
22
22
|
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
23
23
|
from jararaca.presentation.server import create_http_server
|
|
24
|
+
from jararaca.reflect.controller_inspect import inspect_controller
|
|
25
|
+
from jararaca.scheduler.decorators import ScheduledAction
|
|
24
26
|
from jararaca.scheduler.scheduler import Scheduler
|
|
25
27
|
from jararaca.scheduler.scheduler_v2 import SchedulerV2
|
|
26
28
|
from jararaca.tools.typescript.interface_parser import (
|
|
@@ -71,96 +73,17 @@ def find_microservice_by_module_path(module_path: str) -> Microservice:
|
|
|
71
73
|
return app
|
|
72
74
|
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
url: str,
|
|
76
|
-
exchange: str,
|
|
77
|
-
app: Microservice,
|
|
78
|
-
passive_declare: bool = False,
|
|
79
|
-
handler_names: set[str] | None = None,
|
|
80
|
-
force: bool = False,
|
|
81
|
-
) -> None:
|
|
82
|
-
"""
|
|
83
|
-
Declare the infrastructure (exchanges and queues) for worker v1.
|
|
84
|
-
"""
|
|
85
|
-
connection = await aio_pika.connect(url)
|
|
86
|
-
channel = await connection.channel()
|
|
87
|
-
|
|
88
|
-
# Force delete infrastructure if requested
|
|
89
|
-
if force:
|
|
90
|
-
click.echo(f"→ Force deleting existing infrastructure for exchange: {exchange}")
|
|
91
|
-
await RabbitmqUtils.delete_exchange(channel, exchange)
|
|
92
|
-
await RabbitmqUtils.delete_exchange(channel, RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
93
|
-
await RabbitmqUtils.delete_queue(channel, RabbitmqUtils.DEAD_LETTER_QUEUE)
|
|
94
|
-
|
|
95
|
-
# Declare main exchange
|
|
96
|
-
main_ex = await RabbitmqUtils.declare_main_exchange(
|
|
97
|
-
channel=channel,
|
|
98
|
-
exchange_name=exchange,
|
|
99
|
-
passive=passive_declare,
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
# Declare dead letter infrastructure
|
|
103
|
-
dlx, dlq = await RabbitmqUtils.declare_dl_kit(
|
|
104
|
-
channel=channel, passive=passive_declare
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
# Find all message handlers to declare their queues
|
|
108
|
-
from jararaca.di import Container
|
|
109
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
76
|
+
# The v1 infrastructure declaration function has been removed as part of the CLI simplification
|
|
110
77
|
|
|
111
|
-
container = Container(app)
|
|
112
78
|
|
|
113
|
-
|
|
114
|
-
controller = MessageBusController.get_messagebus(instance_type)
|
|
115
|
-
if controller is None:
|
|
116
|
-
continue
|
|
117
|
-
|
|
118
|
-
instance: Any = container.get_by_type(instance_type)
|
|
119
|
-
factory = controller.get_messagebus_factory()
|
|
120
|
-
handlers, _ = factory(instance)
|
|
121
|
-
|
|
122
|
-
for handler in handlers:
|
|
123
|
-
# Filter handlers by name if specified
|
|
124
|
-
if handler_names is not None and handler.spec.name is not None:
|
|
125
|
-
if handler.spec.name not in handler_names:
|
|
126
|
-
continue
|
|
127
|
-
elif handler_names is not None and handler.spec.name is None:
|
|
128
|
-
# Skip handlers without names when filtering is requested
|
|
129
|
-
continue
|
|
130
|
-
|
|
131
|
-
queue_name = f"{handler.message_type.MESSAGE_TOPIC}.{handler.instance_callable.__module__}.{handler.instance_callable.__qualname__}"
|
|
132
|
-
routing_key = f"{handler.message_type.MESSAGE_TOPIC}.#"
|
|
133
|
-
|
|
134
|
-
# Force delete queue if requested
|
|
135
|
-
if force:
|
|
136
|
-
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
137
|
-
|
|
138
|
-
queue = await RabbitmqUtils.declare_worker_v1_queue(
|
|
139
|
-
channel=channel,
|
|
140
|
-
queue_name=queue_name,
|
|
141
|
-
dlx_name=dlx.name,
|
|
142
|
-
dlq_name=dlq.name,
|
|
143
|
-
passive=passive_declare,
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
await queue.bind(exchange=main_ex, routing_key=routing_key)
|
|
147
|
-
click.echo(f"✓ Declared queue: {queue_name} (routing key: {routing_key})")
|
|
148
|
-
|
|
149
|
-
await channel.close()
|
|
150
|
-
await connection.close()
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
async def declare_worker_v2_infrastructure(
|
|
79
|
+
async def declare_worker_infrastructure(
|
|
154
80
|
broker_url: str,
|
|
155
81
|
app: Microservice,
|
|
156
|
-
passive_declare: bool = False,
|
|
157
|
-
handler_names: set[str] | None = None,
|
|
158
82
|
force: bool = False,
|
|
159
83
|
) -> None:
|
|
160
84
|
"""
|
|
161
|
-
Declare the infrastructure (exchanges and queues) for worker
|
|
85
|
+
Declare the infrastructure (exchanges and queues) for worker.
|
|
162
86
|
"""
|
|
163
|
-
from urllib.parse import parse_qs, urlparse
|
|
164
87
|
|
|
165
88
|
parsed_url = urlparse(broker_url)
|
|
166
89
|
if parsed_url.scheme not in ["amqp", "amqps"]:
|
|
@@ -186,170 +109,70 @@ async def declare_worker_v2_infrastructure(
|
|
|
186
109
|
await RabbitmqUtils.delete_exchange(channel, RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
187
110
|
await RabbitmqUtils.delete_queue(channel, RabbitmqUtils.DEAD_LETTER_QUEUE)
|
|
188
111
|
|
|
189
|
-
# Declare main exchange
|
|
190
112
|
await RabbitmqUtils.declare_main_exchange(
|
|
191
113
|
channel=channel,
|
|
192
114
|
exchange_name=exchange,
|
|
193
|
-
passive=
|
|
115
|
+
passive=not force, # If force is True, we already deleted the exchange
|
|
194
116
|
)
|
|
195
117
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
channel=channel, passive=passive_declare
|
|
199
|
-
)
|
|
200
|
-
dlq = await RabbitmqUtils.declare_dl_queue(channel=channel, passive=passive_declare)
|
|
118
|
+
dlx = await RabbitmqUtils.declare_dl_exchange(channel=channel, passive=not force)
|
|
119
|
+
dlq = await RabbitmqUtils.declare_dl_queue(channel=channel, passive=not force)
|
|
201
120
|
await dlq.bind(dlx, routing_key=RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
202
121
|
|
|
203
122
|
# Find all message handlers and scheduled actions
|
|
204
|
-
from jararaca.di import Container
|
|
205
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
206
|
-
|
|
207
|
-
container = Container(app)
|
|
208
123
|
|
|
209
124
|
for instance_type in app.controllers:
|
|
210
|
-
|
|
211
|
-
if
|
|
125
|
+
controller_spec = MessageBusController.get_messagebus(instance_type)
|
|
126
|
+
if controller_spec is None:
|
|
212
127
|
continue
|
|
213
128
|
|
|
214
|
-
|
|
215
|
-
factory = controller.get_messagebus_factory()
|
|
216
|
-
handlers, scheduled_actions = factory(instance)
|
|
129
|
+
_, members = inspect_controller(instance_type)
|
|
217
130
|
|
|
218
131
|
# Declare queues for message handlers
|
|
219
|
-
for
|
|
220
|
-
# Filter handlers by name if specified
|
|
221
|
-
if handler_names is not None and handler.spec.name is not None:
|
|
222
|
-
if handler.spec.name not in handler_names:
|
|
223
|
-
continue
|
|
224
|
-
elif handler_names is not None and handler.spec.name is None:
|
|
225
|
-
# Skip handlers without names when filtering is requested
|
|
226
|
-
continue
|
|
227
|
-
|
|
228
|
-
queue_name = f"{handler.message_type.MESSAGE_TOPIC}.{handler.instance_callable.__module__}.{handler.instance_callable.__qualname__}"
|
|
229
|
-
routing_key = f"{handler.message_type.MESSAGE_TOPIC}.#"
|
|
230
|
-
|
|
231
|
-
# Force delete queue if requested
|
|
232
|
-
if force:
|
|
233
|
-
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
234
|
-
|
|
235
|
-
queue = await RabbitmqUtils.declare_queue(
|
|
236
|
-
channel=channel, queue_name=queue_name, passive=passive_declare
|
|
237
|
-
)
|
|
238
|
-
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
239
|
-
click.echo(
|
|
240
|
-
f"✓ Declared message handler queue: {queue_name} (routing key: {routing_key})"
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
# Declare queues for scheduled actions
|
|
244
|
-
for scheduled_action in scheduled_actions:
|
|
245
|
-
queue_name = f"{scheduled_action.callable.__module__}.{scheduled_action.callable.__qualname__}"
|
|
246
|
-
routing_key = queue_name
|
|
247
|
-
|
|
248
|
-
# Force delete queue if requested
|
|
249
|
-
if force:
|
|
250
|
-
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
132
|
+
for name, member in members.items():
|
|
251
133
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
)
|
|
255
|
-
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
256
|
-
click.echo(
|
|
257
|
-
f"✓ Declared scheduled action queue: {queue_name} (routing key: {routing_key})"
|
|
134
|
+
message_handler = MessageHandler.get_message_incoming(
|
|
135
|
+
member.member_function
|
|
258
136
|
)
|
|
137
|
+
if message_handler is not None:
|
|
259
138
|
|
|
260
|
-
|
|
261
|
-
|
|
139
|
+
queue_name = f"{message_handler.message_type.MESSAGE_TOPIC}.{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
140
|
+
routing_key = f"{message_handler.message_type.MESSAGE_TOPIC}.#"
|
|
262
141
|
|
|
142
|
+
# Force delete queue if requested
|
|
143
|
+
if force:
|
|
144
|
+
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
263
145
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
Declare the infrastructure (exchanges and queues) for scheduler v2.
|
|
273
|
-
"""
|
|
274
|
-
from urllib.parse import parse_qs, urlparse
|
|
275
|
-
|
|
276
|
-
from jararaca.scheduler.decorators import ScheduledAction
|
|
277
|
-
|
|
278
|
-
parsed_url = urlparse(broker_url)
|
|
279
|
-
if parsed_url.scheme not in ["amqp", "amqps"]:
|
|
280
|
-
raise ValueError(f"Unsupported broker URL scheme: {parsed_url.scheme}")
|
|
281
|
-
|
|
282
|
-
if not parsed_url.query:
|
|
283
|
-
raise ValueError("Query string must be set for AMQP URLs")
|
|
284
|
-
|
|
285
|
-
query_params = parse_qs(parsed_url.query)
|
|
286
|
-
|
|
287
|
-
if "exchange" not in query_params or not query_params["exchange"]:
|
|
288
|
-
raise ValueError("Exchange must be set in the query string")
|
|
289
|
-
|
|
290
|
-
exchange = query_params["exchange"][0]
|
|
291
|
-
|
|
292
|
-
connection = await aio_pika.connect(broker_url)
|
|
293
|
-
channel = await connection.channel()
|
|
294
|
-
|
|
295
|
-
# Force delete exchange if requested
|
|
296
|
-
if force:
|
|
297
|
-
await RabbitmqUtils.delete_exchange(channel, exchange)
|
|
146
|
+
# Declare queue
|
|
147
|
+
queue = await RabbitmqUtils.declare_queue(
|
|
148
|
+
channel=channel, queue_name=queue_name, passive=not force
|
|
149
|
+
)
|
|
150
|
+
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
151
|
+
click.echo(
|
|
152
|
+
f"✓ Declared message handler queue: {queue_name} (routing key: {routing_key})"
|
|
153
|
+
)
|
|
298
154
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
durable=True,
|
|
304
|
-
auto_delete=False,
|
|
305
|
-
passive=passive_declare,
|
|
306
|
-
)
|
|
155
|
+
scheduled_action = ScheduledAction.get_scheduled_action(
|
|
156
|
+
member.member_function
|
|
157
|
+
)
|
|
158
|
+
if scheduled_action is not None:
|
|
307
159
|
|
|
308
|
-
|
|
309
|
-
from jararaca.di import Container
|
|
310
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
160
|
+
# Declare queues for scheduled actions
|
|
311
161
|
|
|
312
|
-
|
|
313
|
-
|
|
162
|
+
queue_name = f"{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
163
|
+
routing_key = queue_name
|
|
314
164
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
continue
|
|
165
|
+
# Force delete queue if requested
|
|
166
|
+
if force:
|
|
167
|
+
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
319
168
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
for action in actions:
|
|
328
|
-
# Include actions that have a name and it's in the provided set
|
|
329
|
-
if action.spec.name and action.spec.name in scheduler_names:
|
|
330
|
-
filtered_actions.add(action)
|
|
331
|
-
# Skip actions without names when filtering is active
|
|
332
|
-
actions = filtered_actions
|
|
333
|
-
|
|
334
|
-
scheduled_actions.extend(actions)
|
|
335
|
-
|
|
336
|
-
for scheduled_action in scheduled_actions:
|
|
337
|
-
queue_name = ScheduledAction.get_function_id(scheduled_action.callable)
|
|
338
|
-
|
|
339
|
-
# Force delete queue if requested
|
|
340
|
-
if force:
|
|
341
|
-
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
342
|
-
|
|
343
|
-
queue = await RabbitmqUtils.declare_scheduler_queue(
|
|
344
|
-
channel=channel,
|
|
345
|
-
queue_name=queue_name,
|
|
346
|
-
passive=passive_declare,
|
|
347
|
-
)
|
|
348
|
-
await queue.bind(
|
|
349
|
-
exchange=exchange,
|
|
350
|
-
routing_key=queue_name,
|
|
351
|
-
)
|
|
352
|
-
click.echo(f"✓ Declared scheduler queue: {queue_name}")
|
|
169
|
+
queue = await RabbitmqUtils.declare_queue(
|
|
170
|
+
channel=channel, queue_name=queue_name, passive=not force
|
|
171
|
+
)
|
|
172
|
+
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
173
|
+
click.echo(
|
|
174
|
+
f"✓ Declared scheduled action queue: {queue_name} (routing key: {routing_key})"
|
|
175
|
+
)
|
|
353
176
|
|
|
354
177
|
await channel.close()
|
|
355
178
|
await connection.close()
|
|
@@ -394,6 +217,7 @@ def cli() -> None:
|
|
|
394
217
|
"--passive-declare",
|
|
395
218
|
is_flag=True,
|
|
396
219
|
default=False,
|
|
220
|
+
help="[DEPRECATED] Use passive declarations (check if infrastructure exists without creating it)",
|
|
397
221
|
)
|
|
398
222
|
@click.option(
|
|
399
223
|
"--handlers",
|
|
@@ -407,8 +231,8 @@ def worker(
|
|
|
407
231
|
password: str | None,
|
|
408
232
|
exchange: str,
|
|
409
233
|
prefetch_count: int,
|
|
410
|
-
passive_declare: bool,
|
|
411
234
|
handlers: str | None,
|
|
235
|
+
passive_declare: bool,
|
|
412
236
|
) -> None:
|
|
413
237
|
|
|
414
238
|
app = find_microservice_by_module_path(app_path)
|
|
@@ -447,7 +271,6 @@ def worker(
|
|
|
447
271
|
)
|
|
448
272
|
|
|
449
273
|
worker_v1.MessageBusWorker(app, config=config).start_sync(
|
|
450
|
-
passive_declare=passive_declare,
|
|
451
274
|
handler_names=handler_names,
|
|
452
275
|
)
|
|
453
276
|
|
|
@@ -836,108 +659,7 @@ def gen_entity(entity_name: str, file_path: StreamWriter) -> None:
|
|
|
836
659
|
)
|
|
837
660
|
|
|
838
661
|
|
|
839
|
-
@cli.command(
|
|
840
|
-
@click.argument(
|
|
841
|
-
"app_path",
|
|
842
|
-
type=str,
|
|
843
|
-
)
|
|
844
|
-
@click.option(
|
|
845
|
-
"--broker-url",
|
|
846
|
-
type=str,
|
|
847
|
-
envvar="BROKER_URL",
|
|
848
|
-
help="Broker URL (e.g., amqp://guest:guest@localhost/) [env: BROKER_URL]",
|
|
849
|
-
)
|
|
850
|
-
@click.option(
|
|
851
|
-
"--exchange",
|
|
852
|
-
type=str,
|
|
853
|
-
default="jararaca_ex",
|
|
854
|
-
envvar="EXCHANGE",
|
|
855
|
-
help="Exchange name [env: EXCHANGE]",
|
|
856
|
-
)
|
|
857
|
-
@click.option(
|
|
858
|
-
"--passive-declare",
|
|
859
|
-
is_flag=True,
|
|
860
|
-
default=False,
|
|
861
|
-
help="Use passive declarations (check if infrastructure exists without creating it)",
|
|
862
|
-
)
|
|
863
|
-
@click.option(
|
|
864
|
-
"--handlers",
|
|
865
|
-
type=str,
|
|
866
|
-
help="Comma-separated list of handler names to declare queues for. If not specified, all handlers will be declared.",
|
|
867
|
-
)
|
|
868
|
-
@click.option(
|
|
869
|
-
"--force",
|
|
870
|
-
is_flag=True,
|
|
871
|
-
default=False,
|
|
872
|
-
help="Force recreation by deleting existing exchanges and queues before declaring them",
|
|
873
|
-
)
|
|
874
|
-
def declare_queues_v1(
|
|
875
|
-
app_path: str,
|
|
876
|
-
broker_url: str | None,
|
|
877
|
-
exchange: str,
|
|
878
|
-
passive_declare: bool,
|
|
879
|
-
handlers: str | None,
|
|
880
|
-
force: bool,
|
|
881
|
-
) -> None:
|
|
882
|
-
"""
|
|
883
|
-
Declare RabbitMQ infrastructure (exchanges and queues) for worker v1.
|
|
884
|
-
|
|
885
|
-
This command pre-declares the necessary exchanges and queues that worker v1
|
|
886
|
-
needs, without starting the actual consumption processes.
|
|
887
|
-
|
|
888
|
-
Environment variables:
|
|
889
|
-
- BROKER_URL: Broker URL (e.g., amqp://guest:guest@localhost/)
|
|
890
|
-
- EXCHANGE: Exchange name (defaults to 'jararaca_ex')
|
|
891
|
-
|
|
892
|
-
Examples:
|
|
893
|
-
|
|
894
|
-
\b
|
|
895
|
-
# Declare worker v1 infrastructure
|
|
896
|
-
jararaca declare-queues-v1 myapp:app --broker-url amqp://guest:guest@localhost/
|
|
897
|
-
|
|
898
|
-
\b
|
|
899
|
-
# Use environment variables
|
|
900
|
-
export BROKER_URL="amqp://guest:guest@localhost/"
|
|
901
|
-
export EXCHANGE="my_exchange"
|
|
902
|
-
jararaca declare-queues-v1 myapp:app
|
|
903
|
-
"""
|
|
904
|
-
|
|
905
|
-
app = find_microservice_by_module_path(app_path)
|
|
906
|
-
|
|
907
|
-
async def run_declarations() -> None:
|
|
908
|
-
if not broker_url:
|
|
909
|
-
click.echo(
|
|
910
|
-
"ERROR: --broker-url is required or set BROKER_URL environment variable",
|
|
911
|
-
err=True,
|
|
912
|
-
)
|
|
913
|
-
return
|
|
914
|
-
|
|
915
|
-
# Parse handler names if provided
|
|
916
|
-
handler_names: set[str] | None = None
|
|
917
|
-
if handlers:
|
|
918
|
-
handler_names = {
|
|
919
|
-
name.strip() for name in handlers.split(",") if name.strip()
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
click.echo(
|
|
923
|
-
f"→ Declaring worker v1 infrastructure (URL: {broker_url}, Exchange: {exchange})"
|
|
924
|
-
)
|
|
925
|
-
|
|
926
|
-
try:
|
|
927
|
-
await declare_worker_infrastructure(
|
|
928
|
-
broker_url, exchange, app, passive_declare, handler_names, force
|
|
929
|
-
)
|
|
930
|
-
click.echo("✓ Worker v1 infrastructure declared successfully!")
|
|
931
|
-
except Exception as e:
|
|
932
|
-
click.echo(
|
|
933
|
-
f"ERROR: Failed to declare worker v1 infrastructure: {e}", err=True
|
|
934
|
-
)
|
|
935
|
-
raise
|
|
936
|
-
|
|
937
|
-
asyncio.run(run_declarations())
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
@cli.command("declare-queues-v2")
|
|
662
|
+
@cli.command()
|
|
941
663
|
@click.argument(
|
|
942
664
|
"app_path",
|
|
943
665
|
type=str,
|
|
@@ -977,7 +699,7 @@ def declare_queues_v1(
|
|
|
977
699
|
default=False,
|
|
978
700
|
help="Force recreation by deleting existing exchanges and queues before declaring them",
|
|
979
701
|
)
|
|
980
|
-
def
|
|
702
|
+
def declare(
|
|
981
703
|
app_path: str,
|
|
982
704
|
broker_url: str | None,
|
|
983
705
|
exchange: str,
|
|
@@ -987,10 +709,10 @@ def declare_queues_v2(
|
|
|
987
709
|
force: bool,
|
|
988
710
|
) -> None:
|
|
989
711
|
"""
|
|
990
|
-
Declare RabbitMQ infrastructure (exchanges and queues) for
|
|
712
|
+
Declare RabbitMQ infrastructure (exchanges and queues) for message handlers and schedulers.
|
|
991
713
|
|
|
992
|
-
This command pre-declares the necessary exchanges and queues
|
|
993
|
-
|
|
714
|
+
This command pre-declares the necessary exchanges and queues for message handlers and schedulers,
|
|
715
|
+
without starting the actual consumption processes.
|
|
994
716
|
|
|
995
717
|
Environment variables:
|
|
996
718
|
- BROKER_URL: Broker URL (e.g., amqp://guest:guest@localhost/)
|
|
@@ -999,14 +721,18 @@ def declare_queues_v2(
|
|
|
999
721
|
Examples:
|
|
1000
722
|
|
|
1001
723
|
\b
|
|
1002
|
-
# Declare
|
|
1003
|
-
jararaca declare
|
|
724
|
+
# Declare infrastructure
|
|
725
|
+
jararaca declare myapp:app --broker-url amqp://guest:guest@localhost/
|
|
726
|
+
|
|
727
|
+
\b
|
|
728
|
+
# Force recreation of queues and exchanges
|
|
729
|
+
jararaca declare myapp:app --broker-url amqp://guest:guest@localhost/ --force
|
|
1004
730
|
|
|
1005
731
|
\b
|
|
1006
732
|
# Use environment variables
|
|
1007
733
|
export BROKER_URL="amqp://guest:guest@localhost/"
|
|
1008
734
|
export EXCHANGE="my_exchange"
|
|
1009
|
-
jararaca declare
|
|
735
|
+
jararaca declare myapp:app
|
|
1010
736
|
"""
|
|
1011
737
|
|
|
1012
738
|
app = find_microservice_by_module_path(app_path)
|
|
@@ -1033,26 +759,22 @@ def declare_queues_v2(
|
|
|
1033
759
|
name.strip() for name in schedulers.split(",") if name.strip()
|
|
1034
760
|
}
|
|
1035
761
|
|
|
1036
|
-
# For v2, create the broker URL with exchange parameter
|
|
1037
|
-
v2_broker_url = f"{broker_url}?exchange={exchange}"
|
|
1038
|
-
|
|
1039
|
-
click.echo(f"→ Declaring worker v2 infrastructure (URL: {v2_broker_url})")
|
|
1040
|
-
click.echo(f"→ Declaring scheduler v2 infrastructure (URL: {v2_broker_url})")
|
|
1041
|
-
|
|
1042
762
|
try:
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
v2_broker_url, app, passive_declare, scheduler_names, force
|
|
1049
|
-
),
|
|
763
|
+
# Create the broker URL with exchange parameter
|
|
764
|
+
broker_url_with_exchange = f"{broker_url}?exchange={exchange}"
|
|
765
|
+
|
|
766
|
+
click.echo(
|
|
767
|
+
f"→ Declaring worker infrastructure (URL: {broker_url_with_exchange})"
|
|
1050
768
|
)
|
|
1051
769
|
click.echo(
|
|
1052
|
-
"
|
|
770
|
+
f"→ Declaring scheduler infrastructure (URL: {broker_url_with_exchange})"
|
|
1053
771
|
)
|
|
772
|
+
|
|
773
|
+
await declare_worker_infrastructure(broker_url_with_exchange, app, force)
|
|
774
|
+
|
|
775
|
+
click.echo("✓ Worker and scheduler infrastructure declared successfully!")
|
|
1054
776
|
except Exception as e:
|
|
1055
|
-
click.echo(f"ERROR: Failed to declare
|
|
777
|
+
click.echo(f"ERROR: Failed to declare infrastructure: {e}", err=True)
|
|
1056
778
|
raise
|
|
1057
779
|
|
|
1058
780
|
asyncio.run(run_declarations())
|
|
@@ -108,7 +108,7 @@ class MessageBusController:
|
|
|
108
108
|
|
|
109
109
|
schedulers: SCHEDULED_ACTION_DATA_SET = set()
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
_, members = inspect_controller(cls_t)
|
|
112
112
|
|
|
113
113
|
for name, member in members.items():
|
|
114
114
|
message_handler_decoration = MessageHandler.get_message_incoming(
|
|
@@ -95,40 +95,44 @@ class AioPikaMicroserviceConsumer:
|
|
|
95
95
|
self.lock = asyncio.Lock()
|
|
96
96
|
self.tasks: set[asyncio.Task[Any]] = set()
|
|
97
97
|
|
|
98
|
-
async def consume(self
|
|
99
|
-
|
|
98
|
+
async def consume(self) -> None:
|
|
100
99
|
connection = await aio_pika.connect(self.config.url)
|
|
101
|
-
|
|
102
100
|
channel = await connection.channel()
|
|
103
|
-
|
|
104
101
|
await channel.set_qos(prefetch_count=self.config.prefetch_count)
|
|
105
102
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
# Get existing exchange and DL kit
|
|
104
|
+
try:
|
|
105
|
+
main_ex = await RabbitmqUtils.get_main_exchange(
|
|
106
|
+
channel=channel,
|
|
107
|
+
exchange_name=self.config.exchange,
|
|
108
|
+
)
|
|
109
|
+
dlx, dlq = await RabbitmqUtils.get_dl_kit(channel=channel)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.error(
|
|
112
|
+
f"Required exchange or queue infrastructure not found. "
|
|
113
|
+
f"Please use the declare command first to create the required infrastructure. Error: {e}"
|
|
114
|
+
)
|
|
115
|
+
self.shutdown_event.set()
|
|
116
|
+
return
|
|
113
117
|
|
|
114
118
|
for handler in self.message_handler_set:
|
|
115
|
-
|
|
116
119
|
queue_name = f"{handler.message_type.MESSAGE_TOPIC}.{handler.instance_callable.__module__}.{handler.instance_callable.__qualname__}"
|
|
117
120
|
routing_key = f"{handler.message_type.MESSAGE_TOPIC}.#"
|
|
118
121
|
|
|
119
122
|
self.incoming_map[queue_name] = handler
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
# Get existing queue
|
|
125
|
+
try:
|
|
126
|
+
queue = await RabbitmqUtils.get_worker_v1_queue(
|
|
123
127
|
channel=channel,
|
|
124
128
|
queue_name=queue_name,
|
|
125
|
-
dlx_name=dlx.name,
|
|
126
|
-
dlq_name=dlq.name,
|
|
127
|
-
passive=passive_declare,
|
|
128
129
|
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
except Exception as e:
|
|
131
|
+
logger.error(
|
|
132
|
+
f"Worker queue '{queue_name}' not found. "
|
|
133
|
+
f"Please use the declare command first to create the queue. Error: {e}"
|
|
134
|
+
)
|
|
135
|
+
continue
|
|
132
136
|
|
|
133
137
|
await queue.consume(
|
|
134
138
|
callback=MessageHandlerCallback(
|
|
@@ -338,9 +342,7 @@ class MessageBusWorker:
|
|
|
338
342
|
raise RuntimeError("Consumer not started")
|
|
339
343
|
return self._consumer
|
|
340
344
|
|
|
341
|
-
async def start_async(
|
|
342
|
-
self, passive_declare: bool, handler_names: set[str] | None = None
|
|
343
|
-
) -> None:
|
|
345
|
+
async def start_async(self, handler_names: set[str] | None = None) -> None:
|
|
344
346
|
all_message_handlers_set: MESSAGE_HANDLER_DATA_SET = set()
|
|
345
347
|
async with self.lifecycle():
|
|
346
348
|
for instance_type in self.app.controllers:
|
|
@@ -386,11 +388,9 @@ class MessageBusWorker:
|
|
|
386
388
|
uow_context_provider=self.uow_context_provider,
|
|
387
389
|
)
|
|
388
390
|
|
|
389
|
-
await consumer.consume(
|
|
391
|
+
await consumer.consume()
|
|
390
392
|
|
|
391
|
-
def start_sync(
|
|
392
|
-
self, passive_declare: bool, handler_names: set[str] | None = None
|
|
393
|
-
) -> None:
|
|
393
|
+
def start_sync(self, handler_names: set[str] | None = None) -> None:
|
|
394
394
|
|
|
395
395
|
def on_shutdown(loop: asyncio.AbstractEventLoop) -> None:
|
|
396
396
|
logger.info("Shutting down")
|
|
@@ -400,11 +400,7 @@ class MessageBusWorker:
|
|
|
400
400
|
runner.get_loop().add_signal_handler(
|
|
401
401
|
signal.SIGINT, on_shutdown, runner.get_loop()
|
|
402
402
|
)
|
|
403
|
-
runner.run(
|
|
404
|
-
self.start_async(
|
|
405
|
-
passive_declare=passive_declare, handler_names=handler_names
|
|
406
|
-
)
|
|
407
|
-
)
|
|
403
|
+
runner.run(self.start_async(handler_names=handler_names))
|
|
408
404
|
|
|
409
405
|
|
|
410
406
|
class AioPikaMessageBusController(BusMessageController):
|