diff --git a/Infrastructure/GetHotSpots.template b/Infrastructure/GetHotSpots.template index 7a8c530..3940299 100644 --- a/Infrastructure/GetHotSpots.template +++ b/Infrastructure/GetHotSpots.template @@ -8,10 +8,10 @@ Parameters: Type: String Description: The key of the zip file where the lambda code is stored in s3. Default: lambdas.zip - HotSpotDynamoDbTabeArn: + HotSpotDynamoDbTableArn: Type: String Description: The ARN of the DynamoDB table for HotSpot - HotSpotDynamoDbTabeName: + HotSpotDynamoDbTableName: Type: String Description: The name of the DynamoDB table for HotSpot Resources: @@ -26,7 +26,7 @@ Resources: Description: Get Hot Spots lambda code Environment: Variables: - TABLE_NAME: !Ref HotSpotDynamoDbTabeName + TABLE_NAME: !Ref HotSpotDynamoDbTableName Handler: GetHotSpots.get_hot_spots_handler MemorySize: 128 ReservedConcurrentExecutions: 1 @@ -60,7 +60,7 @@ Resources: - Effect: Allow Action: - dynamodb:Query - Resource: !Ref HotSpotDynamoDbTabeArn + Resource: !Ref HotSpotDynamoDbTableArn Outputs: diff --git a/Infrastructure/HotSpotDynamoDbTable.template b/Infrastructure/HotSpotDynamoDbTable.template index 811cc0e..3a2ea47 100644 --- a/Infrastructure/HotSpotDynamoDbTable.template +++ b/Infrastructure/HotSpotDynamoDbTable.template @@ -1,5 +1,11 @@ AWSTemplateFormatVersion: '2010-09-09' +Parameters: + HotSpotDynamoTableLocaionIndex: + Type: String + Description: Name of the Location ID index + Default: locationID-date_time-index + Resources: HotSpotTable: Type: AWS::DynamoDB::Table @@ -17,7 +23,7 @@ Resources: - AttributeName: date_time KeyType: RANGE GlobalSecondaryIndexes: - - IndexName: locationID-date_time-index + - IndexName: !Ref HotSpotDynamoTableLocaionIndex KeySchema: - AttributeName: locationID KeyType: HASH diff --git a/Infrastructure/PutHotSpot.template b/Infrastructure/PutHotSpot.template index 431417f..c699758 100644 --- a/Infrastructure/PutHotSpot.template +++ b/Infrastructure/PutHotSpot.template @@ -8,12 +8,16 @@ Parameters: Type: String Description: The key of the zip file where the lambda code is stored in s3. Default: lambdas.zip - HotSpotDynamoDbTabeArn: + HotSpotDynamoDbTalbeArn: Type: String Description: The ARN of the DynamoDB table for HotSpot - HotSpotDynamoDbTabeName: + HotSpotDynamoDbTableName: Type: String Description: The name of the DynamoDB table for HotSpot + HotSpotDynamoTableLocaionIndex: + Type: String + Description: The name for the index of the locationID in the HotSpot db + Default: locationID-date_time-index Resources: PutHotSpotLambda: Type: "AWS::Lambda::Function" @@ -26,7 +30,7 @@ Resources: Description: Put Hot Spots lambda code Environment: Variables: - TABLE_NAME: !Ref HotSpotDynamoDbTabeName + TABLE_NAME: !Ref HotSpotDynamoDbTableName Handler: PutHotSpot.put_hot_spot_handler MemorySize: 128 ReservedConcurrentExecutions: 1 @@ -61,7 +65,13 @@ Resources: Action: - dynamodb:PutItem - dynamodb:Query - Resource: !Ref HotSpotDynamoDbTabeArn + - dynamodb:DeleteItem + Resource: !Ref HotSpotDynamoDbTalbeArn + - Effect: Allow + Action: + - dynamodb:Query + Resource: !Sub ${HotSpotDynamoDbTalbeArn}/index/${HotSpotDynamoTableLocaionIndex} + Outputs: RoleArn: diff --git a/Source/GetHotSpots.py b/Source/GetHotSpots.py index 3344551..1945f8a 100644 --- a/Source/GetHotSpots.py +++ b/Source/GetHotSpots.py @@ -32,13 +32,11 @@ def get_hot_spots_handler(event, context): lng = Decimal('{:.1f}'.format(lng)) view_range = event['event'].get('range', 0) print('lat: {}, lng: {}'.format(lat, lng)) - lat_lng_key = Key('lat_lng').eq('{}_{}'.format(lat, lng)) date_key = Key('date_time').gt(oldest_record) print('key: {}_{}'.format(lat, lng)) response = {"Items": []} try: - # if view_range: floor = view_range outter = 0 - view_range print('floor: {}'.format(floor)) diff --git a/Source/PutHotSpot.py b/Source/PutHotSpot.py index b9eafcd..64a804d 100644 --- a/Source/PutHotSpot.py +++ b/Source/PutHotSpot.py @@ -1,66 +1,114 @@ +import datetime import os -from datetime import datetime from decimal import Decimal import boto3 from botocore.exceptions import ClientError +dynamodb = boto3.resource("dynamodb") +table = dynamodb.Table(os.getenv('TABLE_NAME')) + def put_hot_spot_handler(event, context): - print('event: {}'.format(event)) - dynamodb = boto3.resource("dynamodb") - - table = dynamodb.Table(os.getenv('TABLE_NAME')) - lat = Decimal(str(event.get('lat', 35.7721))) - lng = Decimal(str(event.get('lng', -78.6441))) - id = context.aws_request_id - hash = str(event.get('hash', 'no hash')) - print("lat, lng: {} {}".format(lat, lng)) - date_time = datetime.now() - color_code = event.get('colorCode', '1') + print('starting to read.. event: {}'.format(event)) + updated_existing_item = False + if event.get('locationID', ''): + print('found locationID: {}'.format(event.get('locationID'))) + updated_existing_item = update_existing_item(event) + + if not updated_existing_item: + print('item not updatedable, moving on with new locationID') + event['locationID'] = context.aws_request_id + return put_new_location(event) - key = '{:.1f}_{:.1f}'.format(lat, lng) - print('key: {}'.format(key)) - response = {} +def update_existing_item(input_dict: dict): + lat, lng, location_id, input_hash, date_time, color_code, key = unpack_values(input_dict) + + print('looking for a location: {}'.format(location_id)) + two_hours_less = datetime.timedelta(hours=2) + minus_two = date_time - two_hours_less + query_response = table.query(IndexName='locationID-date_time-index', + KeyConditionExpression='locationID = :location_id and date_time > :date_time_value', + FilterExpression='lat_lng = :lat_lng_value', + ExpressionAttributeValues={ + ":location_id": location_id, + ":date_time_value": '{}'.format(minus_two), + ':lat_lng_value': key + }) + print('response.... {}'.format(query_response)) + if not query_response['Items']: + return False + print('found Items...') + old_date_time = query_response['Items'][0]['date_time'] + del_response = table.delete_item(Key={'lat_lng': key, 'date_time': old_date_time}) + print('del response: {}'.format(del_response)) + return True + + +def put_new_location(input_dict: dict): + lat, lng, location_id, input_hash, date_time, color_code, key = unpack_values(input_dict) + response = '' try: + new_put_item = { + 'lat_lng': key, + 'lat': lat, + 'lng': lng, + 'date_time': "{}".format(date_time), + 'locationID': location_id, + 'colorCode': color_code + } + if input_hash: + new_put_item['hash'] = input_hash response = table.put_item( - Item={ - 'lat_lng': key, - 'lat': lat, - 'lng': lng, - 'date_time': "{}".format(date_time), - 'locationID': id, - 'hash': hash, - 'colorCode': color_code - } + Item=new_put_item ) print("response: {}".format(response)) except ClientError as e: print("error: {}".format(e.response['Error']['Message'])) if response: - return { + return_dict = { "response": "success", - "locationID": id + "locationID": location_id } else: - return {"message": "error"} + return_dict = {"message": "error"} + + print('return_dict: {}'.format(return_dict)) + return return_dict + + +def unpack_values(input_dict: dict) -> tuple: + print('event: {}'.format(input_dict)) + lat = Decimal(str(input_dict.get('lat', 35.7721))) + lng = Decimal(str(input_dict.get('lng', -78.6441))) + location_id = str(input_dict.get('locationID', '')) + input_hash = str(input_dict.get('hash', '')) + print("lat, lng: {} {}".format(lat, lng)) + date_time = datetime.datetime.now() + color_code = input_dict.get('colorCode', 1) + + key = '{:.1f}_{:.1f}'.format(lat, lng) + print('key: {}'.format(key)) + + return lat, lng, location_id, input_hash, date_time, color_code, key if __name__ == '__main__': class Context: def __init__(self): - self.aws_request_id = '123' + self.aws_request_id = '123123123123' - os.environ['TABLE_NAME'] = "HotSpotAlpha" + os.environ['TABLE_NAME'] = "HotSpotDynamoDbTable-HotSpotTable-F6VB59AJ2YDK" event_dict = { 'lat': 123.2, 'lng': 321.1, - 'colorCode': 1 + 'colorCode': 1, + "locationID": '123123123123' } - context = Context() - print(put_hot_spot_handler(event_dict, context)) + test_context = Context() + print(put_hot_spot_handler(event_dict, test_context))