How to Create a Ruby Function on AWS Lambda
Amazon has been the biggest tech giant for two decades. The main reason for the success and revenue of Amazon is considered AWS. AWS is empowering almost 40 percent of the cloud market.
Suppose you are running a website with millions of users, and one day you are just surfing through your website, and suddenly it stops responding or starts producing crashes. You can lose millions of dollars just because your site has collapsed for 1 hour.
AWS lambda stops you and your site from suffering such kinds of collapses. AWS Lambda lets you concentrate on your application’s codebase without the stress of server maintenance, leading to mishaps with your website.
AWS Lambda executes your code whenever you trigger an event or whenever it’s required. It is a compute service that lets you run your code without the headache of managing servers. AWS Lambda will only operate if your code is running and triggering requests. You can scale up from a few users per week to one million users per second. You can code almost any kind of application or backend service on AWS Lambda as it will take care of all your server maintenance, security, scalability, caching, OS maintenance, capacity monitoring, and logging. Using AWS CodePipeline and AWS CodeBuild, you can also deploy serverless applications composed of functions and triggered by events.
In this article, we will be deep-diving into the integration of ruby functions using AWS Lambda. In addition to the main topic, we will also be seeing why we should use AWS lambda, the language supported in AWS Lambda, and much more. After the end of this article, you will deploy a ruby function on AWS Lambda successfully.
- The 411 on AWS Lambda
- How to Create Ruby Functions in AWS Lambda
- Lambda Function Example
- Try it For Yourself
The 411 on AWS Lambda
Amazon launched AWS Lambda in 2014 AWS re:Invent conference, by Dr. Tim Wagner. Using AWS Lambda, you can run code on multiple events as either an HTTP request via Amazon API gateway or some modification to database values and table updates. The code we run on AWS Lambda is like a formula in a spreadsheet called Lambda functions. Once your function is ready, you can trigger it anytime. Lambda functions are stateless functions that have to be dependent on infrastructure.
Some of the key features of AWS Lambda that you should know are:
- Extend to other AWS services: We can easily extend to other AWS services such as Amazon S3 bucket and Amazon Dynamo DB tables using custom logic. It makes the computation of data very easy when it travels through the cloud. It is very easy and is done in a few simple steps. First, write your code and upload it to AWS lambda (or directly write on Lambda console). Then choose the memory, timeout, AWS Identity, and access management role(IAM). After that choose the specific resources to trigger the function. Whenever the resources change, your function will be executed and ensure all the resources are updated so that all upcoming requests can be handled easily. Your lambda function may also be executed in response to changes in Amazon Simple Storage Service(Amazon S3) data, DynamoDB, or in response to HTTP requests using Amazon API Gateway.
- Fully custom backend services: It is nearly impossible that two applications have the same logic for backend services. So you need to use custom logic for your backend services and functions can be triggered using Lambda API or using custom endpoints(like xyz.com) built using Amazon Gateway API.
- Use your own code: No matter what, if you have your code ready in any of the languages supported by AWS Lambda, you can bring down your code for your application purpose. Any third-party libraries or native libraries can also be used.
- Automated Administration: As stated earlier, AWS Lambda automatically scales up, manages infrastructure, fully secure, 24x7 available. You do not need to update the OS or resize when your application grows. AWS Lambda very easily deploys your code, scales-up, maintains, does all administration, and built-in logging for you, making you focus only on your code part and making it more robust.
- Pay what you use: AWS Lambda only charges you whenever your code is running or you are triggering any event. Every millisecond is counted towards your billing making it very accurate and cost-effective for customers. To learn more about you can check out AWS Lambda pricing.
Why Use AWS Lambda?
There are many reasons which correctly justify why you should use AWS Lambda. It is appropriate for almost all kinds of applications until you run the code in one of the languages mentioned in AWS Lambda’s documentation. The languages supported by AWS include Ruby, Go, Java, NodeJs, Python, etc. You can visit the documentation for a detailed understanding of exact runtimes supported by AWS Lambda; you just have to take care of the coding part of your application. AWS Lambda provides the appropriate runtime environment for your app. AWS does not provide you with the facility of changing the operating system environment at runtime and can not log in to compute instances. All this helps AWS Lambda seamlessly manage all resources, infrastructure, and scale up memory usages accordingly.
If you want customized compute services, AWS also offers you different services. For example, AWS EC2 allows you to choose everything like operating systems, memory, network, and the entire software stack. In this case, you will be responsible for memory scaling and fault tolerance, etc. Managing everything manually is not preferred because it may lead to serious issues in the application, but if you believe in your knowledge, then you can go ahead with manual operations.
AWS Events
In response to various events like lifecycle events, responding to HTTP requests, changing the values in the database, or some scheduled events, triggers can be configured to invoke a function using AWS Lambda. In short, we can say that an event is a sign of change in an environment. This environment can be an application, Software as a Service( SaaS ) service, or any custom application or app.
Example of AWS events:
- When an EC2 instance state change from pending to running, then Amazon EC2 invokes an event
- Amazon EC2 auto-scaling generates events when it launches or terminates instances.
- Similarly, when you make API calls, the AWS cloud trail invokes an event.
- Like Amazon Augmented AI events, AWS Batch events, and detailed information in the documentation, there are many similarities between them.
AWS Lambda invokes functions when any of the above events are triggered to communicate with other AWS services.
Event is a JSON of origin and information of associated events, depending on the event. The structure of events differs from one event to another. At runtime, Lambda converts the event into an object and passes it to your function.
An example event for Application Load Balancer:
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
}
},
"httpMethod": "GET",
"path": "/lambda",
"queryStringParameters": {
"query": "1234ABCD"
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip",
"accept-language": "en-US,en;q=0.9",
"connection": "keep-alive",
"host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
"x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
"x-forwarded-for": "72.12.164.125",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
"x-imforwards": "20"
},
"body": "",
"isBase64Encoded": false
}
You might be thinking, what are the services AWS Lambda communicates with by invoking events? Well, there are various kinds of services that AWS Lambda uses. Here are some examples:
Services that AWS uses for reading data are:
- Amazon DynamoDB
- Amazon Kinesis
- Amazon MQ
- Amazon Managed Streaming for Apache Kafka
- self-managed Apache Kafka
- Amazon Simple Queue Service
To invoke Lambda functions synchronously:
- Elastic Load Balancing (Application Load Balancer)
- Amazon Cognito
- Amazon Lex
- Amazon Alexa
- Amazon API Gateway
- Amazon CloudFront (Lambda@Edge)
- Amazon Kinesis Data Firehose
- Amazon Simple Storage Service Batch
To invoke Lambda functions asynchronously:
- Amazon Simple Storage Service
- Amazon Simple Notification Service
- Amazon Simple Email Service
- AWS CloudFormation
- Amazon CloudWatch Logs
- Amazon CloudWatch Events
- AWS CodeCommit
- AWS Config
- AWS IoT
- AWS IoT Events
- AWS CodePipeline
Other services that are used by AWS Lambda are:
You can follow the given links for detailed ideas about each service. There is also a concept of Amazon EventBridge, a serverless event bus service that helps your application connect with data from various sources. EventBridge delivers a stream of real-time data from our applications, SaaS applications, and AWS services, and that data is routed to targets such as AWS Lambda. We have explained AWS EventBridge here because it is important for understanding how AWS events exactly work.
Which Languages are Compatible with AWS Lambda?
AWS Lambda provides support for various programming languages through the use of runtimes. Runtimes are a language-specific environment to compile and run a specific language's code. You have to choose a runtime and Linux distribution to create a container image. You will have to create a different container image if you want to change the runtime.
You can write a Lambda function in some specified languages only. But due to a wide range of languages and runtime, it is not so difficult to deploy your application on AWS Lambda.
AWS’s languages currently support Ruby, Java, Go, NodeJs, Powershell, C#, .NET, and Python. For supporting other languages you can use custom runtimes.
Common Use Cases
To know whether AWS is perfect for your application or not, you can check the following features and use cases:
- When your project has requirements for separate functions for separate actions then AWS works better, you can create isolated functions.
- Scalability: If you think that your application will have huge demands in the future then you need a scalable server. AWS automatically scales up when requirements get bigger.
- Prototyping: If you want a fool-proof application and want to test before deployment then AWS is best for this purpose.
- Stateless: All AWS Lambda functions are stateless, which means having no affinity with infrastructure. It means no need to store anything in memory.
- File processing: Photos can be uploaded in Amazon S3 bucket then it creates the thumbnail version and saves it into another S3 bucket. If your application requires uploading photos the AWS is a better option.
- Data and analytics: If your application stores data and require you to do analytics then you can store raw data in a table. Operations like delete, update, fetch, post can be easily done with the help of APIs.
- Websites: You can host your website and backend services on AWS.
- Broadcast: Like a repository in Github, it updates many files from one command.
How to Create Ruby Functions in AWS Lambda
In the initial days of the launch of AWS Lambda in 2014, only the support of Java, NodeJs, and python due to which these languages started revolutionizing and dominating the kingdom of serverless hosting and cloud services. But back in 2018, Ruby got some fame because AWS Lambda finally launched support for Ruby.
Nowadays, AWS Lambda supports Ruby 2.5 and Ruby 2.7 runtimes. The very first step from where you should start is a concept of the handler. The console creates a file named `lambda_function.rb`, which exports a function known as lambda_handler that takes an event object and context object. Lambda calls the lambda handler whenever the function is invoked. In Ruby, function names are generally in lower cases, and an underscore replaces space.
The basic lambda_function.rb with the function lambda_handler will look something like that:
#lambda_function.rb
def lambda_handler(event:, context:)
end
The above given is the simplest form of lambda function and easiest form.
Now you have some idea of AWS lambda and Lambda functions, follow this step-by-step process for creating a Ruby function in AWS Lambda.
Step 1: Create an AWS account and sign in to the Lambda console.
Before working with baby services in AWS, you need to have an AWS account. You can create it using your Amazon account or another email ID. You will get a free trial for learning purposes, but you have to show your credit card to them at the time of sign up. You can follow their guide to get started.
Step 2: Create two S3 buckets
After you have created your AWS account, create two S3 buckets. S3 stands for simple storage service and is a public cloud storage resource provided by Amazon web services. One of the S3 buckets is used to store the object initially, and another one is used for storing them when they are renamed or being moved to another location. If you are finding it troublesome to create S3 buckets, refer to the Amazon documentation.
Step 3: Creating Ruby function using AWS Lambda Console
In this, we will be writing the actual code for our function. We have two options for writing the function: either directly write in the Lambda console or in our favorite editor compatible with AWS, and then upload it to AWS. In this post, we are creating a function in the lambda console. While creating the S3 bucket, make sure to choose the same region as your Lambda. Service can not easily communicate in different regions. So make sure the region of your lambda and S3 is the same.
A good region can save a lot of work and hard work you may have to do in the future as some regions do not have all features required by your application. As a beginner, you can visit the region which is nearest to you.
Now coming back to the topic, now we will be creating the ruby function using the Lambda console. Go to the link https://console.aws.amazon.com/lambda, and it will open a console in your default region.
After you have logged in, you will see a form in which you have to fill in your function’s details, like function name, runtimes, permission, etc. After filling the form, click on the orange Create function button. After clicking on the create function, you will see a beautiful diagram depicting how lambda works with other services.
Step 4: Triggering the Lambda function from the event
Here we are triggering our Lambda function through the S3 trigger. In the view that opened after creating the function, click on S3 there. After that, some options will open for the S3 trigger configuration. From the drop-down, select that S3 bucks that have uploaded images. After selecting, hit Add. Now you have defined an event, it will trigger the lambda function whenever the image uploads to that bucket.
Step 5: Making changes with a lambda function
In this step, we are going to configure our lambda function. Click on the Lambda function box from the view where we have the S3 bucket box. After clicking, it will open an editor-like view to find the lambda_handler.rb file and lambda_handler function inside it. You can write your custom code here. We will be sharing one example function at the end of the article.
After configuring go to the file and then save the file. After that, you have to give some permissions for some extra tasks. For example, allowing the copy of data from one bucket to another by a function requires some extra privileges. From the scroll down, you have to select the Lambda function; moving down to the form will give you a link that will direct you to the IAM service and then click on attach the policy.
Lambda Function Example
We will be now showing you an example Ruby function on AWS Lambda. In this function, we will be uploading a file and then write a function to rename it and move it to another bucket.
Information reading from an event
The `lambda_handler` is the main function that procs all the events. Lambda_hadler function takes event and context as input. The Ruby hash is converted into a JSON string from an event and passed to lambda_handler.
For example, let us see the modified lambda_handler function below.
def lambda_handler(event:, context:)
first_record = event["Records"].first
bucket_name = first_record["s3"]["bucket"]["name"]
file_name= first_record["s3"]["object"]["key"]
end
In these lines of code, you can clearly see an S3 bucket we want to store some images. The key value in the S3 bucket could be used to identify the object we are storing, So in the lambda_handller function, we have to pass bucket name i.e., S3, and key-value from the event. The second line of the code represents how we are retrieving the first object from the event.
Ruby works very smoothly when it comes to string manipulation. We have to shorten the file name of the Ruby function, for the function we will be using Ruby’s inbuilt library. This library takes the first 21 characters of any file anime as the file name.
short_name = file_name[0..20]
If you have a little bit of programming knowledge, you understand that line is the same as selecting the first 21, i.e., 0 to 20, elements in an array.
Configuring AWS SDK
We do not need to add any extra third-party libraries, to use the AWS SDK in Lambda function in Ruby. AWS SDK is already configured in the Lambda function in Ruby. We just need to write a required statement on top of `lambda_function.rb` for using AWS SDK in our project. The given code should be added on top of `lambda_function.rb`:
require "aws-sdk-s3"
It imports all the functions and features available in aws-sdk-s3, and brings them to our file. It works in the same way as the `require` method works in NodeJs. It will help you connect with the s3 service.
Changing the location of files
To change the file’s location from one bucket to another, we have to use the move to function on the object and reference the original name of the object. In the code given below, we create a new client in the eu-west-1 region, and then an s3 resource. The new s3 resource is used to reference the object. Then we call the move_to method to call the s3 service which then copies the original file to a new location, and deletes it from the original location. The following code also shows how we can use the AWS SDK’s built-in function to move the file.
# Get reference to the file in S3
client = Aws::S3::Client.new(region: 'eu-west-1')
s3 = Aws::S3::Resource.new(client: client)
object = s3.bucket(bucket_name).object(file_name)
# Move the file to a new bucket
object.move_to(bucket: 'upload-image-short-name', key: short_name)
Combining the code
When all the above codes conjoin together we have a function that will move one file from one to another location and change the filename to the first 21 letters.
require "aws-sdk-s3"
def lambda_handler(event:, context:)
# Get the record
first_record = event["Records"].first
bucket_name = first_record["s3"]["bucket"]["name"]
file_name = first_record["s3"]["object"]["key"]
# shorten the name
short_name = file_name[0..20]
# Get reference to the file in S3
client = aws::S3::Client.new(region: 'eu-west-1')
s3 = aws::S3::Resource.new(client: client)
object = s3.bucket(bucket_name).object(file_name)
# Move the file to a new bucket
object.move_to(bucket: 'upload-image-short-name', key: short_name)
end
Testing the function
Let us test the function. Upload a file to the S3 bucket, which has a name greater than 11 letters. After some time, it will move, rename the file and move to another S3 bucket. If everything works fine, you have done a great job.
Some extra concepts while working with Ruby in AWS
While working in AWS Lambda in Ruby, you will need operations like logging, error handling, and context object. In this section, we will be explaining special concepts while with AWS Lambda in Ruby.
Lambda Context Object in Ruby
The context object provides information about methods and properties, which contains information about the execution environment, invocation, and function. Context objects are passed to the handler when the Lambda function fires.
Example context methods:
`get_remaining_time_in_millis`
- Returns the number of milliseconds left before the execution times outProperties:
function_name: Name of the corresponding Lambda function.
function_version: Version of the Lambda function.
invoked_function_arn: The Amazon Resource Name (ARN) is used to invoke the function.
memory_limit_in_mb: Amount of memory allocated for that function
aws_request_id: Identifier for the invocation function.
log_group_name: Log group of the function.
log_stream_name: Log stream of function instance.
deadline_ms: Timeout for the execution of the function, Unix time milliseconds.
client_context: The application used by the client provides this client’s context to the Lambda.
Function Logging in Ruby
Logging plays a major role during the development and deployment of APIs. AWS has made logging very easy by sending all the function metrics automatically to Amazon Cloudwatch. A Cloudwatch Logs log group and a log stream come with each instance of your Lambda function. You can watch your function logs using the AWS Command-line interface, the Lambda console, or the Cloudwatch console.
An example Ruby function that will return logs is:
# lambda_function.rb
def handler(event:, context:)
puts "## ENVIRONMENT VARIABLES"
puts ENV.to_a
puts "## EVENT"
puts event.to_a
end
For more detailed logs we can use the Logger library:
# lambda_function.rb
require 'logger'
def handler(event:, context:)
logger = Logger.new($stdout)
logger.info('## ENVIRONMENT VARIABLES')
logger.info(ENV.to_a)
logger.info('## EVENT')
logger.info(event)
event.to_a
end
For using the Lambda console, you can get detailed information from this Accessing Amazon Cloudwatch Logs for AWS Lambda of AWS.
For more information about logging in AWS Lambda using Ruby refer to the official docs of AWS.
Function errors in Ruby
Whenever the Lambda function generates an error, a JSON representation of the error is generated.
Example function which generates error is:
def handler(event:, context:)
puts "Processing event..."
[1, 2, 3].first("two")
"Success"
end
The above code generates a type error. JSON that is generated by the AWS lambda for this error is given below:
{
"errorMessage": "no implicit conversion of String into Integer",
"errorType": "Function<TypeError>",
"stackTrace": [
"/var/task/function.rb:3:in `first'",
"/var/task/function.rb:3:in `handler'"
]
}
For more detailed information for function errors and how it works, you refer to the function error in Ruby.
Try it For Yourself
Now hope you have learned a lot about AWS Lambda and the deployment of Ruby functions using AWS Lambda. Ruby is a marvelous application and certainly has a wide variety of applications. You can build a robust backend application using Ruby.
After the announcement of Ruby support on AWS, AWS Lambda opened the door for various kinds of innovative development. Now it's your turn to create a ruby function using AWS lambda and better your experience with Ruby and AWS.