In Progress
Unit 1, Lesson 1
In Progress

Serverless Ruby with AWS Lambda

For some software applications, even a microservice architecture feels too heavyweight. Sometimes all you really need to implement a bit of new functionality is a single function that takes some inputs and produces some outputs. In those cases, wouldn’t it be nice to simply upload the function into the cloud, and let someone else worry about triggering and scaling it?

That’s the value proposition of so-called “serverless” computing. In today’s episode, guest chef Brittany Martin is going to show you everything you need to know to get started with serverless architecture in Ruby, using Amazon’s Lambda service. Enjoy!

Video transcript & code

Serverless Ruby with AWS Lambda

Script

Slide title Serverless. It's a buzzword that has been circulating. Let's be clear: it still involves servers, so that word serverless feels insincere. Serverless is a new way to pay for and work with servers that, in many cases, is cheaper and easier than deploying to a hosting platform as a service.

Slide title AWS Lambda is an event-driven, serverless computing platform provided by Amazon as a part of the Amazon Web Services. With Lambda, you can run code for virtually any type of application or backend service. Just upload your code and Lambda takes care of everything required to run and scale your code with high availability. Developers can deploy a singular function and only pay for the resources used during the execution.

Slide title Up until now, Lambda was restricted to a few programming languages. This has all changed now because AWS announced support for our favorite language, Ruby. It is now possible to write Lambda functions as idiomatic Ruby code. Let's dive into a common scenario where serverless enables us to get our code into production quickly.

Slide title Let's say we run a server whose only job is to run a cron task against our Rails application. In our case, we are using Sidekiq to execute a job nightly to sync data into our application. Currently, we are using a cron task to insert a job into the designated Sidekiq Redis pool.

Slide title Instead of resourcing a server to insert the task into Redis, we will use AWS Lambda and Cloudwatch. Cloudwatch is a monitoring and scheduling service. We will need an AWS account, an external Redis endpoint and a ruby version above 2.2 installed locally.

Starting locally, create a directory for our new Ruby application:


mkdir task_helper
cd task_helper

Inside of this directory, create a file Gemfile and add aws-record and redis to it:


source 'https://rubygems.org'
gem 'aws-record', '~> 2'
gem 'redis'

Create a file that will execute our function code, called lambda_function.rb with this code.


require 'securerandom'
require 'json'
require 'redis'

def lambda_handler(event:, context:)
  redis = Redis.new(host: "cd-v2-redis.gidmzp.0001.use1.cache.amazonaws.com", port: 6379)
  msg = { "class" => 'SynchronizeSingleProdWorker',
        "queue" => 'default',
        "args" => [{"id" => "58248"}],
        'jid' => SecureRandom.hex(12),
        'created_at' => Time.now.to_f,
        'enqueued_at' => Time.now.to_f }

  redis.lpush("queue:default", JSON.dump(msg))

end

At the top of the file, we require in the dependencies we need. JSON and SecureRandom are available by default on Lambda, we just need to require them.

Moving on to the function, we name our function lambda_function. It takes in two arguments: event and context. An event source is the AWS service or custom application that publishes events.

When Lambda runs our function, it also passes a context object to the handler. This object provides methods and properties that provide information about the invocation, function, and execution environment. <!- begin postproduction insert -->


require 'securerandom'
require 'json'
require 'redis'

def lambda_handler(event:, context:)
  redis = Redis.new(host: "cd-v2-redis.gidmzp.0001.use1.cache.amazonaws.com", port: 6379)
  msg = { "class" => 'SynchronizeSingleProdWorker',
        "queue" => 'default',
        "args" => [{"id" => "58248"}],
        'jid' => SecureRandom.hex(12),
        'created_at' => Time.now.to_f,
        'enqueued_at' => Time.now.to_f }

  redis.lpush("queue:default", JSON.dump(msg))

end

<!- end postproduction insert -->

Next, we identify a Redis connection, build a message object formatted for Sidekiq and then we push the message into the Redis queue.

Run these bundle commands to create the Gemfile.lock file to download the gems to the local directory instead of to the local systems Ruby directory. We can ensure that all of our dependencies are included in the function deployment package since Lambda will not download out gems on execution from Rubygems.org.


bundle install
bundle install --deployment

Lastly, zip the files locally for upload.


cd ..
zip -r task_helper *

Slide title Now, let's upload our function.

Sign into AWS and navigate to Lambda. Choose Create Function, choose Author from Scratch, name our function and choose the latest Ruby as our runtime.

Slide title Under the Function section, choose Upload a .zip file and select the zip file we created. Click Save and we will see our code directory render in the Lambda editor. Move over to Actions and select Publish new version.

Slide title Now that we have our working function setup, we will schedule it to run. Navigate to Cloudwatch.

Slide title Step 1: choose Events, then Rules. Click create rule. We have the option of Event Pattern or Schedule. Under Schedule, we will choose a fixed rate of 5 minutes. Slide title Now, under Target, we will select Lambda and then will select our function.

Slide title Step 2: Name our function and make sure enabled is checked. Click Create rule. Our function is scheduled!

Slide title Click back into Lambda, and choose Monitoring. Here we can see Invocations (our function triggering), Errors and Duration. Clicking over to View logs in Cloudwatch shows our function's logs. Victory!

Slide title We are likely asking ourselves how to edit our function. Click over to Configuration and edit our code inline or upload a new zip file. Now, we can publish a new version of our function.

We are officially serverless with Ruby!

Responses