Beispiel #1
0
def handler(event, context):
    """Method invoked by Lambda event. Verifies that records were received and,
    if so, passes them to be parsed"""
    logger.debug('Starting Lambda Execution')

    records = event.get('Records')

    if records is None:
        logger.error('Records block is missing in SQS Message')
        raise NoRecordsReceived('Records block missing', event)
    elif len(records) < 1:
        logger.error('Records block contains no records')
        raise NoRecordsReceived('Records block empty', event)

    results = parseRecords(records)

    logger.info('Successfully invoked lambda')

    # This return will be reflected in the CloudWatch logs
    # but doesn't actually do anything
    return results
Beispiel #2
0
def handler(event, context):
    """Central handler invoked by Lambda trigger. Begins processing of kinesis
    stream.
    """
    logger.debug('Starting Lambda Execution')

    records = event.get('Records')

    if records is None:
        logger.error('Records block is missing in Kinesis Event')
        raise NoRecordsReceived('Records block missing', event)
    elif len(records) < 1:
        logger.error('Records block contains no records')
        raise NoRecordsReceived('Records block empty', event)

    results = parseRecords(records)

    logger.info('Successfully invoked lambda')

    # This return will be reflected in the CloudWatch logs
    # but doesn't actually do anything
    return results
Beispiel #3
0
def parseRecord(encodedRec, updater):
    """Handles each individual record by parsing JSON from the base64 encoded
    string recieved from the Kinesis stream, creating a database session and
    inserting/updating the database to reflect this new data source. It will
    rollback changes if an error is encountered
    """
    try:
        record = json.loads(base64.b64decode(encodedRec['kinesis']['data']))
        statusCode = record['status']
        if statusCode != 200:
            if statusCode == 204:
                logger.info('No updates received')
                raise NoRecordsReceived(
                    'No records received from {}'.format(record['source']),
                    record
                )
            else:
                logger.error('Received error from pipeline')
                logger.debug(record)
                raise DataError('Received non-200 status code')
    except json.decoder.JSONDecodeError as jsonErr:
        logger.error('Invalid JSON block received')
        logger.error(jsonErr)
        raise DataError('Invalid JSON block')
    except (UnicodeDecodeError, binascii.Error) as b64Err:
        logger.error('Invalid data found in base64 encoded block')
        logger.debug(b64Err)
        raise DataError('Error in base64 encoding of record')

    outRec = None
    try:
        MANAGER.startSession()  # Start transaction
        outRec = updater.importRecord(deepcopy(record))
        MANAGER.commitChanges()
    except OperationalError as opErr:
        logger.error('Conflicting updates caused deadlock, retry')
        logger.debug(opErr)
        OutputManager.putKinesis(
            record.get('data'),
            os.environ['UPDATE_STREAM'],
            recType=record.get('type', 'work'),
        )
        MANAGER.session.rollback()  # Rollback current record only except
    except IntegrityError as intErr:
        logger.error('Unique constraint violated, retry')
        logger.debug(intErr)
        OutputManager.putKinesis(
            record.get('data'),
            os.environ['UPDATE_STREAM'],
            recType=record.get('type', 'work'),
        )
        MANAGER.session.rollback()  # Rollback current record only
    except Exception as err:  # noqa: Q000
        # There are a large number of SQLAlchemy errors that can be thrown
        # These should be handled elsewhere, but this should catch anything
        # and rollback the session if we encounter something unexpected
        logger.error('Failed to store record')
        logger.debug(err)
        logger.debug(traceback.format_exc())
        MANAGER.session.rollback()  # Rollback current record only

    return outRec
Beispiel #4
0
 def test_NoRecordsReceived(self):
     testNoRecs = NoRecordsReceived('testMessage', 'testInvocation')
     assert testNoRecs.message == 'testMessage'
     assert testNoRecs.invocation == 'testInvocation'