Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: aws/aws-lambda-ruby-runtime-interface-client
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.0.0
Choose a base ref
...
head repository: aws/aws-lambda-ruby-runtime-interface-client
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 10 commits
  • 8 files changed
  • 6 contributors

Commits on Mar 5, 2025

  1. Update README for ENTRYPOINT (#41)

    mullermp authored Mar 5, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    e2c5cf4 View commit details
  2. Add missing level_override instance variable to logger #initialize (#32)

    * Add missing level_override instance variable from logger 1.6.0
    
    compatibility for most recent, included in ruby 3.3.3 logger.
    ruby/logger@7aabb0b
    
    * Simpified changes with manipulating only required params
    
    * Update logger_patch.rb
    
    Add annotation what's going on
    choosen authored Mar 5, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    26a442f View commit details

Commits on Apr 22, 2025

  1. feat: add tenant-id to lambda context

    Ramisa Alam committed Apr 22, 2025
    Copy the full SHA
    bc5c6ca View commit details

Commits on Apr 24, 2025

  1. feat: add tenant-id to lambda context (#43)

    Co-authored-by: Ramisa Alam <[email protected]>
    ramisa2108 and Ramisa Alam authored Apr 24, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    abf8e41 View commit details

Commits on May 21, 2025

  1. Bump version to 3.1.0

    Ramisa Alam committed May 21, 2025
    Copy the full SHA
    2c38b72 View commit details

Commits on May 22, 2025

  1. Merge pull request #45 from ramisa2108/main

    Bump version to 3.1.0
    ramisa2108 authored May 22, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    e3c28bc View commit details

Commits on Jun 5, 2025

  1. Fix Formatting override being ignored. (#47)

    * Fix Formatter Override Being Ignored.
    
    ---------
    
    Co-authored-by: Mohammed Ehab <[email protected]>
    M-Elsaeed and Mohammed Ehab authored Jun 5, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    d9cb0a0 View commit details
  2. Version Bump to 3.1.1 (#48)

    * Version Bump to 3.1.1
    
    ---------
    
    Co-authored-by: Mohammed Ehab <[email protected]>
    M-Elsaeed and Mohammed Ehab authored Jun 5, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    ff6b60a View commit details

Commits on Jun 6, 2025

  1. Don't Ignore Custom Formatters + Version Bump to 3.1.2 (#49)

    * Fix Formatter Override Being Ignored.
    
    ---------
    
    Co-authored-by: Mohammed Ehab <[email protected]>
    M-Elsaeed and Mohammed Ehab authored Jun 6, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    c5cf4de View commit details

Commits on Jun 11, 2025

  1. Handle Signal Exceptions during Runtime API Http Requests Gracefully …

    …and Version Bump to 3.1.3 (#50)
    
    * Handle Interrupts to the Runtime API Http Requests Gracefully and Version Bump to 3.1.3.
    
    * Add Unit Test
    
    ---------
    
    Co-authored-by: Mohammed Ehab <[email protected]>
    M-Elsaeed and Mohammed Ehab authored Jun 11, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    d6f4cb4 View commit details
49 changes: 28 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
## AWS Lambda Ruby Runtime Interface Client

We have open-sourced a set of software packages, Runtime Interface Clients (RIC), that implement the Lambda
[Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html), allowing you to seamlessly extend your preferred
base images to be Lambda compatible.
The Lambda Runtime Interface Client is a lightweight interface that allows your runtime to receive requests from and send requests to the Lambda service.
We have open-sourced a set of software packages, Runtime Interface Clients (RIC), that implements the Lambda
[Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html), allowing you to seamlessly extend
your preferred base images to be Lambda compatible.
The Lambda Runtime Interface Client is a lightweight interface that allows your runtime to
receive requests from and send requests to the Lambda service.

The Lambda Ruby Runtime Interface Client is vended through [rubygems](https://rubygems.org/gems/aws_lambda_ric).
You can include this package in your preferred base image to make that base image Lambda compatible.

## Requirements
The Ruby Runtime Interface Client package currently supports Ruby versions:
- 3.2 and 3.3
The Ruby Runtime Interface Client package currently supports ruby 3.0 and above.

## Usage

@@ -37,17 +37,9 @@ Or install it manually as:

$ gem install aws_lambda_ric


Next step would be to copy your Lambda function code into the image's working directory.
```dockerfile
# Copy function code
RUN mkdir -p ${FUNCTION_DIR}
COPY app.rb ${FUNCTION_DIR}

WORKDIR ${FUNCTION_DIR}
```

The next step would be to set the `ENTRYPOINT` property of the Docker image to invoke the Runtime Interface Client and then set the `CMD` argument to specify the desired handler.
The next step would be to copy your Lambda function code into the image's working directory.
You will need to set the `ENTRYPOINT` property of the Docker image to invoke the Runtime Interface Client and
then set the `CMD` argument to specify the desired handler.

Example Dockerfile:
```dockerfile
@@ -84,7 +76,18 @@ ENTRYPOINT ["/usr/local/bin/aws_lambda_ric"]
CMD ["app.App::Handler.process"]
```

Example Ruby handler `app.rb`:
Note that the `ENTRYPOINT` may differ based on the base image used. You can find the correct path by running an
interactive shell in the container and checking the installed location of the gem.

```shell script
docker run -it --rm amazonlinux:latest bash
yum install -y which ruby
gem install aws_lambda_ric
which aws_lambda_ric
```

Finally, create a Ruby handler. This is an example `app.rb`:

```ruby
module App
class Handler
@@ -97,7 +100,10 @@ end

### Local Testing

To make it easy to locally test Lambda functions packaged as container images we open-sourced a lightweight web-server, Lambda Runtime Interface Emulator (RIE), which allows your function packaged as a container image to accept HTTP requests. You can install the [AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator) on your local machine to test your function. Then when you run the image function, you set the entrypoint to be the emulator.
To make it easy to locally test Lambda functions packaged as container images we open-sourced a lightweight web-server,
Lambda Runtime Interface Emulator (RIE), which allows your function packaged as a container image to accept HTTP requests.
You can install the [AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator) on your local machine to test your function.
Thenm when you run the image function, you set the entrypoint to be the emulator.

*To install the emulator and test your Lambda function*

@@ -108,7 +114,8 @@ mkdir -p ~/.aws-lambda-rie && \
curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
chmod +x ~/.aws-lambda-rie/aws-lambda-rie
```
2) Run your Lambda image function using the docker run command.

1) Run your Lambda image function using the docker run command.

```shell script
docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
@@ -119,7 +126,7 @@ docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \

This runs the image as a container and starts up an endpoint locally at `http://localhost:9000/2015-03-31/functions/function/invocations`.

3) Post an event to the following endpoint using a curl command:
1) Post an event to the following endpoint using a curl command:

```shell script
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
47 changes: 47 additions & 0 deletions RELEASE.CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
### Jun 10, 2025
`3.1.3`
- Handle Signal Exceptions during Runtime API Http Requests Gracefully and Version Bump to 3.1.3 ([#50](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/50))

### Jun 6, 2025
`3.1.2`
- Don't Ignore Custom Formatters. ([#49](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/49))

### Jun 5, 2025
`3.1.1`
- Fix Logger Formatting override being ignored. ([#47](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/47))

### May 21, 2025
`3.1.0`
- Add support for multi tenancy ([#43](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/43))

### Feb 19, 2025
`3.0.0`
- Fix send_error_response method signature ([#16](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/16))
- Add "require 'stringio'" ([#20](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/20))
- CentOS 8 is EOL, stop testing on centOS 8 ([#21](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/21))
- Update rbenv & ruby-build github URLs ([#22](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/22))
- Create pull request template ([#29](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/29))
- Version 3 ([#38](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/38))
- V3 Readme Update ([#39](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/39))
- V3 Readme Update ([#40](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/40))

### Sep 29, 2021
`2.0.0`
- AWS Lambda Runtime Interface Client for Ruby with ARM64 support

### Dec 18, 2020
`1.0.2`
- Fix Logger issue
- Add User-Agent header for the requests RIC makes
- Small fix in the README file

### Dec 01, 2020
`1.0.1`
- Improve the examples in the README file
- Update the rake requirement from ~> 10.0 to ~> 13.0
- Add license and required_ruby_version attributes

### Dec 01, 2020
`1.0.0`
- Initial release of AWS Lambda Ruby Runtime Interface Client

3 changes: 2 additions & 1 deletion lib/aws_lambda_ric/lambda_context.rb
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
class LambdaContext
attr_reader :aws_request_id, :invoked_function_arn, :log_group_name,
:log_stream_name, :function_name, :memory_limit_in_mb, :function_version,
:identity, :client_context, :deadline_ms
:identity, :tenant_id, :client_context, :deadline_ms

def initialize(request)
@clock_diff = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond) - Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
@@ -16,6 +16,7 @@ def initialize(request)
@memory_limit_in_mb = ENV['AWS_LAMBDA_FUNCTION_MEMORY_SIZE']
@function_version = ENV['AWS_LAMBDA_FUNCTION_VERSION']
@identity = JSON.parse(request['Lambda-Runtime-Cognito-Identity']) unless request['Lambda-Runtime-Cognito-Identity'].to_s.empty?
@tenant_id = request['Lambda-Runtime-Aws-Tenant-Id'] unless request['Lambda-Runtime-Aws-Tenant-Id'].to_s.empty?
@client_context = JSON.parse(request['Lambda-Runtime-Client-Context']) unless request['Lambda-Runtime-Client-Context'].to_s.empty?
end

2 changes: 2 additions & 0 deletions lib/aws_lambda_ric/lambda_server.rb
Original file line number Diff line number Diff line change
@@ -33,6 +33,8 @@ def next_invocation
"Received #{resp.code} when waiting for next invocation."
)
end
rescue SignalException => sig
raise LambdaErrors::InvocationError.new("Next invocation HTTP request from the runtime interface client was interrupted with a #{sig} SIGNAL, gracefully shutting down.")
rescue LambdaErrors::InvocationError => e
raise e
rescue StandardError => e
23 changes: 10 additions & 13 deletions lib/aws_lambda_ric/logger_patch.rb
Original file line number Diff line number Diff line change
@@ -4,19 +4,16 @@ module LoggerPatch
def initialize(logdev, shift_age = 0, shift_size = 1048576, level: 'debug',
progname: nil, formatter: nil, datetime_format: nil,
binmode: false, shift_period_suffix: '%Y%m%d')
# use unpatched constructor if logdev is a filename or an IO Object other than $stdout or $stderr
if logdev && logdev != $stdout && logdev != $stderr
super(logdev, shift_age, shift_size, level: level, progname: progname,
formatter: formatter, datetime_format: datetime_format,
binmode: binmode, shift_period_suffix: shift_period_suffix)
else
self.level = level
self.progname = progname
@default_formatter = LogFormatter.new
self.datetime_format = datetime_format
self.formatter = formatter
@logdev = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink
@level_override = {}
logdev_lambda_override = logdev
formatter_override = formatter
# use unpatched constructor if logdev is a filename or an IO Object other than $stdout or $stderr
if !logdev || logdev == $stdout || logdev == $stderr
logdev_lambda_override = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink
formatter_override = formatter_override || LogFormatter.new
end

super(logdev_lambda_override, shift_age, shift_size, level: level, progname: progname,
formatter: formatter_override, datetime_format: datetime_format,
binmode: binmode, shift_period_suffix: shift_period_suffix)
end
end
2 changes: 1 addition & 1 deletion lib/aws_lambda_ric/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module AwsLambdaRIC
VERSION = '3.0.0'
VERSION = '3.1.3'
end
75 changes: 75 additions & 0 deletions test/unit/lambda_server_test.rb
Original file line number Diff line number Diff line change
@@ -15,6 +15,23 @@ def setup
@under_test = RapidClient.new(@server_address, @mock_user_agent)
end

def test_next_invocation_handles_different_signals
['INT', 'TERM', 'QUIT'].each do |signal|
http_mock = Minitest::Mock.new
http_mock.expect(:read_timeout=, nil, [RapidClient::LONG_TIMEOUT_MS])
http_mock.expect(:start, nil) { raise SignalException.new(signal) }

Net::HTTP.stub :new, http_mock do
error = assert_raises(LambdaErrors::InvocationError) do
@under_test.next_invocation
end

assert_match(/Next invocation HTTP request from the runtime interface client was interrupted with a SIG#{signal} SIGNAL, gracefully shutting down./, error.message)
http_mock.verify
end
end
end

def test_post_invocation_error_with_large_xray_cause
large_xray_cause = ('a' * 1024 * 1024)[0..-2]
headers = {'Lambda-Runtime-Function-Error-Type' => @error.runtime_error_type,
@@ -53,4 +70,62 @@ def test_post_invocation_error_with_too_large_xray_cause

assert_mock post_mock
end

def mock_next_invocation_response()
mock_response = Net::HTTPSuccess.new(1.0, '200', 'OK')
mock_response['Lambda-Runtime-Aws-Request-Id'] = @request_id
mock_response
end

def mock_next_invocation_request(mock_response)
get_mock = Minitest::Mock.new
get_mock.expect(:read_timeout=, nil, [RapidClient::LONG_TIMEOUT_MS])
get_mock.expect(:start, mock_response) do |&block|
block.call(get_mock)
end
get_mock.expect(:get, mock_response, ['/2018-06-01/runtime/invocation/next', {'User-Agent' => @mock_user_agent}])
get_mock
end

def assert_next_invocation(get_mock, expected_tenant_id)
Net::HTTP.stub(:new, get_mock, ['127.0.0.1', 9001]) do
request_id, response = @under_test.next_invocation
assert_equal @request_id, request_id
assert_equal expected_tenant_id, response['Lambda-Runtime-Aws-Tenant-Id']
end
end

def test_next_invocation_without_tenant_id_header
mock_response = mock_next_invocation_response()
get_mock = mock_next_invocation_request(mock_response)
assert_next_invocation(get_mock, nil)
assert_mock get_mock
end

def test_next_invocation_with_tenant_id_header
mock_response = mock_next_invocation_response()
mock_response['Lambda-Runtime-Aws-Tenant-Id'] = 'blue'

get_mock = mock_next_invocation_request(mock_response)
assert_next_invocation(get_mock, 'blue')
assert_mock get_mock
end

def test_next_invocation_with_empty_tenant_id_header
mock_response = mock_next_invocation_response()
mock_response['Lambda-Runtime-Aws-Tenant-Id'] = ''

get_mock = mock_next_invocation_request(mock_response)
assert_next_invocation(get_mock, '')
assert_mock get_mock
end

def test_next_invocation_with_null_tenant_id_header
mock_response = mock_next_invocation_response()
mock_response['Lambda-Runtime-Aws-Tenant-Id'] = nil

get_mock = mock_next_invocation_request(mock_response)
assert_next_invocation(get_mock, nil)
assert_mock get_mock
end
end
3 changes: 2 additions & 1 deletion test/unit/resources/runtime_handlers/ctx.rb
Original file line number Diff line number Diff line change
@@ -9,7 +9,8 @@ def get_context(event:,context:)
log_group_name: context.log_group_name,
log_stream_name: context.log_stream_name,
memory_limit_in_mb: context.memory_limit_in_mb,
function_version: context.function_version
function_version: context.function_version,
tenant_id: context.tenant_id
}
end