Part 4: Add S3 event source¶
So far, we have been manually invoking the Lambda function ourselves in order to detect objects in the image and add the information to our database. However, we can automate this workflow using Lambda event sources so that the Lambda function is invoked every time an object is uploaded to the S3 bucket.
For this section, we will be doing the following:
Add Lambda event source for S3 object creation event¶
Change the Lambda function to be invoked whenever an object is uploaded to a S3 bucket via the on_s3_event decorator.
Instructions¶
In the
app.pyfile, change thedetect_labels_on_imagesignature to be namedhandle_object_createdthat accepts a singleeventparameter:def handle_object_created(event):
Update the decorator on
handle_object_createdto use theapp.on_s3_eventdecorator instead and have the Lambda function be triggered whenever an object is created in the bucket specified by the environment variableMEDIA_BUCKET_NAME:@app.on_s3_event(bucket=os.environ['MEDIA_BUCKET_NAME'], events=['s3:ObjectCreated:*']) def handle_object_created(event):
Add the tuple
_SUPPORTED_IMAGE_EXTENSTIONSrepresenting a list of supported image extensions:_SUPPORTED_IMAGE_EXTENSIONS = ( '.jpg', '.png', )
Update the
handle_object_createdfunction to use the neweventargument of type S3Event and only do object detection and database additions on specific image file extensions:@app.on_s3_event(bucket=os.environ['MEDIA_BUCKET_NAME'], events=['s3:ObjectCreated:*']) def handle_object_created(event): if _is_image(event.key): _handle_created_image(bucket=event.bucket, key=event.key) def _is_image(key): return key.endswith(_SUPPORTED_IMAGE_EXTENSIONS) def _handle_created_image(bucket, key): labels = get_rekognition_client().get_image_labels(bucket=bucket, key=key) get_media_db().add_media_file(key, media_type=db.IMAGE_TYPE, labels=labels)
Validation¶
Ensure the contents of the
app.pyfile is:
1import os
2
3import boto3
4from chalice import Chalice
5from chalicelib import db
6from chalicelib import rekognition
7
8app = Chalice(app_name='media-query')
9
10_MEDIA_DB = None
11_REKOGNITION_CLIENT = None
12_SUPPORTED_IMAGE_EXTENSIONS = (
13 '.jpg',
14 '.png',
15)
16
17
18def get_media_db():
19 global _MEDIA_DB
20 if _MEDIA_DB is None:
21 _MEDIA_DB = db.DynamoMediaDB(
22 boto3.resource('dynamodb').Table(
23 os.environ['MEDIA_TABLE_NAME']))
24 return _MEDIA_DB
25
26
27def get_rekognition_client():
28 global _REKOGNITION_CLIENT
29 if _REKOGNITION_CLIENT is None:
30 _REKOGNITION_CLIENT = rekognition.RekognitonClient(
31 boto3.client('rekognition'))
32 return _REKOGNITION_CLIENT
33
34
35@app.on_s3_event(bucket=os.environ['MEDIA_BUCKET_NAME'],
36 events=['s3:ObjectCreated:*'])
37def handle_object_created(event):
38 if _is_image(event.key):
39 _handle_created_image(bucket=event.bucket, key=event.key)
40
41
42def _is_image(key):
43 return key.endswith(_SUPPORTED_IMAGE_EXTENSIONS)
44
45
46def _handle_created_image(bucket, key):
47 labels = get_rekognition_client().get_image_labels(bucket=bucket, key=key)
48 get_media_db().add_media_file(key, media_type=db.IMAGE_TYPE, labels=labels)
Redeploy the Chalice application¶
Deploy the updated Chalice application.
Instructions¶
Run
chalice deploy:$ chalice deploy Creating deployment package. Creating IAM role: media-query-dev-handle_object_created Creating lambda function: media-query-dev-handle_object_created Configuring S3 events in bucket media-query-mediabucket-fb8oddjbslv1 to function media-query-dev-handle_object_created Deleting function: arn:aws:lambda:us-west-2:123456789123:function:media-query-dev-detect_labels_on_image Deleting IAM role: media-query-dev-detect_labels_on_image Resources deployed: - Lambda ARN: arn:aws:lambda:us-west-2:123456789123:function:media-query-dev-handle_object_created
Validation¶
Upload the
othersample.jpgimage to the S3 bucket:$ aws s3 cp ../chalice-workshop/code/media-query/final/assets/othersample.jpg s3://$MEDIA_BUCKET_NAME
Use the
get-itemCLI command to ensure theothersample.jpgdata was automatically populated in the DynamoDB table:$ aws dynamodb get-item --table-name $MEDIA_TABLE_NAME \ --key '{"name": {"S": "othersample.jpg"}}' { "Item": { "name": { "S": "othersample.jpg" }, "labels": { "L": [ { "S": "Human" }, { "S": "People" }, { "S": "Person" }, { "S": "Phone Booth" }, { "S": "Bus" }, { "S": "Transportation" }, { "S": "Vehicle" }, { "S": "Man" }, { "S": "Face" }, { "S": "Leisure Activities" }, { "S": "Tourist" }, { "S": "Portrait" }, { "S": "Crowd" } ] }, "type": { "S": "image" } } }If the item does not appear, try running the
get-itemcommand after waiting for ten seconds. Sometimes, it takes a little bit of time for the Lambda function to get triggered.