DynamoDB model

DynamoDB is a no-sql key-value and document database which is fully managed by AWS. Its highly performant and scalable and as per the AWS website -

DynamoDB can handle more than 10 trillion requests per day and support peaks of more than 20 million requests per second.

Lets store books data in DynamoDB as key-value pairs. It will have these attributes:

Book Model

  • title
  • author
  • ISBN

aws-record gem adds Ruby support for DynamoDB. Create a Gemfile, and bundle install, after adding the aws-record gem. Make sure that you are on Ruby 2.5 before doing bundle install, as AWS lambda currently supports only Ruby 2.5 runtime.

The book attributes are defined by constructs like string_attr, integer_attr. Create a book.rb file with these fields, in this case all strings. We are assuming that isbn will be the unique key, and we make it the hash key in the table.

# File: models/book.rb

require 'aws-record'

class Book
  include Aws::Record

  set_table_name ENV['DYNAMODB_TABLE']

  string_attr :isbn, hash_key: true
  string_attr :title
  string_attr :author
end

Please Note: If you dont use Ruby version 2.5.x then AWS lambda will fail to recognize the gems and you will get an "Internal server error".

Defining the DynamoDB table for books

The config in serverless.yml file, needs to change for setting DYNAMODB_TABLE which is passed as an environment variable. Also the permissions to access the table. These needs to be added in the provider section.

# Changes to serverless.yml

provider:
  name: aws
  runtime: ruby2.5
  region: us-east-1
  environment:
    DYNAMODB_TABLE: books-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"

Telling AWS about the DynamoDB table

The table definition needs to be added in the resources section in the same serverless.yml file, indicating the hash key isbn.

# Changes to serverless.yml

resources:
  Resources:
    Users:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        TableName: ${self:provider.environment.DYNAMODB_TABLE}
        AttributeDefinitions:
          -
            AttributeName: isbn
            AttributeType: S
        KeySchema:
          -
            AttributeName: isbn
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

You can view the full serverless file changes here.

To check if everything works fine, change the test handler to load some books and retrieve a book by ISBN.

require 'json'
require_relative '../models/book'

def hello(event:, context:)
  Book.new(
    title: 'Educated',
    author: 'Tara Westover',
    isbn: '0525589983'
  ).save!

  Book.new(
    title: 'Sapiens',
    author: 'Yuval Noah Harari',
    isbn: '0062316110'
  ).save!

  book = Book.find(isbn: '0525589983')

  {
    statusCode: 200,
    body: JSON.generate(book.to_h)
  }
end

Run bundle install --deployment so that bundler saves the gems in the vendor folder, which needs to be uploaded to AWS Lambda for the function to work. Now, deploy the function with sls deploy and the function should be live. Send a request to the endpoint and you should get a successful response.

Get notified on engineering articles like this

Follow us on twitter @neumeralhq