diff --git a/main.tf b/main.tf index d18e6b2..7371fd5 100644 --- a/main.tf +++ b/main.tf @@ -59,6 +59,12 @@ module "ruby-2_7-lambda" { depends_on = [aws_dynamodb_table.data] } +module "ruby-yjit-3_2-lambda" { + source = "./ruby-yjit-3.2" + data_table = aws_dynamodb_table.data + depends_on = [aws_dynamodb_table.data] +} + resource "aws_apigatewayv2_api" "gateway" { name = "lambda-battle-api" protocol_type = "HTTP" @@ -66,7 +72,8 @@ resource "aws_apigatewayv2_api" "gateway" { locals { lambda_resources = { - "ruby-2_7-x86" = { "module" = module.ruby-2_7-lambda } + "ruby-2_7-x86" = { "module" = module.ruby-2_7-lambda }, + "ruby-yjit-3_2-x86" = { "module" = module.ruby-yjit-3_2-lambda } } } diff --git a/ruby-yjit-3.2/main.tf b/ruby-yjit-3.2/main.tf new file mode 100644 index 0000000..a8770f7 --- /dev/null +++ b/ruby-yjit-3.2/main.tf @@ -0,0 +1,94 @@ +variable "data_table" {} + +resource "aws_iam_role" "lambda_role" { + name = "ruby-yjit-3.2_lambda_role" + assume_role_policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Action" : "sts:AssumeRole", + "Principal" : { + "Service" : "lambda.amazonaws.com" + }, + "Effect" : "Allow", + "Sid" : "" + } + ] + }) +} + +resource "aws_iam_policy" "lambda_policy" { + name = "ruby-yjit-3.2_battle_lambda_role" + path = "/" + description = "AWS IAM Policy for ruby yjit 3.2 lambda" + + policy = jsonencode({ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:*:*:*", + "Effect": "Allow" + }, + { + "Action": [ + "dynamodb:BatchGetItem", + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem" + ], + "Resource": var.data_table.arn, + "Effect": "Allow" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" { + role = aws_iam_role.lambda_role.name + policy_arn = aws_iam_policy.lambda_policy.arn +} + +locals { + dist_path = "${path.module}/dist/lambda.zip" +} + +data "archive_file" "source" { + type = "zip" + source_dir = "${path.module}/src" + output_path = local.dist_path +} + +resource "aws_lambda_function" "lambda" { + filename = local.dist_path + function_name = "ruby-yjit-3_2_lambda" + role = aws_iam_role.lambda_role.arn + handler = "func.handler" + + source_code_hash = data.archive_file.source.output_base64sha256 + environment { + variables = { + "GEM_PATH" = "./vendor", + "TABLE" = var.data_table.name, + "RUBY_YJIT_ENABLE" = 1 + } + } + + runtime = "ruby3.2" + memory_size = 128 + timeout = 16 + #reserved_concurrent_executions = 1 + + depends_on = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role] +} + +output "lambda" { + value = aws_lambda_function.lambda +} diff --git a/ruby-yjit-3.2/src/func.rb b/ruby-yjit-3.2/src/func.rb new file mode 100644 index 0000000..76cab03 --- /dev/null +++ b/ruby-yjit-3.2/src/func.rb @@ -0,0 +1,34 @@ +require "aws-sdk-dynamodb" + +DB = ::Aws::DynamoDB::Client.new +LANG = "ruby-yjit-3.2-x86" + +Item = Data.define(:langCase, :iteration, :raw_event, :event_params) do + def to_h = super.except(:event_params).merge(**event_params) +end + +def handler(event:, **) + return { statusCode: 400, body: "yjit not enabled"} unless RubyVM::YJIT.enabled? + + event_params = parse_event_body_params(event) + event_params => iteration: + + return { statusCode: 400 } unless iteration + + item = Item.new(LANG, iteration, event.to_h, event_params) + + new_item = DB.put_item( + table_name: ENV["TABLE"], + item: item.to_h, + return_values: "ALL_OLD" + ).attributes + + previous_item = DB.get_item(table_name: ENV["TABLE"], key: { langCase: LANG, iteration: iteration - 1 }).item + + { statusCode: 200, body: (previous_item || new_item).to_json } +end + +def parse_event_body_params(event) = JSON.parse( + (event in isBase64Encoded: TrueClass, body: body) ? Base64.decode64(body) : body, + symbolize_names: true +)