10. Python
Tags: python, aws
Published: 2021-02-07 16:10:32

The [website](http://blog.komlalebu.com/) uses a `lambda` function to push data into the backend Dynamodb [table](https://dev.to/jicoing/8-database-2cl4) with handler written in [python 3.8](https://www.python.org/) .
AWS Lambda is a serverless compute service that lets you run code without provisioning or managing servers, creating workload-aware cluster scaling logic, maintaining event integrations, or managing runtimes.

![Alt Text](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FQ5jKvyd3UlE4z92t2S%2Fgiphy.gif&f=1&nofb=1)

> # [AWS Lambda](https://aws.amazon.com/lambda/) 

![Alt Text](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi1.wp.com%2Foddblogger.com%2Fwp-content%2Fuploads%2F2019%2F08%2FAWS-Lambda%404x.png%3Fresize%3D234%252C234%26ssl%3D1&f=1&nofb=1)

>To create the function, I went in to the lambda console and clicked create.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ufd6rm69i10wu9mh1tfc.PNG)

>Then I named the function and specified the lambda handler runtime: `Python 3.8` for my use case.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6yx6949se134h13b27wz.PNG)

Once that was done, I assigned a role I had setup previously, for access to dynamodb and created the function.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sslbi6r07nmtooo093cc.PNG)

> # API Gateway trigger

Then I added the api gateway trigger for triggering the lambda function on every API call ([aws-sam-komlalebu](https://dev.to/jicoing/9-api-1ad9)).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vh5qd3in6lc27xauvueq.PNG)

> # Policy

The resource based policy looks like this.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/awxa7el0jzoxdxdovr0j.PNG)

> # app.py

Here the python code used in the lambda function.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wu6wm0x58n2na7wikdec.PNG)

> The handler imports the modules `json` and `boto3`.
* import the json utility package since we will be working with a JSON object.
* import the AWS SDK (for Python the package name is boto3).
* import two packages to help us with dates and date formatting.

                                import json
                                import boto3
                                from time import gmtime, strftime
>
* create a DynamoDB object using the AWS SDK.

                                dynamodb = boto3.resource('dynamodb',region_name='ap-south-1')
>
* use the DynamoDB object to select our table.

                     table = dynamodb.Table('komlalebuTable')
>
* store the current time in a human readable format in a variable.

                   now = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
>
* define the handler function that the Lambda service will use as an entry point.

                                def lambda_handler(event, 
                                context):
>
* extract values from the event object we got from the Lambda service and store in a variable.

                             try:
                             event = json.loads(event['body'])
                             visitor = event['visitorCount'] +' '+ 
                             event['visitorResponse']

`visitorCount` and `visitorResponse` are fetched from the `callAPI` Javascript function ([read more](https://dev.to/jicoing/7-javascript-13h8)) and concatenated into `visitor` variable.

>
* write `visitor` and time to the DynamoDB table using the object we instantiated and save response in a variable using [response](https://www.geeksforgeeks.org/response-methods-python-requests/) method.

                            response = table.put_item(
                            Item={
                                'id': visitor,
                                'LatestGreetingTime':now
                                 })
                           except:
                           visitor = 'request error'

>
* return a properly formatted JSON object. This code is used for testing later ([read more]()).

                          return {
                          'statusCode': 200,
                          }

> # [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)

This was the manual way of doing things, the final application has the lambda function defined in `SAM` template as below in `template.yml` ([read more](https://dev.to/jicoing/12-infrastructure-as-code-1df4)). With the function name as `KomlalebuFunction`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/23rtm52ayh1mm27snzp4.PNG)

>
* CodeUri - Has the handler code location in repository.
                      CodeUri: komla_function/

>
* Handler - Defines the handler name.

      Handler: app.lambda_handler
>
* Runtime - Defines the language used during runtime.

      Runtime: python3.8
>
* Policies - Defines the access policy for the function.

      Policies:
      # Give DynamoDB Full Access to your Lambda Function
      - AmazonDynamoDBFullAccess
>
* Function created in Lambda on SAM `deploy`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nzql6l6d9zo4bvsy3sa8.PNG)

>
* Configuring test event from lambda console.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gsal7u0w2wdtv6xi2xq9.PNG)

* Testing the code - `Passed`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qqksjchvstkww37lsr63.PNG)

* Dynamodb also got updated on table [komlalebuTable](https://dev.to/jicoing/8-database-2cl4). 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f6ghkyhg9hxsed38d5mn.PNG)

And the lambda function was setup and deployed.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0vobgcej8t0ytnl5d9l4.gif)

> # Miscellaneous
# Update

I also setup a visitor stats HTML table, combining stats for visitor counter, likes, dislikes.

* likes - I had to setup a separate API and Lambda function (`komlalikesFunction`) that runs a table scan on the backend table [komlalebuTable](https://dev.to/jicoing/8-database-2cl4) that fetches the records based on DynamoDB `FilterExpressions`. On clicking `like` the user stores data in dynamodb table with the string `YES` appended to the visit count. However this was done as a standalone and therefore not in SAM template.

>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c4kpacvdjp83icuylzc3.PNG)

There is a separate lambda funtion that scans the table with the primary key `id` containing the string `yes` and gives back the result count. This function is called by a separate API everytime the page gets loaded.

`komlalikesFunction`
>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/t6736b134ge4irdsnhmt.PNG)


* Dislikes - I had to setup a separate API and Lambda function (`komladislikesFunction`) that runs a table scan on the backend table [komlalebuTable](https://dev.to/jicoing/8-database-2cl4) that fetches the records based on DynamoDB `FilterExpressions`. On clicking `dislike` the user stores data in dynamodb table with the string `NO` appended to the visit count. However this was done as a standalone and therefore not in SAM template.

>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sdmqfflxwsv0yax9dld9.PNG)

There is a separate lambda funtion that scans the table with the primary key `id` containing the string `NO` and gives back the result count. This function is called by a separate API everytime the page gets loaded.

`komladislikesFunction`
>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xop10c2w5854a03ryhah.PNG)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pcxrky1puawhzz9trptw.PNG)