[server]: Add return_historical_data
This commit is contained in:
@ -0,0 +1,51 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import boto3
|
||||||
|
from boto3.dynamodb.conditions import Key, Attr
|
||||||
|
|
||||||
|
os.environ.setdefault('AWS_DEFAULT_REGION', 'us-east-1')
|
||||||
|
dynamodb = boto3.resource('dynamodb')
|
||||||
|
|
||||||
|
def lambda_handler(event, context):
|
||||||
|
table = dynamodb.Table(os.environ['TABLE_NAME'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
if 'queryStringParameters' in event and event['queryStringParameters'] and 'objectType' in event[
|
||||||
|
'queryStringParameters']:
|
||||||
|
|
||||||
|
objectType = event['queryStringParameters']['objectType']
|
||||||
|
object_types = objectType.split(',')
|
||||||
|
|
||||||
|
items = []
|
||||||
|
response = table.scan(
|
||||||
|
FilterExpression=Attr('objectType').is_in(object_types)
|
||||||
|
)
|
||||||
|
items.extend(response.get('Items', []))
|
||||||
|
|
||||||
|
# Handle pagination
|
||||||
|
while 'LastEvaluatedKey' in response:
|
||||||
|
response = table.scan(
|
||||||
|
FilterExpression=Attr('objectType').is_in(object_types),
|
||||||
|
ExclusiveStartKey=response['LastEvaluatedKey']
|
||||||
|
)
|
||||||
|
items.extend(response.get('Items', []))
|
||||||
|
else:
|
||||||
|
# Fallback to scanning the entire table
|
||||||
|
items = []
|
||||||
|
response = table.scan()
|
||||||
|
items.extend(response.get('Items', []))
|
||||||
|
|
||||||
|
while 'LastEvaluatedKey' in response:
|
||||||
|
response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey'])
|
||||||
|
items.extend(response.get('Items', []))
|
||||||
|
|
||||||
|
return {
|
||||||
|
'statusCode': 200,
|
||||||
|
'body': json.dumps(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'statusCode': 500,
|
||||||
|
'body': json.dumps({'error': str(e)})
|
||||||
|
}
|
@ -41,7 +41,7 @@ def lambda_handler(event, context):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
'statusCode': 200,
|
'statusCode': 200,
|
||||||
'body': json.dumps(items)
|
'body': json.dumps(items, default=str)
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
9
server/src/test/return_historical_data/return_historical_data.sh
Executable file
9
server/src/test/return_historical_data/return_historical_data.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
API_URL="https://8g93x0lm0l.execute-api.us-east-1.amazonaws.com/return_historical_data"
|
||||||
|
|
||||||
|
if [ "$1" ]; then
|
||||||
|
query_string="?objectType=$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl "$API_URL$query_string"
|
@ -0,0 +1,127 @@
|
|||||||
|
import unittest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from functions.return_historical_data.lambda_function import lambda_handler
|
||||||
|
|
||||||
|
|
||||||
|
class TestLambdaFunction(unittest.TestCase):
|
||||||
|
|
||||||
|
# Mock environment variable before each test
|
||||||
|
def setUp(self):
|
||||||
|
patch.dict(os.environ, {'TABLE_NAME': 'test-table'}).start()
|
||||||
|
|
||||||
|
# Clean up patches after each test
|
||||||
|
def tearDown(self):
|
||||||
|
patch.stopall()
|
||||||
|
|
||||||
|
@patch('functions.return_historical_data.lambda_function.dynamodb.Table')
|
||||||
|
def test_lambda_handler_with_object_type(self, mock_table):
|
||||||
|
# Mock scan response for specific object types
|
||||||
|
mock_table.return_value.scan.return_value = {
|
||||||
|
'Items': [
|
||||||
|
{'objectID': '1', 'objectType': 'Bus'},
|
||||||
|
{'objectID': '2', 'objectType': 'Train'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mock event with objectType query parameter
|
||||||
|
event = {
|
||||||
|
'queryStringParameters': {
|
||||||
|
'objectType': 'Bus,Train'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lambda_handler(event, {})
|
||||||
|
self.assertEqual(result['statusCode'], 200)
|
||||||
|
|
||||||
|
# Parse result body
|
||||||
|
body = json.loads(result['body'])
|
||||||
|
self.assertEqual(len(body), 2)
|
||||||
|
self.assertEqual(body[0]['objectType'], 'Bus')
|
||||||
|
self.assertEqual(body[1]['objectType'], 'Train')
|
||||||
|
|
||||||
|
@patch('functions.return_historical_data.lambda_function.dynamodb.Table')
|
||||||
|
def test_lambda_handler_with_pagination(self, mock_table):
|
||||||
|
# Mock paginated scan responses
|
||||||
|
mock_table.return_value.scan.side_effect = [
|
||||||
|
{'Items': [{'objectID': '1', 'objectType': 'Bus'}], 'LastEvaluatedKey': 'key1'},
|
||||||
|
{'Items': [{'objectID': '2', 'objectType': 'Train'}], 'LastEvaluatedKey': 'key2'},
|
||||||
|
{'Items': [{'objectID': '3', 'objectType': 'Luas'}]}
|
||||||
|
]
|
||||||
|
|
||||||
|
event = {
|
||||||
|
'queryStringParameters': {
|
||||||
|
'objectType': 'Bus,Train,Luas'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lambda_handler(event, {})
|
||||||
|
self.assertEqual(result['statusCode'], 200)
|
||||||
|
|
||||||
|
body = json.loads(result['body'])
|
||||||
|
self.assertEqual(len(body), 3)
|
||||||
|
self.assertEqual(body[0]['objectType'], 'Bus')
|
||||||
|
self.assertEqual(body[1]['objectType'], 'Train')
|
||||||
|
self.assertEqual(body[2]['objectType'], 'Luas')
|
||||||
|
|
||||||
|
@patch('functions.return_historical_data.lambda_function.dynamodb.Table')
|
||||||
|
def test_lambda_handler_without_object_type(self, mock_table):
|
||||||
|
# Mock scan response for full table scan
|
||||||
|
mock_table.return_value.scan.return_value = {
|
||||||
|
'Items': [
|
||||||
|
{'objectID': '1', 'objectType': 'Bus'},
|
||||||
|
{'objectID': '2', 'objectType': 'Train'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mock event without objectType query parameter
|
||||||
|
event = {
|
||||||
|
'queryStringParameters': None
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lambda_handler(event, {})
|
||||||
|
self.assertEqual(result['statusCode'], 200)
|
||||||
|
|
||||||
|
body = json.loads(result['body'])
|
||||||
|
self.assertEqual(len(body), 2)
|
||||||
|
self.assertEqual(body[0]['objectType'], 'Bus')
|
||||||
|
self.assertEqual(body[1]['objectType'], 'Train')
|
||||||
|
|
||||||
|
@patch('functions.return_historical_data.lambda_function.dynamodb.Table')
|
||||||
|
def test_lambda_handler_with_no_items(self, mock_table):
|
||||||
|
# Mock empty scan response
|
||||||
|
mock_table.return_value.scan.return_value = {
|
||||||
|
'Items': []
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mock event without objectType query parameter
|
||||||
|
event = {
|
||||||
|
'queryStringParameters': None
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lambda_handler(event, {})
|
||||||
|
self.assertEqual(result['statusCode'], 200)
|
||||||
|
|
||||||
|
body = json.loads(result['body'])
|
||||||
|
self.assertEqual(len(body), 0)
|
||||||
|
|
||||||
|
@patch('functions.return_historical_data.lambda_function.dynamodb.Table')
|
||||||
|
def test_lambda_handler_error(self, mock_table):
|
||||||
|
# Mock table scan to raise an exception
|
||||||
|
mock_table.return_value.scan.side_effect = Exception('DynamoDB error')
|
||||||
|
|
||||||
|
event = {
|
||||||
|
'queryStringParameters': None
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lambda_handler(event, {})
|
||||||
|
self.assertEqual(result['statusCode'], 500)
|
||||||
|
|
||||||
|
body = json.loads(result['body'])
|
||||||
|
self.assertIn('error', body)
|
||||||
|
self.assertEqual(body['error'], 'DynamoDB error')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Reference in New Issue
Block a user