reach_commons 0.18.22__py3-none-any.whl → 0.18.24__py3-none-any.whl

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.
@@ -174,9 +174,11 @@ class BusinessReviewsCommonQueries:
174
174
  Item={
175
175
  "PK": f"business#{business_id}",
176
176
  "SK": "info",
177
- "created_at": created_at_isoformat
178
- if created_at_isoformat
179
- else datetime.utcnow().isoformat(),
177
+ "created_at": (
178
+ created_at_isoformat
179
+ if created_at_isoformat
180
+ else datetime.utcnow().isoformat()
181
+ ),
180
182
  **filtered_info,
181
183
  },
182
184
  ConditionExpression="attribute_not_exists(PK) AND attribute_not_exists(SK)",
@@ -97,9 +97,9 @@ class KMSClient(BaseKMSClient):
97
97
  ciphertext = self.client.encrypt(
98
98
  KeyId=key_alias,
99
99
  Plaintext=bytes(data_to_encrypt, encoding="utf8"),
100
- EncryptionContext={"CustomContext": f"{custom_context}"}
101
- if custom_context
102
- else None,
100
+ EncryptionContext=(
101
+ {"CustomContext": f"{custom_context}"} if custom_context else None
102
+ ),
103
103
  )
104
104
  encrypted = base64.b64encode(ciphertext["CiphertextBlob"])
105
105
  except ClientError as exc:
@@ -4,7 +4,6 @@ from decimal import Decimal
4
4
  from functools import cached_property
5
5
 
6
6
  import boto3
7
- import requests
8
7
  from botocore.exceptions import ClientError
9
8
 
10
9
  from reach_commons.app_logging.logger import get_reach_logger
@@ -147,6 +146,81 @@ class SQSClient(BaseSQSClient):
147
146
 
148
147
  return True
149
148
 
149
+ def _get_visible_messages_count(self) -> int:
150
+ try:
151
+ resp = self.client.get_queue_attributes(
152
+ QueueUrl=self.topic_name,
153
+ AttributeNames=["ApproximateNumberOfMessages"],
154
+ )
155
+ return int(resp["Attributes"].get("ApproximateNumberOfMessages", 0))
156
+ except ClientError as exc:
157
+ self.logger.error(
158
+ "error_fetching_queue_attributes, topic_name=%s, error=%s",
159
+ self.topic_name,
160
+ str(exc),
161
+ )
162
+ # If there's an error, return 0 so as not to block the caller.
163
+ return 0
164
+
165
+ def publish_with_capacity_guard(
166
+ self,
167
+ message_data: dict,
168
+ max_capacity: int,
169
+ delay_seconds: int = 60,
170
+ message_attributes: dict = None,
171
+ ) -> dict:
172
+ """
173
+ Attempts to publish a message while enforcing an approximate queue capacity limit.
174
+
175
+ Behavior:
176
+ - If the queue is below `max_capacity`, the message is published normally.
177
+ - If the queue is at or above `max_capacity`, the message is NOT published.
178
+
179
+ Returns a dict with:
180
+ - posted: bool -> whether the message was actually published
181
+ - visible_count: int -> ApproximateNumberOfMessages at publication time
182
+ - max_capacity: int -> the capacity threshold used
183
+
184
+ Example:
185
+ sqs = SQSClient(topic_name="<enviroment>-messages-queue")
186
+
187
+ Result = sqs.publish_with_capacity_guard(
188
+ message_data={"foo": "bar"},
189
+ max_capacity=100_000,
190
+ delay_seconds=30,
191
+ message_attributes={"service_name": "TestClient"},
192
+ )
193
+
194
+ if not Result["posted"]:
195
+ print("Queue is over capacity:", Result)
196
+ """
197
+ visible_count = self._get_visible_messages_count()
198
+
199
+ if visible_count >= max_capacity:
200
+ self.logger.warning(
201
+ "queue_over_capacity, topic_name=%s, visible=%s, max_capacity=%s",
202
+ self.topic_name,
203
+ visible_count,
204
+ max_capacity,
205
+ )
206
+ return {
207
+ "posted": False,
208
+ "visible_count": visible_count,
209
+ "max_capacity": max_capacity,
210
+ }
211
+
212
+ self.publish(
213
+ message_data=message_data,
214
+ delay_seconds=delay_seconds,
215
+ message_attributes=message_attributes,
216
+ )
217
+
218
+ return {
219
+ "posted": True,
220
+ "visible_count": visible_count,
221
+ "max_capacity": max_capacity,
222
+ }
223
+
150
224
 
151
225
  class MessageFilter:
152
226
  """
@@ -234,15 +308,6 @@ class HubspotSQSNotifier(SQSClient):
234
308
  logger=logger,
235
309
  topic_name=f"{env}-{self.TOPIC_NAME}",
236
310
  )
237
- self.env = env
238
-
239
- @cached_property
240
- def lambda_client(self):
241
- session = boto3.Session(
242
- region_name=self.region_name,
243
- profile_name=self.profile_name,
244
- )
245
- return session.client("lambda")
246
311
 
247
312
  def send_message(
248
313
  self, object_name, object_id, secondary_object_id=None, delay_seconds=60
@@ -283,30 +348,6 @@ class HubspotSQSNotifier(SQSClient):
283
348
  return delay_seconds
284
349
 
285
350
  def notify_business_change(self, business_id, delay_seconds=60):
286
- try:
287
- resp = requests.get(
288
- "https://asoekaw.free.beeceptor.com/processing/eligibility",
289
- timeout=10,
290
- )
291
-
292
- data = resp.json()
293
-
294
- if data.get("allowed", False):
295
- repeat = int(data.get("repeat", 1))
296
- for _ in range(repeat):
297
- self.lambda_client.invoke(
298
- FunctionName=f"{self.env}-nightly-lambda",
299
- InvocationType="Event",
300
- Payload=json.dumps(
301
- {
302
- "event": "hourly_15",
303
- "override_status": True,
304
- }
305
- ).encode("utf-8"),
306
- )
307
- except Exception:
308
- pass
309
-
310
351
  return self.send_message(
311
352
  object_name="business_change",
312
353
  object_id=business_id,
@@ -538,7 +579,6 @@ class POSApiPullerSQSNotifier(SQSClient):
538
579
  logger=logger,
539
580
  topic_name=f"{env}-{self.TOPIC_NAME}",
540
581
  )
541
- self.env = env
542
582
 
543
583
  def notify_for_send_message(
544
584
  self,
@@ -1,10 +1,10 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: reach_commons
3
- Version: 0.18.22
3
+ Version: 0.18.24
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
- Author: Wilson Moraes
7
- Author-email: wmoraes@getreach.ai
6
+ Author: Engineering
7
+ Author-email: engineering@getreach.ai
8
8
  Requires-Python: >=3.8,<4.0
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
@@ -14,6 +14,8 @@ Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
17
19
  Requires-Dist: curlify (==3.0.0)
18
20
  Requires-Dist: fastapi (>=0.115.5)
19
21
  Requires-Dist: pydantic (>=2.9.2)
@@ -16,17 +16,17 @@ reach_commons/mongo/customer_persistence_async.py,sha256=BmcP8TXyyQah-GYM3wcKi1b
16
16
  reach_commons/mongo/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  reach_commons/reach_aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  reach_commons/reach_aws/commons.py,sha256=qQba0li75BIpmyVc0sDVrrxbtYvDCedF6RmFD-V4MYQ,259
19
- reach_commons/reach_aws/dynamo_db.py,sha256=ndwLlaDwb96IlsnpAeeKPg-2DOjxe0JSM0y-zdlOc6E,7082
19
+ reach_commons/reach_aws/dynamo_db.py,sha256=BL3QcKzx4uZic-Ui12tln_GMSKe297FdfyIzFPE7veE,7140
20
20
  reach_commons/reach_aws/exceptions.py,sha256=x0RL5ktNtzxg0KykhEVWReBq_dEtciK6B2vMs_s4C9k,915
21
21
  reach_commons/reach_aws/firehose.py,sha256=1xFKLWMv3bNo3PPW5gtaL6NqzUDyVil6B768slj2wbY,5674
22
- reach_commons/reach_aws/kms.py,sha256=-X4EJOh9IoncNn9C46X55mpSHPO5mR0B36lYLA2hhic,4670
22
+ reach_commons/reach_aws/kms.py,sha256=ZOfyJMQUgxJEojRoB7-aCxtATpNx1Ig522IUYH11NZ4,4678
23
23
  reach_commons/reach_aws/s3.py,sha256=2MLlDNFx0SROJBpE_KjJefyrB7lMqTlrYuRhSZx4iKs,3945
24
- reach_commons/reach_aws/sqs.py,sha256=qH8wAg0T4FYg-zZWXjfCk06_w3UHbz7N-U7CGOwqDoE,17000
24
+ reach_commons/reach_aws/sqs.py,sha256=9_sVM7bqhswBSksJ2bhPvtDmW1N9jHh1OUC25vXYLdU,18563
25
25
  reach_commons/reach_base_model.py,sha256=vgdGDcZr3iXMmyRhmBhOf_LKWB_6QzT3r_Yiyo6OmEk,3009
26
26
  reach_commons/redis_manager.py,sha256=SgUtdtt0eV4bUwsWDankIa9Bjfgcm2DKcmVMQT6ptF0,2946
27
27
  reach_commons/sms_smart_encoding.py,sha256=92y0RmZ0l4ONHpC9qeO5KfViSNq64yE2rc7lhNDSZqE,1241
28
28
  reach_commons/utils.py,sha256=dMgKIGqTgoSItuBI8oz81gKtW3qi21Jkljv9leS_V88,8475
29
29
  reach_commons/validations.py,sha256=CJdWg8qc9ILe3rYHYTLdr2upRspsM_8ghhm4IXX4Pg8,1028
30
- reach_commons-0.18.22.dist-info/METADATA,sha256=1OUoKoNdTE0sLAh8aIUA5Y_eCRzOgdKRdnrWejqQg6E,1861
31
- reach_commons-0.18.22.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
32
- reach_commons-0.18.22.dist-info/RECORD,,
30
+ reach_commons-0.18.24.dist-info/METADATA,sha256=udH-_sPBf_Cvuyx34M5z16tOxlnu_eLdiMpdONMTmag,1965
31
+ reach_commons-0.18.24.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
32
+ reach_commons-0.18.24.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any