jararaca 0.3.11a7__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.11a7 → jararaca-0.3.11a9}/PKG-INFO +1 -1
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/pyproject.toml +1 -1
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/cli.py +155 -258
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/decorators.py +3 -1
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker.py +40 -26
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker_v2.py +59 -27
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/microservice.py +76 -16
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/scheduler/decorators.py +7 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler.py +17 -2
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler_v2.py +26 -20
- jararaca-0.3.11a9/src/jararaca/utils/rabbitmq_utils.py +392 -0
- jararaca-0.3.11a7/src/jararaca/utils/rabbitmq_utils.py +0 -92
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/LICENSE +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/README.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/CNAME +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/architecture.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/index.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/messagebus.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/scheduler.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/stylesheets/custom.css +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/docs/websocket.md +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/__main__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/broker_backend/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/broker_backend/mapper.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/di.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/consumers/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/message.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/decorators.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/py.typed +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/reflect/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/reflect/controller_inspect.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/reflect/metadata.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/scheduler/types.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.3.11a7 → jararaca-0.3.11a9}/src/jararaca/tools/typescript/interface_parser.py +0 -0
- {jararaca-0.3.11a7 → 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,9 +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 MessageBusController, MessageHandler
|
|
20
21
|
from jararaca.microservice import Microservice
|
|
21
22
|
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
22
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
|
|
23
26
|
from jararaca.scheduler.scheduler import Scheduler
|
|
24
27
|
from jararaca.scheduler.scheduler_v2 import SchedulerV2
|
|
25
28
|
from jararaca.tools.typescript.interface_parser import (
|
|
@@ -70,75 +73,17 @@ def find_microservice_by_module_path(module_path: str) -> Microservice:
|
|
|
70
73
|
return app
|
|
71
74
|
|
|
72
75
|
|
|
73
|
-
|
|
74
|
-
url: str,
|
|
75
|
-
exchange: str,
|
|
76
|
-
app: Microservice,
|
|
77
|
-
passive_declare: bool = False,
|
|
78
|
-
) -> None:
|
|
79
|
-
"""
|
|
80
|
-
Declare the infrastructure (exchanges and queues) for worker v1.
|
|
81
|
-
"""
|
|
82
|
-
connection = await aio_pika.connect(url)
|
|
83
|
-
channel = await connection.channel()
|
|
84
|
-
|
|
85
|
-
# Declare main exchange
|
|
86
|
-
main_ex = await RabbitmqUtils.declare_main_exchange(
|
|
87
|
-
channel=channel,
|
|
88
|
-
exchange_name=exchange,
|
|
89
|
-
passive=passive_declare,
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
# Declare dead letter infrastructure
|
|
93
|
-
dlx, dlq = await RabbitmqUtils.declare_dl_kit(
|
|
94
|
-
channel=channel, passive=passive_declare
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
# Find all message handlers to declare their queues
|
|
98
|
-
from jararaca.di import Container
|
|
99
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
76
|
+
# The v1 infrastructure declaration function has been removed as part of the CLI simplification
|
|
100
77
|
|
|
101
|
-
container = Container(app)
|
|
102
|
-
|
|
103
|
-
for instance_type in app.controllers:
|
|
104
|
-
controller = MessageBusController.get_messagebus(instance_type)
|
|
105
|
-
if controller is None:
|
|
106
|
-
continue
|
|
107
|
-
|
|
108
|
-
instance: Any = container.get_by_type(instance_type)
|
|
109
|
-
factory = controller.get_messagebus_factory()
|
|
110
|
-
handlers, _ = factory(instance)
|
|
111
|
-
|
|
112
|
-
for handler in handlers:
|
|
113
|
-
queue_name = f"{handler.message_type.MESSAGE_TOPIC}.{handler.instance_callable.__module__}.{handler.instance_callable.__qualname__}"
|
|
114
|
-
routing_key = f"{handler.message_type.MESSAGE_TOPIC}.#"
|
|
115
|
-
|
|
116
|
-
queue = await channel.declare_queue(
|
|
117
|
-
passive=passive_declare,
|
|
118
|
-
name=queue_name,
|
|
119
|
-
arguments={
|
|
120
|
-
"x-dead-letter-exchange": dlx.name,
|
|
121
|
-
"x-dead-letter-routing-key": dlq.name,
|
|
122
|
-
},
|
|
123
|
-
durable=True,
|
|
124
|
-
)
|
|
125
78
|
|
|
126
|
-
|
|
127
|
-
click.echo(f"✓ Declared queue: {queue_name} (routing key: {routing_key})")
|
|
128
|
-
|
|
129
|
-
await channel.close()
|
|
130
|
-
await connection.close()
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
async def declare_worker_v2_infrastructure(
|
|
79
|
+
async def declare_worker_infrastructure(
|
|
134
80
|
broker_url: str,
|
|
135
81
|
app: Microservice,
|
|
136
|
-
|
|
82
|
+
force: bool = False,
|
|
137
83
|
) -> None:
|
|
138
84
|
"""
|
|
139
|
-
Declare the infrastructure (exchanges and queues) for worker
|
|
85
|
+
Declare the infrastructure (exchanges and queues) for worker.
|
|
140
86
|
"""
|
|
141
|
-
from urllib.parse import parse_qs, urlparse
|
|
142
87
|
|
|
143
88
|
parsed_url = urlparse(broker_url)
|
|
144
89
|
if parsed_url.scheme not in ["amqp", "amqps"]:
|
|
@@ -157,132 +102,77 @@ async def declare_worker_v2_infrastructure(
|
|
|
157
102
|
connection = await aio_pika.connect(broker_url)
|
|
158
103
|
channel = await connection.channel()
|
|
159
104
|
|
|
160
|
-
#
|
|
105
|
+
# Force delete infrastructure if requested
|
|
106
|
+
if force:
|
|
107
|
+
click.echo(f"→ Force deleting existing infrastructure for exchange: {exchange}")
|
|
108
|
+
await RabbitmqUtils.delete_exchange(channel, exchange)
|
|
109
|
+
await RabbitmqUtils.delete_exchange(channel, RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
110
|
+
await RabbitmqUtils.delete_queue(channel, RabbitmqUtils.DEAD_LETTER_QUEUE)
|
|
111
|
+
|
|
161
112
|
await RabbitmqUtils.declare_main_exchange(
|
|
162
113
|
channel=channel,
|
|
163
114
|
exchange_name=exchange,
|
|
164
|
-
passive=
|
|
115
|
+
passive=not force, # If force is True, we already deleted the exchange
|
|
165
116
|
)
|
|
166
117
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
channel=channel, passive=passive_declare
|
|
170
|
-
)
|
|
171
|
-
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)
|
|
172
120
|
await dlq.bind(dlx, routing_key=RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
173
121
|
|
|
174
122
|
# Find all message handlers and scheduled actions
|
|
175
|
-
from jararaca.di import Container
|
|
176
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
177
|
-
|
|
178
|
-
container = Container(app)
|
|
179
123
|
|
|
180
124
|
for instance_type in app.controllers:
|
|
181
|
-
|
|
182
|
-
if
|
|
125
|
+
controller_spec = MessageBusController.get_messagebus(instance_type)
|
|
126
|
+
if controller_spec is None:
|
|
183
127
|
continue
|
|
184
128
|
|
|
185
|
-
|
|
186
|
-
factory = controller.get_messagebus_factory()
|
|
187
|
-
handlers, scheduled_actions = factory(instance)
|
|
129
|
+
_, members = inspect_controller(instance_type)
|
|
188
130
|
|
|
189
131
|
# Declare queues for message handlers
|
|
190
|
-
for
|
|
191
|
-
queue_name = f"{handler.message_type.MESSAGE_TOPIC}.{handler.instance_callable.__module__}.{handler.instance_callable.__qualname__}"
|
|
192
|
-
routing_key = f"{handler.message_type.MESSAGE_TOPIC}.#"
|
|
132
|
+
for name, member in members.items():
|
|
193
133
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)
|
|
197
|
-
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
198
|
-
click.echo(
|
|
199
|
-
f"✓ Declared message handler queue: {queue_name} (routing key: {routing_key})"
|
|
134
|
+
message_handler = MessageHandler.get_message_incoming(
|
|
135
|
+
member.member_function
|
|
200
136
|
)
|
|
137
|
+
if message_handler is not None:
|
|
201
138
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
queue_name = f"{scheduled_action.callable.__module__}.{scheduled_action.callable.__qualname__}"
|
|
205
|
-
routing_key = queue_name
|
|
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}.#"
|
|
206
141
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
211
|
-
click.echo(
|
|
212
|
-
f"✓ Declared scheduled action queue: {queue_name} (routing key: {routing_key})"
|
|
213
|
-
)
|
|
142
|
+
# Force delete queue if requested
|
|
143
|
+
if force:
|
|
144
|
+
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
214
145
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
) -> None:
|
|
224
|
-
"""
|
|
225
|
-
Declare the infrastructure (exchanges and queues) for scheduler v2.
|
|
226
|
-
"""
|
|
227
|
-
from urllib.parse import parse_qs, urlparse
|
|
228
|
-
|
|
229
|
-
from jararaca.scheduler.decorators import ScheduledAction
|
|
230
|
-
|
|
231
|
-
parsed_url = urlparse(broker_url)
|
|
232
|
-
if parsed_url.scheme not in ["amqp", "amqps"]:
|
|
233
|
-
raise ValueError(f"Unsupported broker URL scheme: {parsed_url.scheme}")
|
|
234
|
-
|
|
235
|
-
if not parsed_url.query:
|
|
236
|
-
raise ValueError("Query string must be set for AMQP URLs")
|
|
237
|
-
|
|
238
|
-
query_params = parse_qs(parsed_url.query)
|
|
239
|
-
|
|
240
|
-
if "exchange" not in query_params or not query_params["exchange"]:
|
|
241
|
-
raise ValueError("Exchange must be set in the query string")
|
|
242
|
-
|
|
243
|
-
exchange = query_params["exchange"][0]
|
|
244
|
-
|
|
245
|
-
connection = await aio_pika.connect(broker_url)
|
|
246
|
-
channel = await connection.channel()
|
|
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
|
+
)
|
|
247
154
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
durable=True,
|
|
253
|
-
auto_delete=False,
|
|
254
|
-
passive=passive_declare,
|
|
255
|
-
)
|
|
155
|
+
scheduled_action = ScheduledAction.get_scheduled_action(
|
|
156
|
+
member.member_function
|
|
157
|
+
)
|
|
158
|
+
if scheduled_action is not None:
|
|
256
159
|
|
|
257
|
-
|
|
258
|
-
from jararaca.di import Container
|
|
259
|
-
from jararaca.messagebus.decorators import MessageBusController
|
|
160
|
+
# Declare queues for scheduled actions
|
|
260
161
|
|
|
261
|
-
|
|
262
|
-
|
|
162
|
+
queue_name = f"{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
163
|
+
routing_key = queue_name
|
|
263
164
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
continue
|
|
165
|
+
# Force delete queue if requested
|
|
166
|
+
if force:
|
|
167
|
+
await RabbitmqUtils.delete_queue(channel, queue_name)
|
|
268
168
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
queue = await channel.declare_queue(
|
|
277
|
-
name=queue_name,
|
|
278
|
-
durable=True,
|
|
279
|
-
passive=passive_declare,
|
|
280
|
-
)
|
|
281
|
-
await queue.bind(
|
|
282
|
-
exchange=exchange,
|
|
283
|
-
routing_key=queue_name,
|
|
284
|
-
)
|
|
285
|
-
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
|
+
)
|
|
286
176
|
|
|
287
177
|
await channel.close()
|
|
288
178
|
await connection.close()
|
|
@@ -327,6 +217,12 @@ def cli() -> None:
|
|
|
327
217
|
"--passive-declare",
|
|
328
218
|
is_flag=True,
|
|
329
219
|
default=False,
|
|
220
|
+
help="[DEPRECATED] Use passive declarations (check if infrastructure exists without creating it)",
|
|
221
|
+
)
|
|
222
|
+
@click.option(
|
|
223
|
+
"--handlers",
|
|
224
|
+
type=str,
|
|
225
|
+
help="Comma-separated list of handler names to listen to. If not specified, all handlers will be used.",
|
|
330
226
|
)
|
|
331
227
|
def worker(
|
|
332
228
|
app_path: str,
|
|
@@ -335,6 +231,7 @@ def worker(
|
|
|
335
231
|
password: str | None,
|
|
336
232
|
exchange: str,
|
|
337
233
|
prefetch_count: int,
|
|
234
|
+
handlers: str | None,
|
|
338
235
|
passive_declare: bool,
|
|
339
236
|
) -> None:
|
|
340
237
|
|
|
@@ -362,6 +259,11 @@ def worker(
|
|
|
362
259
|
|
|
363
260
|
url = parsed_url.geturl()
|
|
364
261
|
|
|
262
|
+
# Parse handler names if provided
|
|
263
|
+
handler_names: set[str] | None = None
|
|
264
|
+
if handlers:
|
|
265
|
+
handler_names = {name.strip() for name in handlers.split(",") if name.strip()}
|
|
266
|
+
|
|
365
267
|
config = worker_v1.AioPikaWorkerConfig(
|
|
366
268
|
url=url,
|
|
367
269
|
exchange=exchange,
|
|
@@ -369,7 +271,7 @@ def worker(
|
|
|
369
271
|
)
|
|
370
272
|
|
|
371
273
|
worker_v1.MessageBusWorker(app, config=config).start_sync(
|
|
372
|
-
|
|
274
|
+
handler_names=handler_names,
|
|
373
275
|
)
|
|
374
276
|
|
|
375
277
|
|
|
@@ -389,14 +291,27 @@ def worker(
|
|
|
389
291
|
type=str,
|
|
390
292
|
envvar="BACKEND_URL",
|
|
391
293
|
)
|
|
392
|
-
|
|
294
|
+
@click.option(
|
|
295
|
+
"--handlers",
|
|
296
|
+
type=str,
|
|
297
|
+
help="Comma-separated list of handler names to listen to. If not specified, all handlers will be used.",
|
|
298
|
+
)
|
|
299
|
+
def worker_v2(
|
|
300
|
+
app_path: str, broker_url: str, backend_url: str, handlers: str | None
|
|
301
|
+
) -> None:
|
|
393
302
|
|
|
394
303
|
app = find_microservice_by_module_path(app_path)
|
|
395
304
|
|
|
305
|
+
# Parse handler names if provided
|
|
306
|
+
handler_names: set[str] | None = None
|
|
307
|
+
if handlers:
|
|
308
|
+
handler_names = {name.strip() for name in handlers.split(",") if name.strip()}
|
|
309
|
+
|
|
396
310
|
worker_v2_mod.MessageBusWorker(
|
|
397
311
|
app=app,
|
|
398
312
|
broker_url=broker_url,
|
|
399
313
|
backend_url=backend_url,
|
|
314
|
+
handler_names=handler_names,
|
|
400
315
|
).start_sync()
|
|
401
316
|
|
|
402
317
|
|
|
@@ -449,13 +364,26 @@ def server(app_path: str, host: str, port: int) -> None:
|
|
|
449
364
|
type=int,
|
|
450
365
|
default=1,
|
|
451
366
|
)
|
|
367
|
+
@click.option(
|
|
368
|
+
"--schedulers",
|
|
369
|
+
type=str,
|
|
370
|
+
help="Comma-separated list of scheduler names to run (only run schedulers with these names)",
|
|
371
|
+
)
|
|
452
372
|
def scheduler(
|
|
453
373
|
app_path: str,
|
|
454
374
|
interval: int,
|
|
375
|
+
schedulers: str | None = None,
|
|
455
376
|
) -> None:
|
|
456
377
|
app = find_microservice_by_module_path(app_path)
|
|
457
378
|
|
|
458
|
-
|
|
379
|
+
# Parse scheduler names if provided
|
|
380
|
+
scheduler_names: set[str] | None = None
|
|
381
|
+
if schedulers:
|
|
382
|
+
scheduler_names = {
|
|
383
|
+
name.strip() for name in schedulers.split(",") if name.strip()
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
Scheduler(app, interval=interval, scheduler_names=scheduler_names).run()
|
|
459
387
|
|
|
460
388
|
|
|
461
389
|
@cli.command()
|
|
@@ -479,19 +407,34 @@ def scheduler(
|
|
|
479
407
|
type=str,
|
|
480
408
|
required=True,
|
|
481
409
|
)
|
|
410
|
+
@click.option(
|
|
411
|
+
"--schedulers",
|
|
412
|
+
type=str,
|
|
413
|
+
help="Comma-separated list of scheduler names to run (only run schedulers with these names)",
|
|
414
|
+
)
|
|
482
415
|
def scheduler_v2(
|
|
483
416
|
interval: int,
|
|
484
417
|
broker_url: str,
|
|
485
418
|
backend_url: str,
|
|
486
419
|
app_path: str,
|
|
420
|
+
schedulers: str | None = None,
|
|
487
421
|
) -> None:
|
|
488
422
|
|
|
489
423
|
app = find_microservice_by_module_path(app_path)
|
|
424
|
+
|
|
425
|
+
# Parse scheduler names if provided
|
|
426
|
+
scheduler_names: set[str] | None = None
|
|
427
|
+
if schedulers:
|
|
428
|
+
scheduler_names = {
|
|
429
|
+
name.strip() for name in schedulers.split(",") if name.strip()
|
|
430
|
+
}
|
|
431
|
+
|
|
490
432
|
scheduler = SchedulerV2(
|
|
491
433
|
app=app,
|
|
492
434
|
interval=interval,
|
|
493
435
|
backend_url=backend_url,
|
|
494
436
|
broker_url=broker_url,
|
|
437
|
+
scheduler_names=scheduler_names,
|
|
495
438
|
)
|
|
496
439
|
scheduler.run()
|
|
497
440
|
|
|
@@ -716,7 +659,7 @@ def gen_entity(entity_name: str, file_path: StreamWriter) -> None:
|
|
|
716
659
|
)
|
|
717
660
|
|
|
718
661
|
|
|
719
|
-
@cli.command(
|
|
662
|
+
@cli.command()
|
|
720
663
|
@click.argument(
|
|
721
664
|
"app_path",
|
|
722
665
|
type=str,
|
|
@@ -740,98 +683,36 @@ def gen_entity(entity_name: str, file_path: StreamWriter) -> None:
|
|
|
740
683
|
default=False,
|
|
741
684
|
help="Use passive declarations (check if infrastructure exists without creating it)",
|
|
742
685
|
)
|
|
743
|
-
def declare_queues_v1(
|
|
744
|
-
app_path: str,
|
|
745
|
-
broker_url: str | None,
|
|
746
|
-
exchange: str,
|
|
747
|
-
passive_declare: bool,
|
|
748
|
-
) -> None:
|
|
749
|
-
"""
|
|
750
|
-
Declare RabbitMQ infrastructure (exchanges and queues) for worker v1.
|
|
751
|
-
|
|
752
|
-
This command pre-declares the necessary exchanges and queues that worker v1
|
|
753
|
-
needs, without starting the actual consumption processes.
|
|
754
|
-
|
|
755
|
-
Environment variables:
|
|
756
|
-
- BROKER_URL: Broker URL (e.g., amqp://guest:guest@localhost/)
|
|
757
|
-
- EXCHANGE: Exchange name (defaults to 'jararaca_ex')
|
|
758
|
-
|
|
759
|
-
Examples:
|
|
760
|
-
|
|
761
|
-
\b
|
|
762
|
-
# Declare worker v1 infrastructure
|
|
763
|
-
jararaca declare-queues-v1 myapp:app --broker-url amqp://guest:guest@localhost/
|
|
764
|
-
|
|
765
|
-
\b
|
|
766
|
-
# Use environment variables
|
|
767
|
-
export BROKER_URL="amqp://guest:guest@localhost/"
|
|
768
|
-
export EXCHANGE="my_exchange"
|
|
769
|
-
jararaca declare-queues-v1 myapp:app
|
|
770
|
-
"""
|
|
771
|
-
|
|
772
|
-
app = find_microservice_by_module_path(app_path)
|
|
773
|
-
|
|
774
|
-
async def run_declarations() -> None:
|
|
775
|
-
if not broker_url:
|
|
776
|
-
click.echo(
|
|
777
|
-
"ERROR: --broker-url is required or set BROKER_URL environment variable",
|
|
778
|
-
err=True,
|
|
779
|
-
)
|
|
780
|
-
return
|
|
781
|
-
|
|
782
|
-
click.echo(
|
|
783
|
-
f"→ Declaring worker v1 infrastructure (URL: {broker_url}, Exchange: {exchange})"
|
|
784
|
-
)
|
|
785
|
-
|
|
786
|
-
try:
|
|
787
|
-
await declare_worker_infrastructure(
|
|
788
|
-
broker_url, exchange, app, passive_declare
|
|
789
|
-
)
|
|
790
|
-
click.echo("✓ Worker v1 infrastructure declared successfully!")
|
|
791
|
-
except Exception as e:
|
|
792
|
-
click.echo(
|
|
793
|
-
f"ERROR: Failed to declare worker v1 infrastructure: {e}", err=True
|
|
794
|
-
)
|
|
795
|
-
raise
|
|
796
|
-
|
|
797
|
-
asyncio.run(run_declarations())
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
@cli.command("declare-queues-v2")
|
|
801
|
-
@click.argument(
|
|
802
|
-
"app_path",
|
|
803
|
-
type=str,
|
|
804
|
-
)
|
|
805
686
|
@click.option(
|
|
806
|
-
"--
|
|
687
|
+
"--handlers",
|
|
807
688
|
type=str,
|
|
808
|
-
|
|
809
|
-
help="Broker URL (e.g., amqp://guest:guest@localhost/) [env: BROKER_URL]",
|
|
689
|
+
help="Comma-separated list of handler names to declare queues for. If not specified, all handlers will be declared.",
|
|
810
690
|
)
|
|
811
691
|
@click.option(
|
|
812
|
-
"--
|
|
692
|
+
"--schedulers",
|
|
813
693
|
type=str,
|
|
814
|
-
|
|
815
|
-
envvar="EXCHANGE",
|
|
816
|
-
help="Exchange name [env: EXCHANGE]",
|
|
694
|
+
help="Comma-separated list of scheduler names to declare queues for. If not specified, all schedulers will be declared.",
|
|
817
695
|
)
|
|
818
696
|
@click.option(
|
|
819
|
-
"--
|
|
697
|
+
"--force",
|
|
820
698
|
is_flag=True,
|
|
821
699
|
default=False,
|
|
822
|
-
help="
|
|
700
|
+
help="Force recreation by deleting existing exchanges and queues before declaring them",
|
|
823
701
|
)
|
|
824
|
-
def
|
|
702
|
+
def declare(
|
|
825
703
|
app_path: str,
|
|
826
704
|
broker_url: str | None,
|
|
827
705
|
exchange: str,
|
|
828
706
|
passive_declare: bool,
|
|
707
|
+
handlers: str | None,
|
|
708
|
+
schedulers: str | None,
|
|
709
|
+
force: bool,
|
|
829
710
|
) -> None:
|
|
830
711
|
"""
|
|
831
|
-
Declare RabbitMQ infrastructure (exchanges and queues) for
|
|
712
|
+
Declare RabbitMQ infrastructure (exchanges and queues) for message handlers and schedulers.
|
|
832
713
|
|
|
833
|
-
This command pre-declares the necessary exchanges and queues
|
|
834
|
-
|
|
714
|
+
This command pre-declares the necessary exchanges and queues for message handlers and schedulers,
|
|
715
|
+
without starting the actual consumption processes.
|
|
835
716
|
|
|
836
717
|
Environment variables:
|
|
837
718
|
- BROKER_URL: Broker URL (e.g., amqp://guest:guest@localhost/)
|
|
@@ -840,14 +721,18 @@ def declare_queues_v2(
|
|
|
840
721
|
Examples:
|
|
841
722
|
|
|
842
723
|
\b
|
|
843
|
-
# Declare
|
|
844
|
-
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
|
|
845
730
|
|
|
846
731
|
\b
|
|
847
732
|
# Use environment variables
|
|
848
733
|
export BROKER_URL="amqp://guest:guest@localhost/"
|
|
849
734
|
export EXCHANGE="my_exchange"
|
|
850
|
-
jararaca declare
|
|
735
|
+
jararaca declare myapp:app
|
|
851
736
|
"""
|
|
852
737
|
|
|
853
738
|
app = find_microservice_by_module_path(app_path)
|
|
@@ -860,24 +745,36 @@ def declare_queues_v2(
|
|
|
860
745
|
)
|
|
861
746
|
return
|
|
862
747
|
|
|
863
|
-
#
|
|
864
|
-
|
|
748
|
+
# Parse handler names if provided
|
|
749
|
+
handler_names: set[str] | None = None
|
|
750
|
+
if handlers:
|
|
751
|
+
handler_names = {
|
|
752
|
+
name.strip() for name in handlers.split(",") if name.strip()
|
|
753
|
+
}
|
|
865
754
|
|
|
866
|
-
|
|
867
|
-
|
|
755
|
+
# Parse scheduler names if provided
|
|
756
|
+
scheduler_names: set[str] | None = None
|
|
757
|
+
if schedulers:
|
|
758
|
+
scheduler_names = {
|
|
759
|
+
name.strip() for name in schedulers.split(",") if name.strip()
|
|
760
|
+
}
|
|
868
761
|
|
|
869
762
|
try:
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
)
|
|
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})"
|
|
875
768
|
)
|
|
876
769
|
click.echo(
|
|
877
|
-
"
|
|
770
|
+
f"→ Declaring scheduler infrastructure (URL: {broker_url_with_exchange})"
|
|
878
771
|
)
|
|
772
|
+
|
|
773
|
+
await declare_worker_infrastructure(broker_url_with_exchange, app, force)
|
|
774
|
+
|
|
775
|
+
click.echo("✓ Worker and scheduler infrastructure declared successfully!")
|
|
879
776
|
except Exception as e:
|
|
880
|
-
click.echo(f"ERROR: Failed to declare
|
|
777
|
+
click.echo(f"ERROR: Failed to declare infrastructure: {e}", err=True)
|
|
881
778
|
raise
|
|
882
779
|
|
|
883
780
|
asyncio.run(run_declarations())
|
|
@@ -24,6 +24,7 @@ class MessageHandler(Generic[INHERITS_MESSAGE_CO]):
|
|
|
24
24
|
exception_handler: Callable[[BaseException], None] | None = None,
|
|
25
25
|
nack_on_exception: bool = False,
|
|
26
26
|
auto_ack: bool = True,
|
|
27
|
+
name: str | None = None,
|
|
27
28
|
) -> None:
|
|
28
29
|
self.message_type = message
|
|
29
30
|
|
|
@@ -31,6 +32,7 @@ class MessageHandler(Generic[INHERITS_MESSAGE_CO]):
|
|
|
31
32
|
self.exception_handler = exception_handler
|
|
32
33
|
self.requeue_on_exception = nack_on_exception
|
|
33
34
|
self.auto_ack = auto_ack
|
|
35
|
+
self.name = name
|
|
34
36
|
|
|
35
37
|
def __call__(
|
|
36
38
|
self, func: Callable[[Any, MessageOf[INHERITS_MESSAGE_CO]], Awaitable[None]]
|
|
@@ -106,7 +108,7 @@ class MessageBusController:
|
|
|
106
108
|
|
|
107
109
|
schedulers: SCHEDULED_ACTION_DATA_SET = set()
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
_, members = inspect_controller(cls_t)
|
|
110
112
|
|
|
111
113
|
for name, member in members.items():
|
|
112
114
|
message_handler_decoration = MessageHandler.get_message_incoming(
|