Source code for ecstask.resources.utils
"""
This module contains common utilities.
"""
import copy
import logging
import uuid
from http import HTTPStatus
from ecstask.resources import constants
from pymorri import exceptions
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
[docs]def generate_correlation_id() -> str:
"""
Generate a new correlation id.
"""
return f"strpick-pick-task-{uuid.uuid4().hex}"
[docs]def retry_if_mori_exc_and_not_404(exc: Exception) -> bool:
"""
Return True if we should retry, False otherwise.
"""
if not isinstance(exc, exceptions.MoriException):
return False
if exc.http_status_code != HTTPStatus.NOT_FOUND:
return True
raise exc
[docs]def validate_kafka_message(kafka_message: dict,
store_validator, min_validator) -> tuple[dict, dict, str]:
"""
Validate the message that was received from Kafka
before creating the payload that will be sent to the stock transfer service.
Args:
kafka_message: The message that was received from Kafka
store_validator: The wrapper of location API
min_validator: The wrapper of the product API
Returns:
tuple: The Kafka message stripped of invalid store and MINs,
the message to be written to DLQ and status message
"""
dlq_message = {"original_message": kafka_message,
"invalid_store_or_mins": {"store": "", "mins": []}}
if kafka_message == {}:
logger.warning("Kafka message is empty")
return {}, dlq_message, constants.FOUND_EMPTY_MESSAGE
new_message = copy.deepcopy(kafka_message)
store_id, value = kafka_message.copy().popitem()
items_dict = new_message.get(store_id, {}).get("items", {})
if store_id == "" or items_dict == {}:
logger.warning("Kafka message has no store or no mins")
return {}, dlq_message, constants.FOUND_PARTIAL_MESSAGE
if validate_store(store_validator, store_id, dlq_message):
status = validate_mins(min_validator, items_dict, dlq_message)
else:
status = constants.FOUND_INVALID_STORE
new_message = {}
if items_dict == {}:
new_message = {}
return new_message, dlq_message, status
[docs]def validate_store(store_validator, store_id: str, dlq_message: dict) -> bool:
"""Validate the given store."""
if not store_validator.validate_store(store_id):
logger.warning("Kafka message has invalid store")
dlq_message["invalid_store_or_mins"]["store"] = store_id
return False
return True
[docs]def validate_mins(min_validator, items_dict: dict, dlq_message: dict) -> str:
"""Validate the given MINs."""
_, invalid_mins = min_validator.return_valid_and_invalid_mins(list(items_dict.keys()))
if len(invalid_mins) == 0:
dlq_message.clear()
return constants.NO_VALIDATION_ERRORS
logger.warning("Kafka message has invalid mins")
dlq_message["invalid_store_or_mins"]["mins"] = invalid_mins
for item in invalid_mins:
items_dict.pop(item)
return constants.FOUND_INVALID_MINS