"""GraphQL logic.""" from time import sleep from types import SimpleNamespace from connectors.logging import logger as log from connectors.graphql import GraphQLBackoffConnector, \ GraphQLError from constants import graphql_queries from utils.graphql_utils import format_approve_product from config import ( GRAPHQL_GATEWAY_URL, APPLICATION_NAME, OA_USER, ORCH_HEADER_IDENTITY_ID, ORCH_HEADER_PROFILE_ID, ORCH_HEADER_PROFILE_TYPE, ORCH_HEADER_ROLE ) # create GraphQL connector graphql_conn = GraphQLBackoffConnector(GRAPHQL_GATEWAY_URL, APPLICATION_NAME) graphql_conn.set_headers({ 'Orchard-Profile-Type': ORCH_HEADER_PROFILE_TYPE, 'Orchard-Profile-Id': ORCH_HEADER_PROFILE_ID, 'Orchard-Identity-Id': ORCH_HEADER_IDENTITY_ID, 'Orchard-Roles': ORCH_HEADER_ROLE, 'Orchard-User-Id': OA_USER, }) def approve_products(product_id_list, sleep_time=None): """Set all products in a session to be in_content.""" # Default sleep if not sleep_time: sleep_time = 0.1 # Init method result object results = [] # Sanity check if not len(product_id_list): log.warning('No eligible releases found to approve in graph.') return # Notify user msg = '{} GraphQL calls will be made.'.format(len(product_id_list)) log.info(msg) # Loop and approve products for product_id in product_id_list: response = None error = None try: is_valid, _, _ = validate_product(product_id) if is_valid: log.info(f'{product_id} is valid.') response, error = approve_product(product_id) log.info(f'{product_id} approved.') else: log.warning(f'{product_id} skipped as invalid.') except Exception as e: # Fashion default error fields status = 'python_error' err_code = 0 status_text = 'Python Error' err_msg = str(e) # Push error metadata to method result object error = { 'product_id': product_id, 'status': status, 'error_code': err_code, 'status_text': status_text, 'message': err_msg } # Notify user of Python logic error msg = 'Python Error - Product Id {} product approval call ' \ 'failed - Error Code: {} - {} : {} : {}' \ .format(product_id, status, err_code, status_text, err_msg) log.error(msg) results.append(SimpleNamespace(response=response, error=error)) sleep(sleep_time) return results def approve_product(product_id): """Approve a single product.""" response = None error = None approve_product_data = format_approve_product(product_id=product_id) try: # Fire single GraphQL call response = graphql_conn.execute( graphql_queries.approve_product, {"data": approve_product_data} ) # Notify user success msg = 'GraphQL Call Completed - Product Id {} ' \ 'approved.'.format(product_id) log.info(msg) except GraphQLError as ge: # Push error metadata to method result object error = { 'product_id': product_id, 'status': 'graphql_error', 'error_code': ge.code, 'status_text': 'GraphQL Error', 'message': ge.message } # Notify user of GraphQL error msg = 'GraphQL Call Error - Product Id {} product approval ' \ 'call failed - Error Code: graphql_error - {} : GraphQL ' \ 'Error : {}'.format(product_id, ge.code, ge.message) log.error(msg) return response, error def validate_product(product_id): """Validates a single product.""" product_errors = None track_errors = None is_valid = True validate_result = graphql_conn.execute( graphql_queries.validate_product, {'productId': str(product_id)} )['data']['product'] upc = validate_result['upc'] log.info(f'Validating {product_id} ({upc}):') if not validate_result['validation']['isValid']: is_valid = False product_errors = validate_result['validation']['errors'] if product_errors: product_errors = flatten_errors(product_errors) log.info(f'Product errors: {product_errors}') for track in validate_result['tracks']: if not track['validation']['isValid']: is_valid = False track_errors = track['validation']['errors'] vol_num = track['volumeNumber'] track_num = track['trackNumber'] if track_errors: track_errors = flatten_errors(track_errors) log.info( f'Track errors ({upc}_{vol_num}_{track_num}): ' f'{track_errors}') if not validate_result['isArtworkValid']: is_valid = False return is_valid, product_errors, track_errors def flatten_errors(errors): """Convert nested list to one dimension error list. Args: errors (list): list of errors isrc (str): ISRC Returns: list """ flattened_errors = [] for _, value in enumerate(errors): if type(value) == list: flattened_errors += flatten_errors(value) else: message = value['reason'] flattened_errors.append(message) return flattened_errors