reach_commons 0.18.25__tar.gz → 0.18.27__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.
Files changed (32) hide show
  1. {reach_commons-0.18.25 → reach_commons-0.18.27}/PKG-INFO +1 -1
  2. {reach_commons-0.18.25 → reach_commons-0.18.27}/pyproject.toml +1 -1
  3. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/sqs.py +85 -48
  4. {reach_commons-0.18.25 → reach_commons-0.18.27}/README.md +0 -0
  5. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/__init__.py +0 -0
  6. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/app_logging/__init__.py +0 -0
  7. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/app_logging/http_logger.py +0 -0
  8. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/app_logging/log_deprecated_endpoints.py +0 -0
  9. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/app_logging/logger.py +0 -0
  10. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/app_logging/logging_config.py +0 -0
  11. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/__init__.py +0 -0
  12. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/event_processor.py +0 -0
  13. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/hubspot.py +0 -0
  14. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/outscraper.py +0 -0
  15. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/reach_data_bridge.py +0 -0
  16. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/clients/reach_ops_api.py +0 -0
  17. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/mongo/__init__.py +0 -0
  18. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/mongo/customer_persistence.py +0 -0
  19. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/mongo/customer_persistence_async.py +0 -0
  20. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/mongo/validation/__init__.py +0 -0
  21. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/__init__.py +0 -0
  22. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/commons.py +0 -0
  23. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/dynamo_db.py +0 -0
  24. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/exceptions.py +0 -0
  25. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/firehose.py +0 -0
  26. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/kms.py +0 -0
  27. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_aws/s3.py +0 -0
  28. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/reach_base_model.py +0 -0
  29. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/redis_manager.py +0 -0
  30. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/sms_smart_encoding.py +0 -0
  31. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/utils.py +0 -0
  32. {reach_commons-0.18.25 → reach_commons-0.18.27}/reach_commons/validations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reach_commons
3
- Version: 0.18.25
3
+ Version: 0.18.27
4
4
  Summary: Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem.
5
5
  License: MIT
6
6
  Author: Engineering
@@ -1,7 +1,7 @@
1
1
  # isort .; black .; poetry build; poetry publish
2
2
  [tool.poetry]
3
3
  name = "reach_commons"
4
- version = "0.18.25"
4
+ version = "0.18.27"
5
5
  description = "Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem."
6
6
  authors = ["Engineering <engineering@getreach.ai>"]
7
7
  license = "MIT"
@@ -146,38 +146,61 @@ class SQSClient(BaseSQSClient):
146
146
 
147
147
  return True
148
148
 
149
- def get_visible_messages_count(self) -> int:
149
+ def get_queue_metrics(self) -> dict:
150
+ """
151
+ Retorna métricas aproximadas da fila SQS.
152
+
153
+ {
154
+ "visible": int,
155
+ "in_flight": int,
156
+ "delayed": int,
157
+ "oldest_age_seconds": int,
158
+ }
159
+ """
150
160
  try:
151
161
  resp = self.client.get_queue_attributes(
152
162
  QueueUrl=self.topic_name,
153
163
  AttributeNames=[
154
- "ApproximateNumberOfMessages",
155
- "ApproximateNumberOfMessagesNotVisible",
156
- "ApproximateNumberOfMessagesDelayed",
164
+ "ApproximateNumberOfMessages", # visible
165
+ "ApproximateNumberOfMessagesNotVisible", # in-flight
166
+ "ApproximateNumberOfMessagesDelayed", # delayed
167
+ "ApproximateAgeOfOldestMessage",
157
168
  ],
158
169
  )
159
- visible = int(resp["Attributes"].get("ApproximateNumberOfMessages", 0))
160
- in_flight = int(
161
- resp["Attributes"].get("ApproximateNumberOfMessagesNotVisible", 0)
162
- )
163
- delayed = int(
164
- resp["Attributes"].get("ApproximateNumberOfMessagesDelayed", 0)
165
- )
166
170
 
167
- return visible, in_flight, delayed
171
+ attrs = resp.get("Attributes", {})
172
+
173
+ visible = int(attrs.get("ApproximateNumberOfMessages", 0))
174
+ in_flight = int(attrs.get("ApproximateNumberOfMessagesNotVisible", 0))
175
+ delayed = int(attrs.get("ApproximateNumberOfMessagesDelayed", 0))
176
+ oldest_age_seconds = int(attrs.get("ApproximateAgeOfOldestMessage", 0))
177
+
178
+ return {
179
+ "visible": visible,
180
+ "in_flight": in_flight,
181
+ "delayed": delayed,
182
+ "oldest_age_seconds": oldest_age_seconds,
183
+ }
184
+
168
185
  except ClientError as exc:
169
186
  self.logger.error(
170
187
  "error_fetching_queue_attributes, topic_name=%s, error=%s",
171
188
  self.topic_name,
172
189
  str(exc),
173
190
  )
174
- # If there's an error, return 0 so as not to block the caller.
175
- return 0, 0, 0
191
+
192
+ return {
193
+ "visible": 0,
194
+ "in_flight": 0,
195
+ "delayed": 0,
196
+ "oldest_age_seconds": 0,
197
+ }
176
198
 
177
199
  def publish_with_capacity_guard(
178
200
  self,
179
201
  message_data: dict,
180
- max_capacity: int,
202
+ max_visible_capacity: int,
203
+ max_total_capacity: int = None,
181
204
  delay_seconds: int = 60,
182
205
  message_attributes: dict = None,
183
206
  ) -> dict:
@@ -185,44 +208,56 @@ class SQSClient(BaseSQSClient):
185
208
  Attempts to publish a message while enforcing an approximate queue capacity limit.
186
209
 
187
210
  Behavior:
188
- - If the queue is below `max_capacity`, the message is published normally.
189
- - If the queue is at or above `max_capacity`, the message is NOT published.
211
+ - If the queue is below `max_visible_capacity` (and optional `max_total_capacity`),
212
+ the message is published normally.
213
+ - If the queue is at or above the threshold(s), the message is NOT published.
190
214
 
191
215
  Returns a dict with:
192
- - posted: bool -> whether the message was actually published
193
- - visible_count: int -> ApproximateNumberOfMessages at publication time
194
- - max_capacity: int -> the capacity threshold used
195
-
196
- Example:
197
- sqs = SQSClient(topic_name="<enviroment>-messages-queue")
198
-
199
- Result = sqs.publish_with_capacity_guard(
200
- message_data={"foo": "bar"},
201
- max_capacity=100_000,
202
- delay_seconds=30,
203
- message_attributes={"service_name": "TestClient"},
204
- )
205
-
206
- if not Result["posted"]:
207
- print("Queue is over capacity:", Result)
216
+ - posted: bool
217
+ - visible_count: int
218
+ - in_flight_count: int
219
+ - delayed_count: int
220
+ - oldest_age_seconds: int
221
+ - max_visible_capacity: int
222
+ - max_total_capacity: int | None
208
223
  """
209
- (
210
- visible_count,
211
- in_flight_count,
212
- delayed_count,
213
- ) = self.get_visible_messages_count()
224
+ metrics = self.get_queue_metrics()
225
+ visible = metrics["visible"]
226
+ in_flight = metrics["in_flight"]
227
+ delayed = metrics["delayed"]
228
+ oldest_age_seconds = metrics["oldest_age_seconds"]
229
+
230
+ total_active = visible + in_flight
231
+
232
+ over_visible = visible >= max_visible_capacity
233
+ over_total = (
234
+ max_total_capacity is not None and total_active >= max_total_capacity
235
+ )
214
236
 
215
- if visible_count >= max_capacity:
237
+ if over_visible or over_total:
216
238
  self.logger.warning(
217
- "queue_over_capacity, topic_name=%s, visible=%s, max_capacity=%s",
239
+ (
240
+ "queue_over_capacity, topic_name=%s, "
241
+ "visible=%s, in_flight=%s, delayed=%s, oldest_age_seconds=%s, "
242
+ "total_active=%s, max_visible_capacity=%s, max_total_capacity=%s"
243
+ ),
218
244
  self.topic_name,
219
- visible_count,
220
- max_capacity,
245
+ visible,
246
+ in_flight,
247
+ delayed,
248
+ oldest_age_seconds,
249
+ total_active,
250
+ max_visible_capacity,
251
+ max_total_capacity,
221
252
  )
222
253
  return {
223
254
  "posted": False,
224
- "visible_count": visible_count,
225
- "max_capacity": max_capacity,
255
+ "visible_count": visible,
256
+ "in_flight_count": in_flight,
257
+ "delayed_count": delayed,
258
+ "oldest_age_seconds": oldest_age_seconds,
259
+ "max_visible_capacity": max_visible_capacity,
260
+ "max_total_capacity": max_total_capacity,
226
261
  }
227
262
 
228
263
  self.publish(
@@ -233,10 +268,12 @@ class SQSClient(BaseSQSClient):
233
268
 
234
269
  return {
235
270
  "posted": True,
236
- "visible_count": visible_count,
237
- "in_flight_count": in_flight_count,
238
- "delayed_count": delayed_count,
239
- "max_capacity": max_capacity,
271
+ "visible_count": visible,
272
+ "in_flight_count": in_flight,
273
+ "delayed_count": delayed,
274
+ "oldest_age_seconds": oldest_age_seconds,
275
+ "max_visible_capacity": max_visible_capacity,
276
+ "max_total_capacity": max_total_capacity,
240
277
  }
241
278
 
242
279