Skip to content

Commit 3c9f719

Browse files
Refactor handler into smaller methods
1 parent fe600dd commit 3c9f719

File tree

1 file changed

+106
-35
lines changed

1 file changed

+106
-35
lines changed

src/main/java/com/github/kernelpanicaus/ddb_loader/LambdaFunctionHandler.java

Lines changed: 106 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
import com.jayway.jsonpath.JsonPath;
77
import org.json.simple.JSONObject;
88
import org.json.simple.parser.JSONParser;
9+
import org.json.simple.parser.ParseException;
910
import software.amazon.awssdk.core.ResponseInputStream;
1011
import software.amazon.awssdk.core.sync.ResponseTransformer;
12+
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
1113
import software.amazon.awssdk.regions.Region;
1214
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
1315
import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest;
16+
import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemResponse;
1417
import software.amazon.awssdk.services.dynamodb.model.PutRequest;
1518
import software.amazon.awssdk.services.dynamodb.model.WriteRequest;
1619
import software.amazon.awssdk.services.s3.S3Client;
@@ -22,7 +25,7 @@
2225
import java.io.InputStream;
2326
import java.io.OutputStream;
2427
import java.util.ArrayList;
25-
import java.util.Collection;
28+
import java.util.List;
2629
import java.util.Map;
2730
import java.util.Scanner;
2831
import java.util.zip.GZIPInputStream;
@@ -36,28 +39,30 @@ public class LambdaFunctionHandler implements RequestStreamHandler {
3639
/**
3740
* Provide the AWS region which your DynamoDB table is hosted.
3841
*/
39-
static final Region AWS_REGION = Region.of(System.getenv("AWS_REGION"));
42+
private static final Region AWS_REGION = Region.of(System.getenv("AWS_REGION"));
4043

4144
/**
4245
* The DynamoDB table name.
4346
*/
4447
// TODO: Make this dynamic, from the S3 event.
45-
static final String DYNAMO_TABLE_NAME = System.getenv("DYNAMO_TABLE_NAME");
48+
private static final String DYNAMO_TABLE_NAME = System.getenv("DYNAMO_TABLE_NAME");
4649

4750
/**
4851
* Configurable batch size
4952
*/
50-
static final int BATCH_SIZE = Integer.parseInt(System.getenv().getOrDefault("BATCH_SIZE", "25"));
53+
private static final int BATCH_SIZE = Integer.parseInt(System.getenv().getOrDefault("BATCH_SIZE", "25"));
5154
//
5255
// static final ClientConfiguration config = new ClientConfiguration()
5356
// .withMaxConnections(ClientConfiguration.DEFAULT_MAX_CONNECTIONS * 2);
5457

55-
final S3Client s3Client = S3Client.builder()
58+
private static final S3Client s3Client = S3Client.builder()
5659
.region(AWS_REGION)
60+
.httpClientBuilder(UrlConnectionHttpClient.builder())
5761
.build();
5862

59-
final DynamoDbClient dynamoDBClient = DynamoDbClient.builder()
63+
private static final DynamoDbClient dynamoDBClient = DynamoDbClient.builder()
6064
.region(AWS_REGION)
65+
.httpClientBuilder(UrlConnectionHttpClient.builder())
6166
.build();
6267

6368
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
@@ -81,73 +86,53 @@ public void handleRequest(InputStream inputStream, OutputStream outputStream, Co
8186
String srcKey = JsonPath.read(event, "$.Records[0].s3.object.key");
8287
String srcBucket = JsonPath.read(event, "$.Records[0].s3.bucket.name");
8388

84-
8589
logger.log("Bucket name: " + srcBucket + "\n");
8690
logger.log("Key name: " + srcKey + "\n");
8791
logger.log("S3 Object: " + srcBucket + "/" + srcKey + "\n");
8892

8993
logger.log("S3 Event Received: " + srcBucket + "/" + srcKey + "\n");
9094

91-
ResponseInputStream<GetObjectResponse> responseInputStream = s3Client.getObject(
92-
GetObjectRequest.builder()
93-
.bucket(srcBucket)
94-
.key(srcKey)
95-
.build()
96-
, ResponseTransformer.toInputStream()
97-
);
95+
ResponseInputStream<GetObjectResponse> responseInputStream = getS3ClientObject(srcKey, srcBucket);
9896

9997
logger.log("Reading input stream \n");
10098

10199
GZIPInputStream gis = new GZIPInputStream(responseInputStream);
102100
Scanner fileIn = new Scanner(gis);
103101
var parser = new JSONParser();
104102

105-
Collection<WriteRequest> itemList = new ArrayList<>();
106-
107103
int counter = 0;
108104
int batchCounter = 0;
105+
List<WriteRequest> itemList = new ArrayList<>();
106+
109107
while (fileIn.hasNext()) {
110-
var line = fileIn.nextLine();
111-
JSONObject jsonLine = (JSONObject) parser.parse(line);
112-
JSONObject jsonItem = (JSONObject) jsonLine.get("Item");
113108

114-
WriteRequest item = WriteRequest.builder()
115-
.putRequest(PutRequest.builder().item(jsonItem).build())
116-
.build();
109+
JSONObject jsonItem = getWriteItemRequest(fileIn, parser);
117110

118-
itemList.add(item);
111+
itemList.add(getWriteItemRequest(jsonItem));
119112

120113
logger.log("[" + batchCounter + "/" + counter + "] Adding item to itemlist \n");
121114
counter++;
122115

123116
if (counter == BATCH_SIZE) {
124-
batchCounter++;
125-
126-
var batchItemRequest = BatchWriteItemRequest.builder()
127-
.requestItems(Map.of(DYNAMO_TABLE_NAME, itemList))
128-
.build();
129117

130118
logger.log("Sending Batch " + batchCounter + " \n");
131-
132-
var outcome = dynamoDBClient.batchWriteItem(batchItemRequest);
119+
BatchWriteItemResponse outcome = getBatchWriteItemResponse(Map.of(DYNAMO_TABLE_NAME, itemList));
133120

134121
do {
135-
var unprocessedItemsRequest = BatchWriteItemRequest.builder()
136-
.requestItems(outcome.unprocessedItems())
137-
.build();
122+
BatchWriteItemRequest unprocessedItemsRequest = getBatchWriteItemRequest(outcome.unprocessedItems());
138123

139124
if (outcome.unprocessedItems().size() > 0) {
140125
logger.log("Retrieving the unprocessed " + outcome.unprocessedItems().size() + " items, batch [" + batchCounter + "].");
141-
outcome = dynamoDBClient.batchWriteItem(unprocessedItemsRequest);
126+
outcome = batchWrite(unprocessedItemsRequest);
142127
}
143128

144129
} while (outcome.unprocessedItems().size() > 0);
145130
itemList.clear();
131+
batchCounter++;
146132
counter = 0;
147133
}
148134
}
149135

150-
151136
logger.log("Load finish in " + (System.currentTimeMillis() - startTime) + "ms");
152137
fileIn.close();
153138
gis.close();
@@ -158,4 +143,90 @@ public void handleRequest(InputStream inputStream, OutputStream outputStream, Co
158143
}
159144
statusReport.setExecutiongTime(System.currentTimeMillis() - startTime);
160145
}
146+
147+
/**
148+
* <p>
149+
* Builds and returns a <code>WriteRequest</code> for JSON object.
150+
* </p>
151+
*
152+
* @param jsonItem
153+
* @return WriteRequest object
154+
*/
155+
private WriteRequest getWriteItemRequest(JSONObject jsonItem) {
156+
return WriteRequest.builder()
157+
.putRequest(PutRequest.builder().item(jsonItem).build())
158+
.build();
159+
}
160+
161+
/**
162+
* <p>
163+
* Takes a Map of Dynamo Table name to a List of Write requests and executes a bulk write.
164+
* </p>
165+
*
166+
* @param items Mapping of table name to collection of write requests.
167+
* @return BatchWriteItemResponse
168+
*/
169+
private BatchWriteItemResponse getBatchWriteItemResponse(Map<String, List<WriteRequest>> items) {
170+
return batchWrite(getBatchWriteItemRequest(items));
171+
}
172+
173+
/**
174+
* <p>
175+
* Builds and return a BatchWriteItemRequest object.
176+
* </p>
177+
*
178+
* @param items Mapping of table name to collection of write requests.
179+
* @return BatchWriteItemRequest
180+
*/
181+
private BatchWriteItemRequest getBatchWriteItemRequest(Map<String, List<WriteRequest>> items) {
182+
return BatchWriteItemRequest.builder()
183+
.requestItems(items)
184+
.build();
185+
}
186+
187+
/**
188+
* <p>
189+
* Executes BatchWriteItem operation against a Dynamo Table.
190+
* </p>
191+
*
192+
* @param `batchItemRequest`
193+
* @return <code>BatchWriteItemResponse</code>
194+
*/
195+
private BatchWriteItemResponse batchWrite(BatchWriteItemRequest batchItemRequest) {
196+
return dynamoDBClient.batchWriteItem(batchItemRequest);
197+
}
198+
199+
/**
200+
* <p>
201+
* Returns inner JSON object.
202+
* </p>
203+
*
204+
* @param fileIn
205+
* @param parser
206+
* @return <code>JSONObject</code>
207+
* @throws ParseException
208+
*/
209+
private JSONObject getWriteItemRequest(Scanner fileIn, JSONParser parser) throws ParseException {
210+
var line = fileIn.nextLine();
211+
JSONObject jsonLine = (JSONObject) parser.parse(line);
212+
return (JSONObject) jsonLine.get("Item");
213+
}
214+
215+
/**
216+
* <p>
217+
* getS3ClientObject and returns an S3 Object as a stream.
218+
* </p>
219+
*
220+
* @param srcKey
221+
* @param srcBucket
222+
* @return
223+
*/
224+
private ResponseInputStream<GetObjectResponse> getS3ClientObject(String srcKey, String srcBucket) {
225+
GetObjectRequest objectRequest = GetObjectRequest.builder()
226+
.bucket(srcBucket)
227+
.key(srcKey)
228+
.build();
229+
230+
return s3Client.getObject(objectRequest, ResponseTransformer.toInputStream());
231+
}
161232
}

0 commit comments

Comments
 (0)