Skip to content

An example project for UWB Hacks the Cloud, ACM's on-campus 2020 hackathon.

License

Notifications You must be signed in to change notification settings

UWB-ACM/feelgood

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FeelGood, an Example Project for AWS

The organizers of UWB Hacks the Cloud wanted to build an application that facilitates self-service for good vibes and positivity.

From that ideal, the project grew to provide additional registration options to facilitate laughs and silliness.

Read about the project and how we built it!

Goals

  • Text Messages: uplifting content, delivered straight to your phone.
  • Mix and Match Subscriptions: users should be able to register for message streams that fit their personality.
  • Fully Cloud Hosted: The end-to-end deployment should be fully hosted in the cloud, without running a VM or using local computing resources.

TL;DR: automatic, supersonic, hypnotic, funky fresh

User Experience

  1. A user goes to the application's website to sign up for messages.

    <iframe src="https://giphy.com/embed/fQZX2aoRC1Tqw" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

    via GIPHY

  2. The user subscribes to a topic.

    <iframe src="https://giphy.com/embed/mgqefqwSbToPe" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

    via GIPHY

  3. The user gets a welcome message after subscribing to a topic of their choice. They can continue to subscribe to other topics they are interested in.

    <iframe src="https://giphy.com/embed/10a9ikXNvR9MXe" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

    via GIPHY

  4. At set times during the day, the user gets a text message reminding them to:

    • Feel good
    • Drink water
    • Laugh
    • Commune with their crow friends

    Of course, the messages they actually get are dependent on which topics they subscribed to.

    <iframe src="https://giphy.com/embed/QBd2kLB5qDmysEXre9" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

    via GIPHY

    <iframe src="https://giphy.com/embed/wqd5THxOO39KM" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

    via GIPHY

Architecture

To realize these desired behaviors & user experiences, we used AWS services and deployed the application to the cloud. The application's design is described below.

User Subscription

  • An S3 bucket is used to host the subscription site. We configured domain redirection for a custom domain and SSL certificates for HTTP/S traffic.
  • The user interacts with the site as they would any other.
  • Upon clicking the Submit button, a JavaScript function makes an HTTP POST request to the application's API, sending the user's data from the website's subscription form. The API endpoint is connected to a Lambda function using
    API Gateway.
  • The Lambda function takes the JSON payload delivered by the POST request, which contains the user's phone number and selected topic. The function then:
    • Validates the phone number for correct formatting
    • Looks up the Amazon Resource Name (ARN) for the selected topic
    • Invokes the Simple Notification Service (SNS) SDK
    • Makes a subscribe() call to SNS, passing the user's data and topic ARN
  • SNS saves the user's phone number as a subscriber under the specified topic.
  • If the Lambda function processes successfully, it will return a success code to the API Gateway method, which in turn returns the HTTP 200 status to the user's browser. The Lambda function also publishes a text message to the user's provided number, which confirms subscription and welcomes the user.

View the website code here.

View the subscription Lambda function here.

Here's a diagram of the system's flow of logic:

FeelGood subscription mechanism

User Notification

  • To send messages out at regular intervals, we used CloudWatch Events to create rules which get invoked on a time schedule.
  • When creating the Event rule, the message publication function was selected as the target.
  • Upon being invoked, the Lambda function:
    • Chooses 4 messages to publish (one for each possible topic)
    • Looks up the ARN for each topic
    • Invokes the Simple Notification Service SDK
    • Makes 4 publish() calls to SNS, where each call uses a different message and topic ARN
  • SNS receives the SDK invocation to publish a message and distributes the message for each topic to all subscribers for that topic. Each topic is handled asynchronously.

View the publication Lambda function here.

Here's a diagram of the subsystem's flow of logic:

FeelGood publication mechanism

Implementation Notes

The specific instructions, how-tos, and details we encountered are organized here by AWS product.

S3 & Website Construction

We used to the following resources as a guide for configuring S3 buckets to host the subscription website:

API Gateway

There are multiple types of APIs that can be built using API Gateway, such as REST, HTTP, or WebSocket. This document will focus specifically on REST APIs. AWS' API Gateway documentation has a helpful tutorial that covers creating a REST API with Lambda Integrations. This was the approach taken for FeelGood.

Create a Resource

A resource is something that can be accessed through the REST API using CRUD operations. GCP has a good explanation of REST APIs and resources if you are unfamiliar with the concept or would like to refresh your memory. In API Gateway, the resource also represents your endpoint. For example, on a hypothetical website for a car dealership, the URL might be www.cars.com/buycar. The endpoint in this scenario is /buycar. Each endpoint has its own set of methods.

Create a Method

A method is the actual operation to be performed on the resource, such as GET, PUT, POST, DELETE, etc. The method's settings are where integrations with Lambda functions including input pass-through are set. See the API Gateway page on REST API methods for a detailed tutorial.

Setup CORS

CORS stands for Cross-Origin Resource Sharing. This is required to tell your browser that it is safe to access certain API endpoints. Whether or not CORS is required depends on what the API does. See Mozilla's MDN Docs on CORS for more information on what it is and why it's needed. See API Gateway Docs on Enabling CORS for REST APIs for a tutorial on enabling CORS.

Deploy the API

Once everything is setup correctly, all that's left is to deploy the API. You can create stages like "staging" and "production" and deploy different versions on the API to each stage. It is recommended to deploy a staging version of the API for testing before deployed the production version of the API for use in an application. Note that the name of the stage will be part of the endpoint URL. See API Gateway Docs on Deploying a REST API for a detailed walkthrough.

Lambda

AWS Lambda handles all of FeelGood's computation. Within AWS Lambda, there are several important things that must be configured in order for FeelGood's code to operate correctly.

Give Lambda access to SNS

By default, creating a Lambda function from scratch, adding SNS code, and pressing "Test" won't work. Why? Simple, because the Lambda function does not have access to SNS. Cloud systems operate on a least-required permissions model, meaning that in order for your Lambda function to access SNS, you must explicitly grant Lambda access to SNS (and any other AWS services you might want Lambda to access). Refer to AWS documentation on IAM permissions for SNS, and check out [the TL;DR explanation of IAM on the documentation site for this hackathon]({% link _docs/aws_secrets.md %}).

Set up environment variables for Lambda functions

  • In order to keep the code looking clean, and to keep our Topic ARNs safe (more on these in the SNS section), we use environment variables to store the names of the SNS topics and their ARNs. These are exactly like environment variables on your computer. They're variables that you can access in your code like any other, but since they're not declared or otherwise modified in the source code, they're invisible and can't be accidentally leaked (say when you upload your code to a public git repository).

  • After you create a Lambda function in the AWS portal, you will be greeted with the function's page. Here you can edit the code directly and modify the function's settings. Right below the code window, you will see a menu item for Environment Variables. Click Edit to modify them. The key is the variable name, and the value is the variable's value. Click Save to save these variables in the function. Now you can access the environment variables in the Lambda function's code by calling it using the key. See AWS Documentation on Environment Variables for more info.

Set up aliases for Lambda functions

  • Lambda has a feature called Aliases. Aliases are used in combination with function versions to manage what version of the Lambda function will be called by other AWS services. In FeelGood, aliases are used to connect API Gateway endpoints to the publish and subscribe Lambda functions.

  • In order to create an alias, you must first have a published function version to connect it to. Under the Actions menu in the function, click on Publish new version, enter a description, and publish it to create a new version. This new version will retain the functionality that it has at the time that it is published. Refer to the AWS Docs on Lambda Versions for more detail on what you can do with versioning.

  • Aliases allow you to refer to different versions of a function with the same name. So for example in API Gateway you can link a GET request with a Lambda function using the alias "API_GET_Version". Then, no matter what function version you connect to that alias, be it 1, 10, or 1000, you will not need to change the API Gateway configuration when you update the Lambda code. You do however, need to modify which function version the alias will point to each time you publish a new version. You can alias to the $LATEST version in order to have Lambda automatically use whatever code exists when you Save the function, but this is not recommended. You should only alias to function versions that you have tested and verified to work. Further documentation on function aliases is available here.

Configure CloudWatch Trigger Invocation

  • In order for FeelGood messages to be sent out at a specific time, we use AWS CloudWatch Events/EventBridge as a trigger to run the Lambda publish function at a specific time.

  • First, select an alias in the menu for the Lambda function that you wish to trigger. In the Designer pane, there is a button called Add trigger. Clicking on that will bring up a drop-down with a number of potential triggering services.

  • After clicking Add trigger, AWS will present a menu to configure a rule. This rule will trigger the Lambda function. Proceed to name the trigger.

  • Schedule expression is where you define the time interval that the function should be triggered at. FeelGood uses cron syntax identical to the syntax used to schedule recurring jobs in native Unix systems; a good reference on cron syntax we found useful is available here. Cron syntax uses UTC time. In FeelGood, the trigger uses the cron syntax cron(0 18 * * ? *), which means every day at 10 AM PST/11 AM PDT. We recommend looking up a converter from UTC to your timezone. Saving and enabling this trigger will run the function at the specified time. AWS has a good explainer on creating CloudWatch Events Rules here.

Simple Notification Service

Gotchas & Lessons Learned

  1. Amazon SNS may have reliability issues that are outside of your control; message delivery to subscribers is not guaranteed. If high availability or reliability is important to your application, consider incorporating an API-accessible service which specializes in SMS, such as Twilio.
  2. Always, always, always set up robust logging. AWS streamlines setup of logging and performance monitoring for many services via CloudWatch. This was particularly useful when troubleshooting unreliable message delivery to subscribers, monitoring S3 usage, and monitoring the frequency of API requests.
<iframe src="https://giphy.com/embed/3KVChGOKcyyRO" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

About

An example project for UWB Hacks the Cloud, ACM's on-campus 2020 hackathon.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •