Reputation: 139
I am just getting into aws lambda functions and have written a function that fetches some data from a dynamodb table. This is the function:
import boto3
from boto3.dynamodb.conditions import Key, Attr
import botocore.exceptions
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
dynamodb=boto3.resource('dynamodb')
appointmentsTable = dynamodb.Table('Appointments')
class NotFoundError(Exception):
pass
def lambda_handler(event, context):
try:
logger.info(f'event: {event}')
bookedAppointments = fetchAppointments(event)
logger.info(f'Response: {bookedAppointments}')
return sendResponse(True , 200 , 'Appointments found' , bookedAppointments)
except NotFoundError:
return sendResponse(True , 400, 'No booked appointments Found' , [])
except Exception as error:
return sendResponse(False , 500 , 'Error in fetch booked appointments' , str(error))
def sendResponse(success , statusCode , message , responseData):
return {
'success' : success,
'statusCode' : statusCode,
'message': message,
'responseData' : responseData
}
def fetchAppointments(event):
consId = event.get('consId')
try:
bookedAppointments = appointmentsTable.query(
IndexName = 'consId-index',
KeyConditionExpression = Key('consId').eq(consId),
FilterExpression = 'booked=:b',
ExpressionAttributeValues = {
':b' : True
}
)
except botocore.exceptions.ClientError as error:
logger.exception(f'Error in fetchAppointments function: {error}')
raise error
if bookedAppointments.get('Items') == []:
raise NotFoundError
sortedResult = sortResult(bookedAppointments.get('Items'))
return sortedResult
def sortResult(listTobeSorted):
return sorted(listTobeSorted , key=lambda k: (k['appointmentDate'] , k['appointmentSlot']))
I know wrapping all of your code logic in a try-catch block is bad practise , so is there a better way to handle any exceptions that may occur in the fetchAppointments function?
Upvotes: 0
Views: 4462
Reputation: 9625
Code quality is certainly a good thing we don't have to start from scratch IMO, In my experience what I learned is
it should work first and then it should look beautiful
But in Cloud, there is more to it, it should be optimized in terms of cost as well.
So there you already started on the right path already by handling the exception
If you don't handle the exception and let the function fail, by default lambda would try to execute it 3 times
So you would be charged for those executions. You can customize this behaviour
As far as handling the exception goes @Jens explained it real good.
Upvotes: 1
Reputation: 21500
There are different ways to solve issues like this, but the underlying truth is: it always depends on what you want to do. So the following advice might be ok for this specific case, but might not be ok for other uses cases. So take the following with a grain of salt.
That said, the first thing to analyse is the different outputs of your fetchAppointments()
function:
Coming to your question: should you use exception handling for this? Yes, but I would not use it as much as you did.
I would only use it for the "proper" exception in this case and the rest should be covered by "normal" application logic.
Consider the following simplified version of your handler:
def lambda_handler(event, context):
try:
appointments = fetchAppointments(event)
except Exception as error:
return sendResponse(False, 500, 'Error in fetch booked appointments', str(error))
if not appointments:
return sendResponse(True, 400, 'No booked appointments Found', [])
return sendResponse(True, 200, 'Appointments found', appointments)
As you can see, only the "real" application exception is handled with exception handling and the rest just uses "normal" logic to figure out, if there are appointments or not.
Upvotes: 3