"""Lambda function module.""" import json import config from src.common import common_config from src.common import elastic_transcoder from src.common import lambda_exceptions from src.common.constants import transcoding_types from owsrequest import request def _parse_elastic_transcoder_message(message): final_assets = [] errors = None status = message['state'] if status == 'COMPLETED': # get exact duration of output files from Elastic Transcoder Job job = elastic_transcoder.get_job_by_id(message['jobId']) output_key_duration_map = {output['Key']: output['DurationMillis'] for output in job['Job']['Outputs']} outputs = message['outputs'] for output in outputs: preset = output['presetId'] if preset == elastic_transcoder.PRESET_MP3_320K: container = transcoding_types.CONTAINER_MPEG3 elif preset == elastic_transcoder.PRESET_FLAC: container = transcoding_types.CONTAINER_FLAC else: raise Exception(f'Unexpected PresetId: {preset}') final_assets.append({ 'key': output['key'], 'duration': output_key_duration_map[output['key']], 'container': container }) if status == 'ERROR': errors = {'elastic_transcoder_error': message.get('messageDetails', None)} return status, final_assets, errors def sns_event_get_final_status_details(event): """Get filename and status from SNS message. Args: event (dict): AWS SNS event object. Returns: dict: Dictionary with keys: status, errors, filename, timestamp, final_assets. """ sns_body = event['Records'][0]['Sns'] subject = sns_body.get('Subject') timestamp = sns_body.get('Timestamp') message_json = sns_body['Message'] message = json.loads(message_json) filename = message['input']['key'] if subject and 'Amazon Elastic Transcoder' in subject: status, final_assets, errors = _parse_elastic_transcoder_message(message) else: # this message is coming from image_encoding status = message['status'] errors = message.get('errors') final_assets = message.get('final_assets', []) data = { 'status': 'encoding_{}'.format(status.lower()), 'errors': errors, 'filename': filename, 'timestamp': timestamp, 'final_assets': final_assets } return data def post_asset_final_status(status_data): """Call ows-asset post asset final status handler. Args: status_data (dict): Status data. Returns: bool: True if success else raise Exception. """ response = request.process( application=config.APPLICATION_NAME, environment=common_config.ENVIRONMENT, method='POST', service_name=common_config.OWS_ASSETS_SERVICE_NAME, path=common_config.POST_ASSET_FINAL_STATUS_PATH, json=status_data) if response.status_code == 404: raise lambda_exceptions.PostAssetNotFoundError(response) if response.status_code != 200: raise lambda_exceptions.PostAssetError(response) return response.json() def handler(event, context): """Lambda entry point. Saves asset final status. Args: event (dict): Object with asset status info. context (dict): Environment state. Returns: bool: True if success else raise Exception. """ try: status_data = sns_event_get_final_status_details(event) post_asset_final_status(status_data) return {'status': 'OK', 'message': 'final status message sent'} except Exception as e: # TODO: add handling S3Error config.logger.exception(str(e)) raise