Source code for lambdas.process_ocean_events

import os
import logging
import boto3
import traceback

from pymorri.exceptions import MoriException
from pymorri.util.response_builder import ResponseBuilder
from pymorri.util.aws_utils import get_event_from_sns, publish_event_to_sns
from pymorri.util.general_utils import build_response_or_throw
from pymorri.util.serverless_utils import resolve_env, get_or_exception
from pymorri.util.datadog_utils import post_datadog_event_to_sns
from pymorri.api.morrisons.customer import Customer
from constants import DATADOG_APP_NAME, OCEAN_SSM_KEY, APP_NAME, DD_CHECK_METRIC_NAME, COLLEAGUE_DISCOUNT_CONFIG, \
    DATADOG_CREATE_SHELL_AC_APP_NAME, DATADOG_PROCESS_OCEAN_EVENTS_APP_NAME
from pymorri.util.application_dependencies import ApplicationDependencies

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

deps = None


def _prepare_deps():
    global deps

    if not deps:
        deps = ApplicationDependencies(
            config_file=COLLEAGUE_DISCOUNT_CONFIG,
            ssm_param_store_name=OCEAN_SSM_KEY,
        )


[docs]def delete_from_dynamodb(dynamodb, source_system_cust_id, table_name): dynamodb_response = dynamodb.delete_item( TableName=table_name, Key={ "customerID": {"S": source_system_cust_id}, } ) logger.info(f'dynamodb_response {dynamodb_response}') post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="ocean_colleague_discount_remove", metric_value="1")
[docs]def put_into_dynamodb(dynamodb, source_system_cust_id, table_name): _ = dynamodb.put_item( TableName=table_name, Item={ "customerID": {"S": source_system_cust_id}, } ) post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="ocean_colleague_discount_create", metric_value="1")
[docs]@get_event_from_sns @build_response_or_throw def lambda_handler(event, context): """ This lambda receives event from SNS (event example given further below) For eventType 'addCustomerToOcean': - Lambda gets event from SNS with data to create rows in dynamodb table ENV.xxwmm.storepick.ocean_colleague_discount related to provided customerId. For eventType 'removeCustomerFromOcean': - Lambda removes rows related to provided customerId from above dynamodb table. Additionally function post CHECK status to DataDog API: - metric name: `colleague_discount_check` in DataDog - app name: `storepick_colleague_discount` It sends: * value 0 (SUCCESS) when this function returns 200 * value 2 (ERROR) when this function throws exception + exception is handled and processed in `build_response_or_throw` decorator and error response with 500 or 4xx is sent. Input: - event (dict) - required: eventType, eventData .. code-block:: python { "eventType": "addCustomerToOcean|removeCustomerFromOcean", "eventData": { "customerId": "1234567" } } Output: - event (dict) - required: eventType, eventData .. code-block:: python { "eventType": "addCustomerToOcean", "eventData": { "customerId": "1234567" } } Raises: MoriException: MoriException containing details about exception """ ################################################################################ # need to populate the global deps (which is cached deliberately outside this # main handler ################################################################################ _prepare_deps() global deps # update event in order this function could send STATUS data to DataDog API # from build_response_or_throw event.update({ "DATADOG_APP_NAME": DATADOG_APP_NAME, "DD_CHECK_METRIC_NAME": DD_CHECK_METRIC_NAME, }) event_type = get_or_exception(event, "eventType") event_data = get_or_exception(event, "eventData") customer_id = get_or_exception(event_data, "customerId") club_id = get_or_exception(event, "club_id") # get sourceSystemId from API based on customerId try: logger.info(f"Getting data for customer with customer_id: {customer_id}") customer = Customer(configuration=deps.get_config(), ssm=deps.get_ssm_params()) resp = customer.request(customer_id) logger.info(f"Successfully got data for customer with customer_id: {customer_id}") except MoriException as ex: if ex.http_status_code == 404: logger.warning(f"Customer {customer_id} does NOT EXISTS in Morrisons Customer V2 API") post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="ocean_customer_not_found", metric_value="1") event['response_message'] = "customer not found" return event else: logger.error("Unexpected exception from request Customer V2") raise ex source_system_cust_id = resp.get('payload').get("sourceSystemCustomerId") if not source_system_cust_id or len(source_system_cust_id.strip()) == 0: error_msg = f"source_system_cust_id is null for customer_id {customer_id}" logger.error(error_msg) post_datadog_event_to_sns(application_name=DATADOG_PROCESS_OCEAN_EVENTS_APP_NAME, metric_type="count", metric_name="ocean_colleague_discount_no_source_id", metric_value="1") raise MoriException(http_status_code=500, detail=error_msg) logger.info(f"Got source_system_cust_id from API: {source_system_cust_id}") dynamodb = boto3.client("dynamodb") table_name = os.environ.get("COLLEAGUE_DISCOUNT_TABLE") friends_and_family_table_name = os.environ.get("FRIENDS_AND_FAMILY_DISCOUNT_TABLE") if event_type not in ("addCustomerToOcean", "removeCustomerFromOcean"): msg = f"invalid event type for processing {event_type}" logger.warning(msg) post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="ocean_customer_fail", metric_value="1") event['response_message'] = msg return event if event_type == "addCustomerToOcean": # not needed to get response => if error then exception will be thrown # which should be cautght in build_response_or_throw and published into # failure SNS topic if club_id == "6": put_into_dynamodb(dynamodb, source_system_cust_id, table_name) elif club_id == "7": put_into_dynamodb(dynamodb, source_system_cust_id, friends_and_family_table_name) elif event_type == "removeCustomerFromOcean": # not needed to get response => if error then exception will be thrown # which should be cautght in build_response_or_throw and published into # failure SNS topic if club_id == "6": logger.info(f'club_id {club_id}') delete_from_dynamodb(dynamodb, source_system_cust_id, table_name) elif club_id == "7": logger.info(f'club_id {club_id}') delete_from_dynamodb(dynamodb, source_system_cust_id, friends_and_family_table_name) return event
if __name__ == "__main__": event = { "eventType": "addCustomerToOcean", "eventData": { # "customerId" : "1234567" "customerId": "1025974240" } } response = lambda_handler(event, '') logger.info(f"{response}")