M. Chirico
M. Chirico

Reputation: 103

Amazon Lambda timing out when attempting to initialize a client for DynamoDB

I have the following Java class that is uploaded on Amazon's Lambda service:

public class DevicePutHandler implements RequestHandler<DeviceRequest, Device> {
    private static final Logger log = Logger.getLogger(DevicePutHandler.class);

    public Device handleRequest(DeviceRequest request, Context context) {
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
        DynamoDBMapper mapper = new DynamoDBMapper(client);

        if (request == null) {
            log.info("The request had a value of null.");
            return null;
        }

        log.info("Retrieving device");
        Device deviceRetrieved = mapper.load(Device.class, request.getDeviceId());

        log.info("Updating device properties");
        deviceRetrieved.setBuilding(request.getBuilding());
        deviceRetrieved.setMotionPresent(request.getMotionPresent());
        mapper.save(deviceRetrieved);

        log.info("Updated device has been saved");
        return deviceRetrieved;
    }
}

I also have an Execution Role set that gives me complete control over DynamoDB. My permissions should be perfectly fine since I've used the exact same permissions with other projects that used Lambda and DynamoDB in this exact manner (the only difference being a different request type).

The intended point of this class is to have it be called by API Gateway (API Gateway -> Lambda -> DynamoDB), but for now I simply am trying to test it on Lambda (Lambda -> DynamoDB).

For reference, in case it matters, here is the DeviceRequest class:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({ "deviceId", "building", "motionPresent" })
public class DeviceRequest {

   @JsonProperty("deviceId")
   private String deviceId;
   @JsonProperty("building")
   private String building;
   @JsonProperty("motionPresent")
   private Boolean motionPresent;
   @JsonIgnore
   private Map<String, Object> additionalProperties = new HashMap<String, Object>();

   @JsonProperty("deviceId")
   public String getDeviceId() {
       return deviceId;
   }

   @JsonProperty("deviceId")
   public void setDeviceId(String deviceId) {
       this.deviceId = deviceId;
   }

   @JsonProperty("building")
   public String getBuilding() {
       return building;
   }

    @JsonProperty("building")
    public void setBuilding(String building) {
        this.building = building;
    }

    @JsonProperty("motionPresent")
    public Boolean getMotionPresent() {
        return motionPresent;
    }

    @JsonProperty("motionPresent")
        public void setMotionPresent(Boolean motionPresent) {
        this.motionPresent = motionPresent;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

And here is the Device class:

@DynamoDBTable(tableName="DeviceTable")
public class Device {
    private String deviceID;
    private String building;
    private String queue;
    private boolean motionPresent;

    @DynamoDBHashKey(attributeName="Device ID")
    public String getDeviceID() {
        return deviceID;
    }

    public void setDeviceID(String deviceID) {
        this.deviceID = deviceID;
    }

    @DynamoDBAttribute(attributeName="Motion Present")
    public boolean getMotionPresent() {
        return motionPresent;
    }

    public void setMotionPresent(boolean motionPresent) {
        this.motionPresent = motionPresent;
    }

    @DynamoDBAttribute(attributeName="Building")
    public String getBuilding() {
        return this.building;
    }

    public void setBuilding(String building) {
        this.building = building;
    }

    @DynamoDBAttribute(attributeName="Queue")
    public String getQueue() {
        return this.queue;
    }

    public void setQueue(String queue) {
        this.queue = queue;
    }
}

Here is the JSON input that I'm trying to test the Lambda with:

{
  "deviceId": "test_device_name",
  "building": "building1",
  "motionPresent": false
}

No exceptions whatsoever are thrown (I've tried wrapping it around a try/catch block) and the lambda timing out is the only thing that happens. I've tried using log/print statements at the very beginning prior to the initialization of the DynamoDB client to see if the request can be read properly and it does appear to properly parse the JSON fields. I've also separated the client builder out and found that the builder object is able to be initialized, but the timing out comes from when the builder calls build() to make the client.

If anyone has any insight into why this timing out is occurring, please let me know!

Upvotes: 2

Views: 930

Answers (1)

M. Chirico
M. Chirico

Reputation: 103

Turns out that by bumping up the timout period AND the allotted memory, the problem get solved. Not sure why it works since the lambda always indicated that its memory usage was under the previously set limit, but oh well. Wish that in the future Amazon will provide better error feedback that indicates if a lambda needs more resources to run.

Upvotes: 8

Related Questions