Try to detect single-valued returns in AWS

Lambdas generally only deal with single values anyway, but for
consistency we should return similar results from a Lambda handler
as from an MVC handler in s-c-f-web.
This commit is contained in:
Dave Syer
2017-05-24 11:25:54 +01:00
parent 5589804d2c
commit 87f077954e
6 changed files with 215 additions and 67 deletions

View File

@@ -1,52 +0,0 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.function.adapter.aws;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Date;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
/**
* @author Mark Fisher
*/
public class FunctionInvokingKinesisEventHandler extends SpringBootRequestHandler<KinesisEvent, String> {
public FunctionInvokingKinesisEventHandler(Class<?> configurationClass) {
super(configurationClass);
}
@Override
protected String convertEvent(KinesisEvent event) {
StringBuilder result = new StringBuilder();
for (KinesisEventRecord record : event.getRecords()) {
String id = record.getEventID();
String name = record.getEventName();
String source = record.getEventSource();
Date timestamp = record.getKinesis().getApproximateArrivalTimestamp();
String partitionKey = record.getKinesis().getPartitionKey();
String sequenceNumber = record.getKinesis().getSequenceNumber();
ByteBuffer data = record.getKinesis().getData();
String dataString = new String(data.array(), Charset.forName("UTF-8"));
result.append(String.format("id=%s,name=%s,source=%s,timestamp=%s,partitionKey=%s,sequenceNumber=%s,data=%s",
id, name, source, timestamp, partitionKey, sequenceNumber, dataString));
}
return result.toString();
}
}

View File

@@ -16,19 +16,28 @@
package org.springframework.cloud.function.adapter.aws;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import java.util.List;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
/**
* @author Mark Fisher
*/
public class FunctionInvokingS3EventHandler extends SpringBootRequestHandler<S3Event, String> {
public class SpringBootKinesisEventHandler
extends SpringBootRequestHandler<KinesisEvent, String> {
public FunctionInvokingS3EventHandler(Class<?> configurationClass) {
public SpringBootKinesisEventHandler() {
super();
}
public SpringBootKinesisEventHandler(Class<?> configurationClass) {
super(configurationClass);
}
@Override
protected String convertEvent(S3Event event) {
return event.toJson();
protected List<KinesisEventRecord> convertEvent(KinesisEvent event) {
// TODO: maybe convert to List<Message>
return event.getRecords();
}
}

View File

@@ -28,7 +28,7 @@ import reactor.core.publisher.Flux;
/**
* @author Mark Fisher
*/
public class SpringBootRequestHandler<E, O> extends SpringFunctionInitializer implements RequestHandler<E, List<O>> {
public class SpringBootRequestHandler<E, O> extends SpringFunctionInitializer implements RequestHandler<E, Object> {
public SpringBootRequestHandler(Class<?> configurationClass) {
super(configurationClass);
@@ -39,24 +39,26 @@ public class SpringBootRequestHandler<E, O> extends SpringFunctionInitializer im
}
@Override
public List<O> handleRequest(E event, Context context) {
public Object handleRequest(E event, Context context) {
initialize();
Object input = convertEvent(event);
Flux<?> output = apply(extract(input));
return result(output);
return result(input, output);
}
private List<O> result(Flux<?> output) {
private Object result(Object input, Flux<?> output) {
List<Object> result = new ArrayList<>();
for (Object value : output.toIterable()) {
result.add(value);
}
return convertResult(result);
if (isSingleValue(input) && result.size()==1) {
return result.get(0);
}
return result;
}
@SuppressWarnings("unchecked")
protected List<O> convertResult(List<Object> value) {
return (List<O>) value;
private boolean isSingleValue(Object input) {
return !(input instanceof Collection);
}
private Flux<?> extract(Object input) {

View File

@@ -54,17 +54,24 @@ public class SpringBootStreamHandler extends SpringFunctionInitializer
initialize();
Object value = convertStream(input);
Flux<?> flux = apply(extract(value));
mapper.writeValue(output, result(flux));
mapper.writeValue(output, result(value, flux));
}
private Object result(Flux<?> flux) {
private Object result(Object input, Flux<?> flux) {
List<Object> result = new ArrayList<>();
for (Object value : flux.toIterable()) {
result.add(value);
}
if (isSingleValue(input) && result.size()==1) {
return result.get(0);
}
return result;
}
private boolean isSingleValue(Object input) {
return !(input instanceof Collection);
}
private Flux<?> extract(Object input) {
if (input instanceof Collection) {
return Flux.fromIterable((Iterable<?>) input);