Esempio n. 1
0
def update_record(table_name, item_key: dict, update_dictionary: dict):
    """
    update dynamo DB by dictionary automatically. Don't need to write dynamodb expression as this
    function will help you write it.

    Args:
        dynamodb_resource: a dynamo DB resource instance
        table_name: the name of the table we want to scan
        key: the key for update
        update_dictionary: the dictionary for update


    Returns:
        response from dynamo DB
    """
    (update_expression, expression_attr_values) = construct_update_expression(
        item_key, update_dictionary)
    table = get_dynamo_table(table_name)
    response = table.update_item(
        Key=item_key,
        UpdateExpression=update_expression,
        ConditionExpression=Attr('version').eq(update_dictionary['version'] -
                                               1),
        ExpressionAttributeValues=expression_attr_values,
        ReturnValues="ALL_NEW")
    return response
Esempio n. 2
0
def invalidate_record(table_name: TableNames, item_key: dict, version: int,
                      last_updated_by: str):
    """
    Fake delete a record by setting isValid to false.
    The caller must have the latest version of the record.
    This check prevents races, as a part of the optimistic write technique, often also
    referred to as CAS (compare and swap).
    """
    if table_name is None or item_key is None or version is None or last_updated_by is None:
        raise ValueError(
            "Either of these is None: table_name[{}], item_key[{}], version[{}], lastUpdatedBy[{}]"
            .format(table_name, item_key, version, last_updated_by))

    table = get_dynamo_table(table_name)
    update_expression = 'SET {0} = :{0}, {1} = :{1}, {2} = :{2}'.format(
        'isValid', 'version', 'lastUpdatedBy')
    new_item = {
        ':isValid': False,
        ':version': version + 1,
        ':lastUpdatedBy': last_updated_by
    }
    response = table.update_item(
        Key=item_key,
        UpdateExpression=update_expression,
        ConditionExpression=Attr('version').eq(version),
        ExpressionAttributeValues=new_item,
        ReturnValues="ALL_NEW")
    return response
Esempio n. 3
0
def get_item(table_name, item_key: dict):
    try:
        table = get_dynamo_table(table_name)
        return table.get_item(Key=item_key, ConsistentRead=True)['Item']
    except:
        import traceback
        import sys
        traceback.print_tb(sys.exc_info()[2], limit=5)
        return None
Esempio n. 4
0
def create_item(event, context):
    item_unique_id = str(uuid.uuid1())
    try:
        data = event
        req_data = convert_to_dynamo_compatible(data['body'])
        user_id = get_user_id_from_gateway_event(event)
        email = get_email_from_gateway_event(event)
        username = get_username_from_gateway_event(event)

        required(
            req_data['item'],
            {'description', 'type', 'latitude', 'longitude', 'name', 'city'})

        item = {
            'id': item_unique_id,
            'isValid': True,
            'version': 0,
            'lastUpdatedBy': user_id,
            'lastUpdatedDateTime': now(),
            'description': req_data['item']['description'],
            'type': req_data['item']['type'],
            'latitude': req_data['item']['latitude'],
            'longitude': req_data['item']['longitude'],
            'username': username,
            'userId': user_id
        }

        # copy rest of the fields
        remaining_keys = set(req_data['item'].keys()) - set(item.keys())
        for k in remaining_keys:
            item[k] = req_data['item'][k]

        table = get_dynamo_table(TableNames.LISTING_TABLE)
        log.info(get_resolved_dynamo_table_name(TableNames.LISTING_TABLE))
        query_response = table.put_item(Item=item)
        log.info(json.dumps(query_response))
    except (KeyError, ClientError) as e:
        traceback.print_tb(sys.exc_info()[2], limit=5)
        log.error(sys.exc_info())
        raise e(sys.exc_info())
    else:
        response = generate_success_response(item)
        log.info(response)
        return response
Esempio n. 5
0
def query_table_all(table: TableNames, query_params: dict, filter_exp=None):
    """
    A table can be queried for primary index or secondary indexes.
    For all others use scan_table.
    query_table is much faster as it uses indexes for query, unlike
    scan_table which happens to be a full table scan.
    :param table:
    :param query_params:
    :return:
    """
    key_condition = None
    for k, v in query_params.items():
        if key_condition:
            key_condition = key_condition & Key(k).eq(v)
        else:
            key_condition = Key(k).eq(v)
    response = get_dynamo_table(table).query(
        KeyConditionExpression=key_condition, FilterExpression=filter_exp)
    items = response['Items']
    return items
Esempio n. 6
0
def scan_table_all(table_name, filtering_exp=None):
    """
    Perform a scan operation on table.
    While using this function, if isValid is not set in the filtering_exp, caller receives:
    VALID as well as INVALID records.

    DynamoDB table are paginated hence it is not guaranteed that this
    scan will be able to grab all the data in table.

    In order to scan the table page by page, we use a loop as indicated bellow.

    More details can be found here:
    https://www.tutorialspoint.com/dynamodb/dynamodb_scan.htm


    Args:
        dynamodb_resource: a dynamo DB resource instance
        table_name: the name of the table we want to scan
        filtering_exp: A valid dynamodb filter expression
        - Attr('assetStatus').eq('{}'.format('FINAL')) & Attr('isValid').eq(True)


    Returns:
        List of Items
    """
    table = get_dynamo_table(table_name)
    if filtering_exp is not None:
        response = table.scan(FilterExpression=filtering_exp)
    else:
        response = table.scan()
    # Get items
    items = response['Items']
    while response.get('LastEvaluatedKey'):
        response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey'],
                              ConsistentRead=True)
        items += response['Items']
    return items