Hi, I'm Johnathan Sewell

Software Engineer & JavaScript Developer

Creating a "Serverless" Happiness Tracking App

I had an idea (not really mine at all) that it'd be interesting to track how I rate my happiness at work daily. So I've started building a web app for this.

I'm going to try out the Serverless Framework and AWS.

Serverless architecture replaces long-running virtual machines with ephemeral compute power that comes into existence on request and disappears immediately after use.

Installing Serverless

Serverless is a Node CLI tool, just grab it off npm:

  npm install -g serverless

The introduction docs are great, so I won't try to repeat them here. Basically the next steps are:

  1. Give Serverless permission to manage your AWS resources (via AWS Identity and Access Management)
  2. Generate a template project (serverless create --template aws-nodejs --name your-service-name)
  3. Create Node functions - these will be run as AWS Lambda functions
  4. Use serverless.yml to tell Serverless how to configure your AWS services
  5. Run "serverless deploy" and let Serverless set up and deploy to your AWS services

Mood App

My mood app is a single page (app) posting new data and getting historical data via AWS API Gateway. The endpoints are:

These endpoints trigger lambda functions, which recieve the request payload, you can see Serverless created them for me in AWS:

The Lambda functions are using DynamoDB to manage the data for the app, the complete code is below. The "event" argument contains information about the initiator of the Lambda function, in this case it's an API Gateway event (having path and body properties).

'use strict';
const aws = require('aws-sdk');

const dynamo = new aws.DynamoDB.DocumentClient();
const tableName = 'Moods';

//POST users/:userid/moods
exports.createMood = (event, context) => {
    const payload = {
        TableName: tableName,
        Item: {
            userId: event.path.userid,
            date: event.body.date,
            mood: event.body.mood
        }
    };
    dynamo.put(payload, (err, data) => {
        if (err) {
            context.fail(err);
        } else {
            context.succeed(data);
        }
    });
};

//GET users/:userid/moods
exports.getAllMoods = (event, context) => {
    const payload = {
        TableName: tableName,
        KeyConditionExpression: "userId = :userId",
        ExpressionAttributeValues: {
            ":userId": event.path.userid
        }
    };
    dynamo.query(payload, (err, data) => {
        if (err) {
            context.fail(err);
        } else {
            context.succeed(data.Items);
        }
    });
};

And here's my Serverless configuration:

# Welcome to Serverless!
# This file is the main config file for your service.
service: mood-api
provider:
  name: aws
  runtime: nodejs4.3
functions:
  createMood:
    handler: handler.createMood
    events:
      - http:
          path: users/{userid}/moods
          method: POST
  getMoods:
    handler: handler.getAllMoods
    events:
      - http:
          path: users/{userid}/moods
          method: GET