talentro-commons 0.20.4__tar.gz → 0.20.6__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.
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/PKG-INFO +1 -1
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/pyproject.toml +1 -1
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/rabbitmq.py +39 -54
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/README.md +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/acquisition/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/acquisition/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/acquisition/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/billing/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/billing/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/billing/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/candidates/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/candidates/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/candidates/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/constants.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/event.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/exceptions.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/general/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/general/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/general/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/iam/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/iam/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/iam/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/iam/types.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/integrations/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/integrations/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/integrations/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/messaging/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/messaging/topology.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/billing.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/caching.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/clients.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/db.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/services/google_storage.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/attributes.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/enum.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/files.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/singleton.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/string.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/util/vacancy.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/vacancies/__init__.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/vacancies/dataclasses.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/vacancies/models.py +0 -0
- {talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/vacancies/taxanomy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "talentro-commons"
|
|
3
|
-
version = "0.20.
|
|
3
|
+
version = "0.20.6"
|
|
4
4
|
description = "This package contains all globally used code, services, models and data structures for Talentro"
|
|
5
5
|
authors = ["Emiel van Essen <emiel@marksmen.nl>"]
|
|
6
6
|
license = "Proprietary"
|
|
@@ -100,12 +100,12 @@ class RabbitMQ:
|
|
|
100
100
|
f"(TTL: {ttl_ms}ms)")
|
|
101
101
|
|
|
102
102
|
async def consume(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
self,
|
|
104
|
+
exchange_name: str,
|
|
105
|
+
queue: str,
|
|
106
|
+
callback: Callable,
|
|
107
|
+
dlx_name: Optional[str] = None,
|
|
108
|
+
max_retries: int = 3
|
|
109
109
|
):
|
|
110
110
|
while True:
|
|
111
111
|
try:
|
|
@@ -125,62 +125,40 @@ class RabbitMQ:
|
|
|
125
125
|
|
|
126
126
|
async for message in queue_object:
|
|
127
127
|
try:
|
|
128
|
-
|
|
128
|
+
# Use ignore_processed=True to prevent auto-ack on successful processing
|
|
129
|
+
async with message.process(ignore_processed=True, requeue=False):
|
|
129
130
|
event: Event = Event.decode(message.body)
|
|
130
|
-
print(
|
|
131
|
+
print(
|
|
132
|
+
f" RabbitMQ ({queue}) - [x] Received event: {event.meta.event_type} (trace: {event.meta.trace_id})")
|
|
131
133
|
await callback(queue, event)
|
|
134
|
+
# If we reach here, callback succeeded - manually ack
|
|
135
|
+
await message.ack()
|
|
132
136
|
except Exception as e:
|
|
133
137
|
# Handle callback exception - send to retry queue
|
|
134
138
|
print(f" RabbitMQ ({queue}) - ⚠️ Error processing message: {e}")
|
|
135
139
|
traceback.print_exc()
|
|
136
|
-
|
|
140
|
+
|
|
141
|
+
# Get retry count from headers
|
|
142
|
+
x_death = message.headers.get('x-death', [])
|
|
143
|
+
death_count = len(x_death) if x_death else 0
|
|
144
|
+
|
|
145
|
+
print(f" RabbitMQ ({queue}) - Retry attempt {death_count + 1}/{max_retries + 1}")
|
|
146
|
+
|
|
147
|
+
if death_count >= max_retries:
|
|
148
|
+
print(f" RabbitMQ ({queue}) - ❌ Max retries ({max_retries}) exceeded. Sending to DLQ.")
|
|
149
|
+
await message.nack(requeue=False)
|
|
150
|
+
else:
|
|
151
|
+
print(f" RabbitMQ ({queue}) - Sending to retry queue...")
|
|
152
|
+
await message.nack(requeue=False)
|
|
137
153
|
|
|
138
154
|
except (aio_pika.exceptions.AMQPConnectionError, aio_pika.exceptions.ChannelClosed):
|
|
139
155
|
print(f" RabbitMQ - Connection lost while consuming {queue}. Retrying in 5 seconds...")
|
|
140
156
|
await asyncio.sleep(5)
|
|
141
157
|
except Exception as e:
|
|
142
158
|
print(f" RabbitMQ - Unexpected error in consumer {queue}: {e}")
|
|
159
|
+
traceback.print_exc()
|
|
143
160
|
await asyncio.sleep(5)
|
|
144
161
|
|
|
145
|
-
@staticmethod
|
|
146
|
-
async def _handle_failed_message(
|
|
147
|
-
message: aio_pika.IncomingMessage,
|
|
148
|
-
queue_name: str,
|
|
149
|
-
exchange_name: str,
|
|
150
|
-
dlx_name: Optional[str] = None,
|
|
151
|
-
max_retries: int = 3
|
|
152
|
-
):
|
|
153
|
-
"""
|
|
154
|
-
Handle failed messages by sending them to the retry queue or DLQ.
|
|
155
|
-
"""
|
|
156
|
-
try:
|
|
157
|
-
# Get death count from headers
|
|
158
|
-
x_death = message.headers.get('x-death', [])
|
|
159
|
-
death_count = 0
|
|
160
|
-
|
|
161
|
-
if x_death:
|
|
162
|
-
# x-death is a list of death info dicts
|
|
163
|
-
death_count = len(x_death)
|
|
164
|
-
|
|
165
|
-
print(f" RabbitMQ ({queue_name}) - Retry attempt {death_count + 1}/{max_retries + 1}")
|
|
166
|
-
|
|
167
|
-
if death_count >= max_retries:
|
|
168
|
-
# Max retries exceeded - send to DLQ
|
|
169
|
-
print(f" RabbitMQ ({queue_name}) - ❌ Max retries ({max_retries}) exceeded. Sending to DLQ.")
|
|
170
|
-
await message.nack(requeue=False)
|
|
171
|
-
else:
|
|
172
|
-
# Still have retries left - send to retry queue
|
|
173
|
-
if dlx_name:
|
|
174
|
-
await message.nack(requeue=False)
|
|
175
|
-
print(f" RabbitMQ ({queue_name}) - Sending to retry queue...")
|
|
176
|
-
else:
|
|
177
|
-
await message.nack(requeue=True)
|
|
178
|
-
print(f" RabbitMQ ({queue_name}) - Message requeued")
|
|
179
|
-
|
|
180
|
-
except Exception as e:
|
|
181
|
-
print(f" RabbitMQ ({queue_name}) - Error handling failed message: {e}")
|
|
182
|
-
await message.nack(requeue=False)
|
|
183
|
-
|
|
184
162
|
async def send_message(self, message: Message):
|
|
185
163
|
# Haal de exchange op
|
|
186
164
|
if message.exchange == "default":
|
|
@@ -210,7 +188,7 @@ class QueueContext(metaclass=SingletonMeta):
|
|
|
210
188
|
def __init__(self):
|
|
211
189
|
self._rabbit_mq = RabbitMQ()
|
|
212
190
|
self._message_callbacks = []
|
|
213
|
-
self.
|
|
191
|
+
self._topology_configs: dict[str, TopologyConfig] = {} # Store all topologies
|
|
214
192
|
|
|
215
193
|
async def connect(self):
|
|
216
194
|
try:
|
|
@@ -227,7 +205,8 @@ class QueueContext(metaclass=SingletonMeta):
|
|
|
227
205
|
await self._setup_topology_with_config(topology)
|
|
228
206
|
|
|
229
207
|
async def _setup_topology_with_config(self, topology_config: TopologyConfig):
|
|
230
|
-
|
|
208
|
+
# Sla topology op met exchange_name als key
|
|
209
|
+
self._topology_configs[topology_config.exchange_name] = topology_config
|
|
231
210
|
|
|
232
211
|
await self._rabbit_mq.setup_topology(
|
|
233
212
|
topology_config.exchange_name,
|
|
@@ -237,15 +216,21 @@ class QueueContext(metaclass=SingletonMeta):
|
|
|
237
216
|
retry_config=topology_config.retry_config
|
|
238
217
|
)
|
|
239
218
|
|
|
240
|
-
|
|
241
|
-
|
|
219
|
+
|
|
220
|
+
async def start_consuming(self, queue: str, exchange_name: str):
|
|
221
|
+
topology_config = self._topology_configs.get(exchange_name)
|
|
222
|
+
|
|
223
|
+
if not topology_config:
|
|
224
|
+
raise ValueError(f"Topology not found for exchange: {exchange_name}")
|
|
225
|
+
|
|
226
|
+
max_retries = topology_config.get_max_retries(queue)
|
|
242
227
|
|
|
243
228
|
asyncio.create_task(
|
|
244
229
|
self._rabbit_mq.consume(
|
|
245
|
-
|
|
230
|
+
exchange_name,
|
|
246
231
|
queue,
|
|
247
232
|
self._on_new_message,
|
|
248
|
-
dlx_name=
|
|
233
|
+
dlx_name=topology_config.dlx_name,
|
|
249
234
|
max_retries=max_retries
|
|
250
235
|
)
|
|
251
236
|
)
|
|
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
|
{talentro_commons-0.20.4 → talentro_commons-0.20.6}/src/talentro/integrations/dataclasses.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
|