Source code for lambdas.storepick_colleague_handler

import json
import sys
import time
from datetime import datetime, timedelta
import logging
from pymorri.exceptions import MoriException
from pymorri.util.datadog_utils import post_datadog_event_to_sns
from pymorri.util.response_builder import ResponseBuilder
from pymorri.api.morrisons.colleague import QueryColleagues
from pymorri.api.morrisons.colleaguediscount import DeleteColleagueDiscount
from pymorri.util.application_dependencies import ApplicationDependencies
from pymorri.util.general_utils import build_response_or_throw
from pymorri.util.gcp_clients import GCPStorageClient
from constants import APP_NAME, SSM_NAME, DATADOG_APP_NAME, DD_CHECK_METRIC_NAME

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

DEFAULT_TIMEOUT = 60

[docs]@build_response_or_throw def lambda_handler(event, context): """ This Lambda queries customer lists of leavers since yesterday and delete them using DELETE endpoint of colleague discount api (DELETE /colleaguediscount/v1/colleagues) Input: - event (dict) - can be empty json {} but CANNOT be None Output: - resp (dict): HTTP response - 200 on success and 500 on failure / exception Additionally function post CHECK status to DataDog API: - metric name: `colleague_discount_check` - 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. Example body: .. code-block:: python resp = { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, 'body': { "status": "success", "message": "Today colleage leavers deleted successfully", "body": [] } } Raises: MoriException: MoriException for timeout of retrieving file from QueryColleagues endpoint """ #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, }) all_leavers = [] successful_leavers_number = 0 failed_leavers_number = 0 deps = ApplicationDependencies(config_file=f"{APP_NAME}.json", ssm_param_store_name=SSM_NAME) timeout = int(deps.get_config().get("GET_COLLEAGE_JOB_ID_PROCESSING_TIMEOUT", DEFAULT_TIMEOUT)) scope = deps.get_config().get("QUERYCOLLEAGUES_SCOPE_VALUE", "LEAVER") today = datetime.today().strftime("%Y-%m-%d") query = QueryColleagues(ssm=deps.get_ssm_params(), configuration=deps.get_config()) resp = query.request(scope=scope, from_date=today, to_date=today) logger.info(f"QueryColleagues - resp: {resp}") job_id = resp.get("payload").get("jobId") logger.info(f"Retrieved job_id {job_id} from query GET /colleague endpoint " f"with params: scope: {scope}, from_date: {today}; to_date: {today}") status = "UNKNOWN" try_number = 0 start_time = datetime.now() #will be break when status == COMPLETED or when timeout occurs while True: end_time = datetime.now() try_number += 1 resp = query.request(job_id=job_id) payload = resp.get("payload") if payload: status = str(payload.get("status")) logger.info(f"Checking whether job_id {job_id} processing finished " f"- try_number: {try_number}. Resp: {resp}") if (end_time - start_time).total_seconds() > timeout: message = f"TIMEOUT of {timeout} seconds reached while processing job_id: {job_id}" logger.error(message) post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="check", metric_name=DD_CHECK_METRIC_NAME, metric_value="2") raise MoriException(http_status_code=500, detail=message) if status == "COMPLETED": break #sleep 5 seconds between each request time.sleep(5) resp_file = payload.get("file").split("gs://")[1] bucket_name = resp_file.split("/")[0] file_path = resp_file.split(f"{bucket_name}/")[1] all_leavers = GCPStorageClient(SSM_NAME).get_file_content( bucket_name, file_path, base64_encryption_key=deps.get_ssm_params().get("DECRYPTION_KEY") if deps.get_ssm_params().get( "DECRYPTION_KEY") and len(deps.get_ssm_params().get("DECRYPTION_KEY")) > 0 else None ) logger.info(f"Number of leavers to process: {len(all_leavers)}") post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="leavers_retrieved", metric_value=len(all_leavers)) delete_obj = DeleteColleagueDiscount(ssm=deps.get_ssm_params(), configuration=deps.get_config()) for leaver in all_leavers: employee_id = str(leaver.get("employeeId")) try: _ = delete_obj.request(employee_id) successful_leavers_number += 1 except MoriException as ex: failed_leavers_number += 1 if ex.http_status_code == 404: logger.warning(f"Customer NOT FOUND while DeleteColleague {employee_id} from API: {ex}") else: logger.error(f"EXCEPTION while DeleteColleague {employee_id} from API: {ex}") post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="leavers_success", metric_value=successful_leavers_number) post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="count", metric_name="leavers_failed", metric_value=failed_leavers_number) if failed_leavers_number == 0: event['response_message'] = "All today colleague leavers deleted successfully" post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="check", metric_name=DD_CHECK_METRIC_NAME, metric_value="0") logger.info(f"All today colleague leavers deleted") else: event['response_message'] = f"{successful_leavers_number}/{len(all_leavers)} today colleague leavers deleted" post_datadog_event_to_sns(application_name=DATADOG_APP_NAME, metric_type="check", metric_name=DD_CHECK_METRIC_NAME, metric_value="1") logger.warning(f"{successful_leavers_number}/{len(all_leavers)} today colleague leavers deleted") return event
if __name__ == "__main__": event = {} response = lambda_handler(event, None) logger.info(f"{response}")