"""Lambda to begin step machine execution upon S3 trigger.""" import json import os from random import random from time import sleep from common.helpers.asset import copy_asset from common.helpers.asset import create_asset_token from common.helpers.bulk_asset import load_bulk_asset_json import config from config import graphql_gateway from constants import jitter as jitter_const from lambdacommon.graphql.graphql import GraphQLError def handler(event, context): """Lambda handler entry point.""" correlation_id = event.get('correlation_id') # DDEX_INGESTER_INTEGRATION: Implemented standard logger, not # DDEXIngesterAdapter logger logger = config.get_current_logger(correlation_id) # Jitter calls jitter(correlation_id) graphql_gateway.set_headers( { 'Orchard-User-Id': config.OA_USER, 'Correlation-Id': correlation_id } ) # Log lambda begins message logger.info(f'handle_artwork received: {event}') # DDEX_INGESTER_INTEGRATION: Skip ddex-ingester context JSON, load basic # JSON elements asset = load_bulk_asset_json(event) # DDEX_INGESTER_INTEGRATION: Ignore ddex-ingester extended logger # # update_logger_with_message_ids( # logger, # s3_data.message_id, # s3_data.message_thread_id, # s3_data.execution_name # ) artwork = asset.product.artwork # Get our source key and bucket src_bucket = artwork.bucket src_key = artwork.key logger.info(f'Artwork source bucket: {src_bucket}') logger.info(f'Artwork key: {src_key}') # DDEX_INGESTER_INTEGRATION: From lambda-ddex-ingester (handle_artwork) # TODO: Move image pre-processing to separate lambda based on # lambda-ripper-feeder # # Make sure the artwork image has the correct dimensions # process_artwork_size(artwork) # Ask for a token from ows-assets # TODO: For speed increases, get asset_tokens in bulk earlier, and pass a # token name into the handler via the event try: asset_token = create_asset_token(graphql_gateway, 'image') except GraphQLError as e: error_str = 'GraphQL create asset error' msg = f'{error_str}: {str(e)}' logger.error(msg) raise e # Construct metadata and copy our asset to target bucket from ows-assets filename = asset_token['filename'] + os.path.splitext(artwork.filename)[1] target_bucket = asset_token['bucket'] logger.info(f'Target bucket: {target_bucket}') logger.info(f'Target filename/key: {filename}') s3_metadata = construct_s3_metadata( asset.product, artwork ) try: copy_asset(s3_metadata, artwork, target_bucket, filename) except Exception as e: error_str = 'S3 Copy error' msg = f'{error_str}: {str(e)}' logger.error(msg) raise e artwork.ows_assets_filename = filename asset.product.artwork = artwork return json.loads( json.dumps(asset, default=lambda s: vars(s))) # DDEX_INGESTER_INTEGRATION: Modified to remove is_correction param def construct_s3_metadata( product, artwork) -> dict: """Construct metadata dict for s3.""" return { 'asset_type': format_asset_type(artwork), 'product_id': str(product.product_id), 'upc': str(product.upc), 'track_unique_id': '0', 'original_filename': artwork.filename, 'is_correction': '0', } def format_asset_type(artwork): """Format asset type from asset artwork.""" return os.path.splitext(artwork.filename)[1].strip('.').upper() def jitter(correlation_id): """Jitter lambda calls so the systems don't get hammered.""" logger = config.get_current_logger(correlation_id) if config.ENVIRONMENT.upper() == 'PROD': jitter_amt = (random() + random()) / jitter_const.PROD_FACTOR else: jitter_amt = (random() + random()) / jitter_const.QA_FACTOR logger.info(f'Jittering: {jitter_amt}') sleep(jitter_amt)