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.

Files changed (85) hide show
  1. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/PKG-INFO +1 -1
  2. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/pyproject.toml +1 -1
  3. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/cli.py +72 -350
  4. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/decorators.py +1 -1
  5. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker.py +28 -32
  6. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/worker_v2.py +36 -26
  7. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/microservice.py +76 -16
  8. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler_v2.py +8 -19
  9. jararaca-0.3.11a9/src/jararaca/utils/rabbitmq_utils.py +392 -0
  10. jararaca-0.3.11a8/src/jararaca/utils/rabbitmq_utils.py +0 -170
  11. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/LICENSE +0 -0
  12. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/README.md +0 -0
  13. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/CNAME +0 -0
  14. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/architecture.md +0 -0
  15. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
  16. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
  17. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/assets/tracing_example.png +0 -0
  18. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/index.md +0 -0
  19. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/messagebus.md +0 -0
  20. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/scheduler.md +0 -0
  21. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/stylesheets/custom.css +0 -0
  22. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/docs/websocket.md +0 -0
  23. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/__init__.py +0 -0
  24. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/__main__.py +0 -0
  25. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/__init__.py +0 -0
  26. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/mapper.py +0 -0
  27. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
  28. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/common/__init__.py +0 -0
  29. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/__init__.py +0 -0
  30. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/providers.py +0 -0
  31. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/core/uow.py +0 -0
  32. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/di.py +0 -0
  33. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/files/entity.py.mako +0 -0
  34. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/lifecycle.py +0 -0
  35. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/__init__.py +0 -0
  36. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/bus_message_controller.py +0 -0
  37. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/consumers/__init__.py +0 -0
  38. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
  39. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
  40. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
  41. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/message.py +0 -0
  42. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/messagebus/publisher.py +0 -0
  43. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/decorators.py +0 -0
  44. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/interceptor.py +0 -0
  45. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/providers/__init__.py +0 -0
  46. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/observability/providers/otel.py +0 -0
  47. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/base.py +0 -0
  48. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/exports.py +0 -0
  49. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/__init__.py +0 -0
  50. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
  51. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/session.py +0 -0
  52. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/sort_filter.py +0 -0
  53. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/persistence/utilities.py +0 -0
  54. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/__init__.py +0 -0
  55. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/decorators.py +0 -0
  56. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/hooks.py +0 -0
  57. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/http_microservice.py +0 -0
  58. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/server.py +0 -0
  59. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/__init__.py +0 -0
  60. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/base_types.py +0 -0
  61. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/context.py +0 -0
  62. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/decorators.py +0 -0
  63. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/redis.py +0 -0
  64. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/types.py +0 -0
  65. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
  66. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/py.typed +0 -0
  67. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/__init__.py +0 -0
  68. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/controller_inspect.py +0 -0
  69. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/reflect/metadata.py +0 -0
  70. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/__init__.py +0 -0
  71. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/__init__.py +0 -0
  72. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/__init__.py +0 -0
  73. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/httpx.py +0 -0
  74. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/backends/otel.py +0 -0
  75. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/decorators.py +0 -0
  76. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/rpc/http/httpx.py +0 -0
  77. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/__init__.py +0 -0
  78. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/decorators.py +0 -0
  79. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/scheduler.py +0 -0
  80. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/scheduler/types.py +0 -0
  81. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/__init__.py +0 -0
  82. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/decorators.py +0 -0
  83. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/app_config/interceptor.py +0 -0
  84. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/tools/typescript/interface_parser.py +0 -0
  85. {jararaca-0.3.11a8 → jararaca-0.3.11a9}/src/jararaca/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: jararaca
3
- Version: 0.3.11a8
3
+ Version: 0.3.11a9
4
4
  Summary: A simple and fast API framework for Python
5
5
  Author: Lucas S
6
6
  Author-email: me@luscasleo.dev
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "jararaca"
3
- version = "0.3.11a8"
3
+ version = "0.3.11a9"
4
4
  description = "A simple and fast API framework for Python"
5
5
  authors = ["Lucas S <me@luscasleo.dev>"]
6
6
  readme = "README.md"
@@ -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 SCHEDULED_ACTION_DATA_SET
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
- async def declare_worker_infrastructure(
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
- for instance_type in app.controllers:
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 v2.
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=passive_declare,
115
+ passive=not force, # If force is True, we already deleted the exchange
194
116
  )
195
117
 
196
- # Declare dead letter infrastructure
197
- dlx = await RabbitmqUtils.declare_dl_exchange(
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
- controller = MessageBusController.get_messagebus(instance_type)
211
- if controller is None:
125
+ controller_spec = MessageBusController.get_messagebus(instance_type)
126
+ if controller_spec is None:
212
127
  continue
213
128
 
214
- instance: Any = container.get_by_type(instance_type)
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 handler in handlers:
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
- queue = await RabbitmqUtils.declare_queue(
253
- channel=channel, queue_name=queue_name, passive=passive_declare
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
- await channel.close()
261
- await connection.close()
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
- async def declare_scheduler_v2_infrastructure(
265
- broker_url: str,
266
- app: Microservice,
267
- passive_declare: bool = False,
268
- scheduler_names: set[str] | None = None,
269
- force: bool = False,
270
- ) -> None:
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
- # Declare exchange for scheduler
300
- await channel.declare_exchange(
301
- name=exchange,
302
- type="topic",
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
- # Find all scheduled actions and declare their queues
309
- from jararaca.di import Container
310
- from jararaca.messagebus.decorators import MessageBusController
160
+ # Declare queues for scheduled actions
311
161
 
312
- container = Container(app)
313
- scheduled_actions: list[Any] = []
162
+ queue_name = f"{member.member_function.__module__}.{member.member_function.__qualname__}"
163
+ routing_key = queue_name
314
164
 
315
- for instance_type in app.controllers:
316
- controller = MessageBusController.get_messagebus(instance_type)
317
- if controller is None:
318
- continue
165
+ # Force delete queue if requested
166
+ if force:
167
+ await RabbitmqUtils.delete_queue(channel, queue_name)
319
168
 
320
- instance: Any = container.get_by_type(instance_type)
321
- factory = controller.get_messagebus_factory()
322
- _, actions = factory(instance)
323
-
324
- # Filter scheduled actions by name if specified
325
- if scheduler_names is not None:
326
- filtered_actions: SCHEDULED_ACTION_DATA_SET = set()
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("declare-queues-v1")
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 declare_queues_v2(
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 worker v2 and scheduler v2.
712
+ Declare RabbitMQ infrastructure (exchanges and queues) for message handlers and schedulers.
991
713
 
992
- This command pre-declares the necessary exchanges and queues that worker v2
993
- and scheduler v2 need, without starting the actual consumption processes.
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 worker v2 and scheduler v2 infrastructure
1003
- jararaca declare-queues-v2 myapp:app --broker-url amqp://guest:guest@localhost/
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-queues-v2 myapp:app
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
- await asyncio.gather(
1044
- declare_worker_v2_infrastructure(
1045
- v2_broker_url, app, passive_declare, handler_names, force
1046
- ),
1047
- declare_scheduler_v2_infrastructure(
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
- " Worker v2 and scheduler v2 infrastructure declared successfully!"
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 v2 infrastructure: {e}", err=True)
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
- controller, members = inspect_controller(cls_t)
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, passive_declare: bool) -> None:
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
- main_ex = await RabbitmqUtils.declare_main_exchange(
107
- channel=channel,
108
- exchange_name=self.config.exchange,
109
- passive=passive_declare,
110
- )
111
-
112
- dlx, dlq = await RabbitmqUtils.declare_dl_kit(channel=channel)
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
- queue: aio_pika.abc.AbstractQueue = (
122
- await RabbitmqUtils.declare_worker_v1_queue(
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
- await queue.bind(exchange=main_ex, routing_key=routing_key)
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(passive_declare=passive_declare)
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):