jararaca 0.3.11a14__tar.gz → 0.3.11a15__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.11a14 → jararaca-0.3.11a15}/PKG-INFO +1 -1
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/pyproject.toml +1 -1
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/cli.py +280 -110
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/LICENSE +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/README.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/CNAME +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/architecture.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/index.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/messagebus.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/scheduler.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/stylesheets/custom.css +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/websocket.md +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/__main__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/broker_backend/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/broker_backend/mapper.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/di.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/consumers/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/message.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/messagebus/worker.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/microservice.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/py.typed +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/reflect/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/reflect/controller_inspect.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/reflect/metadata.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/scheduler/beat_worker.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/scheduler/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/scheduler/types.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/tools/typescript/interface_parser.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/utils/__init__.py +0 -0
- {jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/utils/rabbitmq_utils.py +0 -0
|
@@ -20,7 +20,10 @@ from jararaca.messagebus.decorators import MessageBusController, MessageHandler
|
|
|
20
20
|
from jararaca.microservice import Microservice
|
|
21
21
|
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
22
22
|
from jararaca.presentation.server import create_http_server
|
|
23
|
-
from jararaca.reflect.controller_inspect import
|
|
23
|
+
from jararaca.reflect.controller_inspect import (
|
|
24
|
+
ControllerMemberReflect,
|
|
25
|
+
inspect_controller,
|
|
26
|
+
)
|
|
24
27
|
from jararaca.scheduler.beat_worker import BeatWorker
|
|
25
28
|
from jararaca.scheduler.decorators import ScheduledAction
|
|
26
29
|
from jararaca.tools.typescript.interface_parser import (
|
|
@@ -83,7 +86,6 @@ async def declare_worker_infrastructure(
|
|
|
83
86
|
"""
|
|
84
87
|
Declare the infrastructure (exchanges and queues) for worker.
|
|
85
88
|
"""
|
|
86
|
-
|
|
87
89
|
parsed_url = urlparse(broker_url)
|
|
88
90
|
if parsed_url.scheme not in ["amqp", "amqps"]:
|
|
89
91
|
raise ValueError(f"Unsupported broker URL scheme: {parsed_url.scheme}")
|
|
@@ -98,41 +100,161 @@ async def declare_worker_infrastructure(
|
|
|
98
100
|
|
|
99
101
|
exchange = query_params["exchange"][0]
|
|
100
102
|
|
|
103
|
+
# Create a connection that will be used to create channels for each operation
|
|
101
104
|
connection = await aio_pika.connect(broker_url)
|
|
102
|
-
channel = await connection.channel()
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
try:
|
|
107
|
+
# Step 1: Setup infrastructure (exchanges and dead letter queues)
|
|
108
|
+
# Creating a dedicated channel for infrastructure setup
|
|
109
|
+
await setup_infrastructure(connection, exchange, force, interactive_mode)
|
|
110
|
+
|
|
111
|
+
# Step 2: Declare all message handlers and scheduled actions queues
|
|
112
|
+
# Creating a dedicated channel for controller queues
|
|
113
|
+
await declare_controller_queues(
|
|
114
|
+
connection, app, exchange, force, interactive_mode
|
|
115
|
+
)
|
|
116
|
+
finally:
|
|
117
|
+
# Always close the connection in the finally block
|
|
118
|
+
await connection.close()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def setup_infrastructure(
|
|
122
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
123
|
+
exchange: str,
|
|
124
|
+
force: bool = False,
|
|
125
|
+
interactive_mode: bool = False,
|
|
126
|
+
) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Setup the basic infrastructure (exchanges and dead letter queues).
|
|
129
|
+
"""
|
|
130
|
+
# Check if infrastructure exists
|
|
131
|
+
infrastructure_exists = await check_infrastructure_exists(connection, exchange)
|
|
132
|
+
|
|
133
|
+
# If it exists and force or user confirms, delete it
|
|
134
|
+
if not infrastructure_exists and should_recreate_infrastructure(
|
|
135
|
+
force,
|
|
136
|
+
interactive_mode,
|
|
137
|
+
f"Existing infrastructure found for exchange '{exchange}'. Delete and recreate?",
|
|
108
138
|
):
|
|
139
|
+
await delete_infrastructure(connection, exchange)
|
|
140
|
+
|
|
141
|
+
# Try to declare required infrastructure
|
|
142
|
+
await declare_infrastructure(connection, exchange, force, interactive_mode)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
async def check_infrastructure_exists(
|
|
146
|
+
connection: aio_pika.abc.AbstractConnection, exchange: str
|
|
147
|
+
) -> bool:
|
|
148
|
+
"""
|
|
149
|
+
Check if the infrastructure exists by trying passive declarations.
|
|
150
|
+
"""
|
|
151
|
+
# Create a dedicated channel for checking infrastructure existence using async context manager
|
|
152
|
+
async with connection.channel() as channel:
|
|
153
|
+
try:
|
|
154
|
+
await RabbitmqUtils.declare_main_exchange(
|
|
155
|
+
channel=channel,
|
|
156
|
+
exchange_name=exchange,
|
|
157
|
+
passive=True,
|
|
158
|
+
)
|
|
159
|
+
await RabbitmqUtils.declare_dl_exchange(channel=channel, passive=True)
|
|
160
|
+
await RabbitmqUtils.declare_dl_queue(channel=channel, passive=True)
|
|
161
|
+
return True
|
|
162
|
+
except Exception:
|
|
163
|
+
# Infrastructure doesn't exist, which is fine for fresh setup
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def should_recreate_infrastructure(
|
|
168
|
+
force: bool, interactive_mode: bool, confirmation_message: str
|
|
169
|
+
) -> bool:
|
|
170
|
+
"""
|
|
171
|
+
Determine if infrastructure should be recreated based on force flag and user input.
|
|
172
|
+
"""
|
|
173
|
+
return force or (interactive_mode and click.confirm(confirmation_message))
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
async def delete_infrastructure(
|
|
177
|
+
connection: aio_pika.abc.AbstractConnection, exchange: str
|
|
178
|
+
) -> None:
|
|
179
|
+
"""
|
|
180
|
+
Delete existing infrastructure (exchanges and queues).
|
|
181
|
+
"""
|
|
182
|
+
# Create a dedicated channel for deleting infrastructure using async context manager
|
|
183
|
+
async with connection.channel() as channel:
|
|
109
184
|
click.echo(f"→ Deleting existing infrastructure for exchange: {exchange}")
|
|
110
185
|
await RabbitmqUtils.delete_exchange(channel, exchange)
|
|
111
186
|
await RabbitmqUtils.delete_exchange(channel, RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
112
187
|
await RabbitmqUtils.delete_queue(channel, RabbitmqUtils.DEAD_LETTER_QUEUE)
|
|
113
188
|
|
|
114
|
-
try:
|
|
115
|
-
await RabbitmqUtils.declare_main_exchange(
|
|
116
|
-
channel=channel,
|
|
117
|
-
exchange_name=exchange,
|
|
118
|
-
passive=False,
|
|
119
|
-
)
|
|
120
189
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
190
|
+
async def declare_infrastructure(
|
|
191
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
192
|
+
exchange: str,
|
|
193
|
+
force: bool,
|
|
194
|
+
interactive_mode: bool,
|
|
195
|
+
) -> None:
|
|
196
|
+
"""
|
|
197
|
+
Declare the required infrastructure (exchanges and dead letter queues).
|
|
198
|
+
"""
|
|
199
|
+
# Using async context manager for channel creation
|
|
200
|
+
async with connection.channel() as channel:
|
|
201
|
+
try:
|
|
202
|
+
# Declare main exchange
|
|
203
|
+
await RabbitmqUtils.declare_main_exchange(
|
|
204
|
+
channel=channel,
|
|
205
|
+
exchange_name=exchange,
|
|
206
|
+
passive=False,
|
|
207
|
+
)
|
|
134
208
|
|
|
135
|
-
|
|
209
|
+
# Declare dead letter exchange and queue
|
|
210
|
+
dlx = await RabbitmqUtils.declare_dl_exchange(
|
|
211
|
+
channel=channel, passive=False
|
|
212
|
+
)
|
|
213
|
+
dlq = await RabbitmqUtils.declare_dl_queue(channel=channel, passive=False)
|
|
214
|
+
await dlq.bind(dlx, routing_key=RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
215
|
+
|
|
216
|
+
except Exception as e:
|
|
217
|
+
click.echo(f"Error during exchange declaration: {e}")
|
|
218
|
+
|
|
219
|
+
# If interactive mode and user confirms, or if forced, try again after deletion
|
|
220
|
+
if should_recreate_infrastructure(
|
|
221
|
+
force, interactive_mode, "Delete existing infrastructure and recreate?"
|
|
222
|
+
):
|
|
223
|
+
# Delete infrastructure with a new channel
|
|
224
|
+
await delete_infrastructure(connection, exchange)
|
|
225
|
+
|
|
226
|
+
# Try again with a new channel
|
|
227
|
+
async with connection.channel() as new_channel:
|
|
228
|
+
# Try again after deletion
|
|
229
|
+
await RabbitmqUtils.declare_main_exchange(
|
|
230
|
+
channel=new_channel,
|
|
231
|
+
exchange_name=exchange,
|
|
232
|
+
passive=False,
|
|
233
|
+
)
|
|
234
|
+
dlx = await RabbitmqUtils.declare_dl_exchange(
|
|
235
|
+
channel=new_channel, passive=False
|
|
236
|
+
)
|
|
237
|
+
dlq = await RabbitmqUtils.declare_dl_queue(
|
|
238
|
+
channel=new_channel, passive=False
|
|
239
|
+
)
|
|
240
|
+
await dlq.bind(dlx, routing_key=RabbitmqUtils.DEAD_LETTER_EXCHANGE)
|
|
241
|
+
elif force:
|
|
242
|
+
# If force is true but recreation failed, propagate the error
|
|
243
|
+
raise
|
|
244
|
+
else:
|
|
245
|
+
click.echo("Skipping main exchange declaration due to error")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
async def declare_controller_queues(
|
|
249
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
250
|
+
app: Microservice,
|
|
251
|
+
exchange: str,
|
|
252
|
+
force: bool,
|
|
253
|
+
interactive_mode: bool,
|
|
254
|
+
) -> None:
|
|
255
|
+
"""
|
|
256
|
+
Declare all message handler and scheduled action queues for controllers.
|
|
257
|
+
"""
|
|
136
258
|
for instance_type in app.controllers:
|
|
137
259
|
controller_spec = MessageBusController.get_messagebus(instance_type)
|
|
138
260
|
if controller_spec is None:
|
|
@@ -140,54 +262,135 @@ async def declare_worker_infrastructure(
|
|
|
140
262
|
|
|
141
263
|
_, members = inspect_controller(instance_type)
|
|
142
264
|
|
|
143
|
-
#
|
|
265
|
+
# Process each member (method) in the controller
|
|
144
266
|
for _, member in members.items():
|
|
145
|
-
|
|
146
|
-
|
|
267
|
+
# Check if it's a message handler
|
|
268
|
+
await declare_message_handler_queue(
|
|
269
|
+
connection, member, exchange, force, interactive_mode
|
|
147
270
|
)
|
|
148
|
-
if message_handler is not None:
|
|
149
|
-
queue_name = f"{message_handler.message_type.MESSAGE_TOPIC}.{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
150
|
-
routing_key = f"{message_handler.message_type.MESSAGE_TOPIC}.#"
|
|
151
|
-
|
|
152
|
-
try:
|
|
153
|
-
# Try to declare queue
|
|
154
|
-
queue = await RabbitmqUtils.declare_worker_queue(
|
|
155
|
-
channel=channel, queue_name=queue_name, passive=False
|
|
156
|
-
)
|
|
157
|
-
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
158
|
-
click.echo(
|
|
159
|
-
f"✓ Declared message handler queue: {queue_name} (routing key: {routing_key})"
|
|
160
|
-
)
|
|
161
|
-
except Exception as e:
|
|
162
|
-
click.echo(
|
|
163
|
-
f"⚠ Skipping message handler queue {queue_name} due to error: {e}"
|
|
164
|
-
)
|
|
165
|
-
continue
|
|
166
271
|
|
|
167
|
-
|
|
168
|
-
|
|
272
|
+
# Check if it's a scheduled action
|
|
273
|
+
await declare_scheduled_action_queue(
|
|
274
|
+
connection, member, exchange, force, interactive_mode
|
|
169
275
|
)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
async def declare_message_handler_queue(
|
|
279
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
280
|
+
member: ControllerMemberReflect,
|
|
281
|
+
exchange: str,
|
|
282
|
+
force: bool,
|
|
283
|
+
interactive_mode: bool,
|
|
284
|
+
) -> None:
|
|
285
|
+
"""
|
|
286
|
+
Declare a queue for a message handler if the member is one.
|
|
287
|
+
"""
|
|
288
|
+
message_handler = MessageHandler.get_message_incoming(member.member_function)
|
|
289
|
+
if message_handler is not None:
|
|
290
|
+
queue_name = f"{message_handler.message_type.MESSAGE_TOPIC}.{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
291
|
+
routing_key = f"{message_handler.message_type.MESSAGE_TOPIC}.#"
|
|
292
|
+
|
|
293
|
+
await declare_and_bind_queue(
|
|
294
|
+
connection,
|
|
295
|
+
queue_name,
|
|
296
|
+
routing_key,
|
|
297
|
+
exchange,
|
|
298
|
+
force,
|
|
299
|
+
interactive_mode,
|
|
300
|
+
is_scheduled_action=False,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
async def declare_scheduled_action_queue(
|
|
305
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
306
|
+
member: ControllerMemberReflect,
|
|
307
|
+
exchange: str,
|
|
308
|
+
force: bool,
|
|
309
|
+
interactive_mode: bool,
|
|
310
|
+
) -> None:
|
|
311
|
+
"""
|
|
312
|
+
Declare a queue for a scheduled action if the member is one.
|
|
313
|
+
"""
|
|
314
|
+
scheduled_action = ScheduledAction.get_scheduled_action(member.member_function)
|
|
315
|
+
if scheduled_action is not None:
|
|
316
|
+
queue_name = (
|
|
317
|
+
f"{member.member_function.__module__}.{member.member_function.__qualname__}"
|
|
318
|
+
)
|
|
319
|
+
routing_key = queue_name
|
|
320
|
+
|
|
321
|
+
await declare_and_bind_queue(
|
|
322
|
+
connection,
|
|
323
|
+
queue_name,
|
|
324
|
+
routing_key,
|
|
325
|
+
exchange,
|
|
326
|
+
force,
|
|
327
|
+
interactive_mode,
|
|
328
|
+
is_scheduled_action=True,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
async def declare_and_bind_queue(
|
|
333
|
+
connection: aio_pika.abc.AbstractConnection,
|
|
334
|
+
queue_name: str,
|
|
335
|
+
routing_key: str,
|
|
336
|
+
exchange: str,
|
|
337
|
+
force: bool,
|
|
338
|
+
interactive_mode: bool,
|
|
339
|
+
is_scheduled_action: bool,
|
|
340
|
+
) -> None:
|
|
341
|
+
"""
|
|
342
|
+
Declare and bind a queue to the exchange with the given routing key.
|
|
343
|
+
"""
|
|
344
|
+
queue_type = "scheduled action" if is_scheduled_action else "message handler"
|
|
345
|
+
|
|
346
|
+
# Using async context manager for channel creation
|
|
347
|
+
async with connection.channel() as channel:
|
|
348
|
+
try:
|
|
349
|
+
# Try to declare queue using the appropriate method
|
|
350
|
+
if is_scheduled_action:
|
|
351
|
+
queue = await RabbitmqUtils.declare_scheduled_action_queue(
|
|
352
|
+
channel=channel, queue_name=queue_name, passive=False
|
|
353
|
+
)
|
|
354
|
+
else:
|
|
355
|
+
queue = await RabbitmqUtils.declare_worker_queue(
|
|
356
|
+
channel=channel, queue_name=queue_name, passive=False
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# Bind the queue to the exchange
|
|
360
|
+
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
361
|
+
click.echo(
|
|
362
|
+
f"✓ Declared {queue_type} queue: {queue_name} (routing key: {routing_key})"
|
|
363
|
+
)
|
|
364
|
+
except Exception as e:
|
|
365
|
+
click.echo(f"⚠ Error declaring {queue_type} queue {queue_name}: {e}")
|
|
366
|
+
|
|
367
|
+
# If interactive mode and user confirms, or if forced, recreate the queue
|
|
368
|
+
if force or (
|
|
369
|
+
interactive_mode
|
|
370
|
+
and click.confirm(f"Delete and recreate queue {queue_name}?")
|
|
371
|
+
):
|
|
372
|
+
# Create a new channel for deletion and recreation
|
|
373
|
+
async with connection.channel() as new_channel:
|
|
374
|
+
# Delete the queue
|
|
375
|
+
await RabbitmqUtils.delete_queue(new_channel, queue_name)
|
|
376
|
+
|
|
377
|
+
# Try to declare queue again using the appropriate method
|
|
378
|
+
if is_scheduled_action:
|
|
379
|
+
queue = await RabbitmqUtils.declare_scheduled_action_queue(
|
|
380
|
+
channel=new_channel, queue_name=queue_name, passive=False
|
|
381
|
+
)
|
|
382
|
+
else:
|
|
383
|
+
queue = await RabbitmqUtils.declare_worker_queue(
|
|
384
|
+
channel=new_channel, queue_name=queue_name, passive=False
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
# Bind the queue to the exchange
|
|
179
388
|
await queue.bind(exchange=exchange, routing_key=routing_key)
|
|
180
389
|
click.echo(
|
|
181
|
-
f"✓
|
|
182
|
-
)
|
|
183
|
-
except Exception as e:
|
|
184
|
-
click.echo(
|
|
185
|
-
f"⚠ Skipping scheduled action queue {queue_name} due to error: {e}"
|
|
390
|
+
f"✓ Recreated {queue_type} queue: {queue_name} (routing key: {routing_key})"
|
|
186
391
|
)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
await channel.close()
|
|
190
|
-
await connection.close()
|
|
392
|
+
else:
|
|
393
|
+
click.echo(f"⚠ Skipping {queue_type} queue {queue_name}")
|
|
191
394
|
|
|
192
395
|
|
|
193
396
|
@click.group()
|
|
@@ -562,29 +765,14 @@ def gen_entity(entity_name: str, file_path: StreamWriter) -> None:
|
|
|
562
765
|
help="Broker URL (e.g., amqp://guest:guest@localhost/) [env: BROKER_URL]",
|
|
563
766
|
)
|
|
564
767
|
@click.option(
|
|
565
|
-
"
|
|
566
|
-
|
|
567
|
-
default="jararaca_ex",
|
|
568
|
-
envvar="EXCHANGE",
|
|
569
|
-
help="Exchange name [env: EXCHANGE]",
|
|
570
|
-
)
|
|
571
|
-
@click.option(
|
|
572
|
-
"--passive-declare",
|
|
768
|
+
"-i",
|
|
769
|
+
"--interactive-mode",
|
|
573
770
|
is_flag=True,
|
|
574
771
|
default=False,
|
|
575
|
-
help="
|
|
576
|
-
)
|
|
577
|
-
@click.option(
|
|
578
|
-
"--handlers",
|
|
579
|
-
type=str,
|
|
580
|
-
help="Comma-separated list of handler names to declare queues for. If not specified, all handlers will be declared.",
|
|
581
|
-
)
|
|
582
|
-
@click.option(
|
|
583
|
-
"--schedulers",
|
|
584
|
-
type=str,
|
|
585
|
-
help="Comma-separated list of scheduler names to declare queues for. If not specified, all schedulers will be declared.",
|
|
772
|
+
help="Enable interactive mode for queue declaration (confirm before deleting existing queues)",
|
|
586
773
|
)
|
|
587
774
|
@click.option(
|
|
775
|
+
"-f",
|
|
588
776
|
"--force",
|
|
589
777
|
is_flag=True,
|
|
590
778
|
default=False,
|
|
@@ -592,12 +780,9 @@ def gen_entity(entity_name: str, file_path: StreamWriter) -> None:
|
|
|
592
780
|
)
|
|
593
781
|
def declare(
|
|
594
782
|
app_path: str,
|
|
595
|
-
broker_url: str
|
|
596
|
-
exchange: str,
|
|
597
|
-
passive_declare: bool,
|
|
598
|
-
handlers: str | None,
|
|
599
|
-
schedulers: str | None,
|
|
783
|
+
broker_url: str,
|
|
600
784
|
force: bool,
|
|
785
|
+
interactive_mode: bool,
|
|
601
786
|
) -> None:
|
|
602
787
|
"""
|
|
603
788
|
Declare RabbitMQ infrastructure (exchanges and queues) for message handlers and schedulers.
|
|
@@ -636,28 +821,13 @@ def declare(
|
|
|
636
821
|
)
|
|
637
822
|
return
|
|
638
823
|
|
|
639
|
-
# Parse handler names if provided
|
|
640
|
-
handler_names: set[str] | None = None
|
|
641
|
-
if handlers:
|
|
642
|
-
handler_names = {
|
|
643
|
-
name.strip() for name in handlers.split(",") if name.strip()
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
# Parse scheduler names if provided
|
|
647
|
-
scheduler_names: set[str] | None = None
|
|
648
|
-
if schedulers:
|
|
649
|
-
scheduler_names = {
|
|
650
|
-
name.strip() for name in schedulers.split(",") if name.strip()
|
|
651
|
-
}
|
|
652
|
-
|
|
653
824
|
try:
|
|
654
825
|
# Create the broker URL with exchange parameter
|
|
655
|
-
broker_url_with_exchange = f"{broker_url}?exchange={exchange}"
|
|
656
826
|
|
|
657
|
-
click.echo(
|
|
658
|
-
|
|
827
|
+
click.echo(f"→ Declaring worker infrastructure (URL: {broker_url})")
|
|
828
|
+
await declare_worker_infrastructure(
|
|
829
|
+
broker_url, app, force, interactive_mode
|
|
659
830
|
)
|
|
660
|
-
await declare_worker_infrastructure(broker_url_with_exchange, app, force)
|
|
661
831
|
|
|
662
832
|
click.echo("✓ Workers infrastructure declared successfully!")
|
|
663
833
|
except Exception as e:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg
RENAMED
|
File without changes
|
{jararaca-0.3.11a14 → jararaca-0.3.11a15}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jararaca-0.3.11a14 → jararaca-0.3.11a15}/src/jararaca/broker_backend/redis_broker_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|