Showing posts with label lambda. Show all posts
Showing posts with label lambda. Show all posts

Sunday, February 15, 2026

Lambda Before Switch

 This article was originally published in JRoller on September 22, 2015.

We had this method that was doing the same thing several times in a row. Here is a simplified version:

void resolveAll() {
	a = resolveA();
	if (a == null)
		states.remove(State.A);
	else
		states.add(State.A);

	b = resolveB();
	if (b == null)
		states.remove(State.B);
	else
		states.add(State.B);

	c = resolveC();
	if (c == null)
		states.remove(State.C);
	else
		states.add(State.C);
} 

It's almost the same thing repeated three times (a bit more in the real life code), except for this method resolveX which is different each time, returning a different type of object. We needed to modify the code, but did not feel like having to repeat the change several times. So we resorted to a refactoring. But what to do with this resolveX method? Inner classes are really ugly, so we turned to a switch:

void resolveAll() {
	a = resolve(State.A);
	b = resolve(State.B);
	c = resolve(State.C);
} 
	
@SuppressWarnings("unchecked")
private <T> T resolve(State state) {
	T resolved = null;
	switch (state) {
		case A:
			resolved = (T) resolveA();
			break;
		case B:
			resolved = (T) resolveB();
			break;
		case C:
			resolved = (T) resolveC();
			break;
	} 

	if (resolved == null) {
		states.remove(state);
	}  else {
		states.add(state);
	} 
	
	return resolved;
} 

Not that much simpler than the original code. However, we are moving slowly to Java 8. With lambdas, inner classes do not look so ugly anymore:

void resolveAll() {
	a = resolve(State.A, this::resolveA);
	b = resolve(State.B, this::resolveB);
	c = resolve(State.C, this::resolveC);
} 

private <T> T resolve(State state, Supplier<T> resolver) {
	T resolved = resolver.get();
	
	if (resolved == null) {
		states.remove(state);
	}  else {
		states.add(state);
	} 
	
	return resolved;
} 

Wednesday, October 2, 2024

AWS: Step functions can keep only Lambda payloads

 When running an AWS Lambda in synchronous mode from a Step Function, you will get the Lambda's return value in the output's Payload part. But unfortunately, you might also get some mostly useless information as well:

{
    "ExecutedVersion": "$LATEST",
    "Payload": {
        "result": "value"
    },
    "SdkHttpMetadata": {},
    "HttpHeaders": {}
}

When browsing your Step Functions's output, that's a lot of noise. So to keep only the lambda's payload part, you can add this line in your task definition:

    "ResultSelector": { "Payload.$": "$.Payload" }

Keep only the good stuff!

Friday, October 6, 2023

AWS: Automatic Subscription Confirmation from SQS Queue to SNS Topic

 We have an architecture in AWS where different events from different accounts need to be sent to one central SQS queue. Since the events will cross both accounts and regions, one way to do it is to send them to a local SNS Topic. 

The SQS queue will have to subscribe to all those Topics, but we can not do it on the SQS side, since it does not know each time someone pops out a new account. However, the problem with having the SNS Topics create the subscriptions, is that they are waiting for confirmation from the SQS queue.

Since we already have a lambda waiting on the other side of the queue, handling all the events, we added a small code to handle the subscription confirmation as well. Here it is:

import json
import urllib.request

def lambda_handler(event, context):
    for record in event["Records"]:
        body = json.loads(record["body"])

        if body.get("Type") == "SubscriptionConfirmation":
            handle_subscription_confirmation(body)

def handle_subscription_confirmation(message):
    url = message["SubscribeURL"]

    with urllib.request.urlopen(url) as response:
        print(response.read())

I find it strange that the Cloudformation template that we use to create the subscription does not handle the confirmation as well. Or maybe not cross-account?


Friday, April 7, 2023

AWS: Create a Layer with Git

 If you want to perform Git operations inside an AWS Lambda written in Python, you can decide to use the GitPython library. However, it needs git to be installed on your system.

In order to package git, I discovered a really nice tool: lambci/yumda. It's a docker container that overrides the yum installer to deploy the library you install, including all its dependencies, into a separate folder called /lambda/opt. So all you need to do is to yum your git, and zip the content of the folder.

Here is an example of a script that packages both GitPython and git into a zip file compatible with AWS Layers:

docker run --rm -v "$PWD":/tmp/layer lambci/yumda:2 bash -c "
  yum install -y git && \
  cd /lambda/opt && \
  zip -yr /tmp/layer/gitlayer.zip
"

pip install GitPython -t python
zip -r gitlayer.zip python/*

Then you can send this zip to an S3 bucket and create your layer easily. The nice thing about running this script inside a CodeBuild is that all tools, such as docker and pip, are already installed. However, for docker, do not forget to enable the Privileged Mode.