Skip to content

Commit cba776c

Browse files
bmaizelszoewangg
authored andcommitted
Adding unprocessedKeysForTable to BatchGetItem results object
1 parent 7c5c2fd commit cba776c

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "DynamoDB Enhanced Client",
3+
"contributor": "",
4+
"type": "feature",
5+
"description": "Added method to BatchGetItem results to retrieve unprocessed keys for a given table."
6+
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.java

+34
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@
1818
import static java.util.Collections.emptyList;
1919
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.readAndTransformSingleItem;
2020

21+
import java.util.Collections;
2122
import java.util.List;
2223
import java.util.Map;
24+
import java.util.Optional;
2325
import java.util.stream.Collectors;
2426
import software.amazon.awssdk.annotations.SdkPublicApi;
2527
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
2628
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension;
29+
import software.amazon.awssdk.enhanced.dynamodb.Key;
2730
import software.amazon.awssdk.enhanced.dynamodb.MappedTableResource;
2831
import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DefaultOperationContext;
2932
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
3033
import software.amazon.awssdk.services.dynamodb.model.BatchGetItemResponse;
34+
import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes;
3135

3236
/**
3337
* Defines one result page with retrieved items in the result of a batchGetItem() operation, such as
@@ -74,6 +78,36 @@ public <T> List<T> resultsForTable(MappedTableResource<T> mappedTable) {
7478
.collect(Collectors.toList());
7579
}
7680

81+
/**
82+
* Returns a list of keys associated with a given table that were not processed during the operation, typically
83+
* because the total size of the request is too large or exceeds the provisioned throughput of the table. If an item
84+
* was attempted to be retrieved but not found in the table, it will not appear in this list or the results list.
85+
*
86+
* @param mappedTable the table to retrieve the unprocessed keys for
87+
* @return a list of unprocessed keys
88+
*/
89+
public List<Key> unprocessedKeysForTable(MappedTableResource<?> mappedTable) {
90+
KeysAndAttributes keysAndAttributes = this.batchGetItemResponse.unprocessedKeys().get(mappedTable.tableName());
91+
92+
if (keysAndAttributes == null) {
93+
return Collections.emptyList();
94+
}
95+
96+
String partitionKey = mappedTable.tableSchema().tableMetadata().primaryPartitionKey();
97+
Optional<String> sortKey = mappedTable.tableSchema().tableMetadata().primarySortKey();
98+
99+
return keysAndAttributes.keys()
100+
.stream()
101+
.map(keyMap -> {
102+
AttributeValue partitionValue = keyMap.get(partitionKey);
103+
AttributeValue sortValue = sortKey.map(keyMap::get).orElse(null);
104+
return Key.builder()
105+
.partitionValue(partitionValue)
106+
.sortValue(sortValue)
107+
.build(); })
108+
.collect(Collectors.toList());
109+
}
110+
77111
/**
78112
* A builder that is used to create a result object with the desired parameters.
79113
*/

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/BatchGetItemOperationTest.java

+73-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static java.util.stream.Collectors.toList;
2323
import static org.hamcrest.MatcherAssert.assertThat;
2424
import static org.hamcrest.Matchers.containsInAnyOrder;
25+
import static org.hamcrest.Matchers.empty;
2526
import static org.hamcrest.Matchers.is;
2627
import static org.hamcrest.Matchers.nullValue;
2728
import static org.hamcrest.Matchers.sameInstance;
@@ -36,6 +37,7 @@
3637
import static software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort.createUniqueFakeItemWithSort;
3738

3839
import java.util.Arrays;
40+
import java.util.Collections;
3941
import java.util.HashMap;
4042
import java.util.List;
4143
import java.util.Map;
@@ -94,13 +96,13 @@ public class BatchGetItemOperationTest {
9496
@Mock
9597
private DynamoDbEnhancedClientExtension mockExtension;
9698

97-
private DynamoDbEnhancedClient enhancedClient;
9899
private DynamoDbTable<FakeItem> fakeItemMappedTable;
99100
private DynamoDbTable<FakeItemWithSort> fakeItemWithSortMappedTable;
100101

101102
@Before
102103
public void setupMappedTables() {
103-
enhancedClient = DynamoDbEnhancedClient.builder().dynamoDbClient(mockDynamoDbClient).extensions().build();
104+
DynamoDbEnhancedClient enhancedClient =
105+
DynamoDbEnhancedClient.builder().dynamoDbClient(mockDynamoDbClient).extensions().build();
104106
fakeItemMappedTable = enhancedClient.table(TABLE_NAME, FakeItem.getTableSchema());
105107
fakeItemWithSortMappedTable = enhancedClient.table(TABLE_NAME_2, FakeItemWithSort.getTableSchema());
106108
}
@@ -296,6 +298,75 @@ public void transformResponse_multipleTables_multipleItems_noExtension() {
296298
assertThat(fakeItemWithSortResultsPage, containsInAnyOrder(FAKESORT_ITEMS.get(0)));
297299
}
298300

301+
@Test
302+
public void transformResponse_multipleTables_multipleItems_unprocessedKeys() {
303+
KeysAndAttributes keysAndAttributes1 =
304+
KeysAndAttributes.builder()
305+
.keys(Arrays.asList(FAKE_ITEM_MAPS.get(0), FAKE_ITEM_MAPS.get(1)))
306+
.build();
307+
308+
KeysAndAttributes keysAndAttributes2 =
309+
KeysAndAttributes.builder()
310+
.keys(Collections.singletonList(FAKESORT_ITEM_MAPS.get(0)))
311+
.build();
312+
313+
Map<String, KeysAndAttributes> keysAndAttributesMap = new HashMap<>();
314+
keysAndAttributesMap.put(TABLE_NAME, keysAndAttributes1);
315+
keysAndAttributesMap.put(TABLE_NAME_2, keysAndAttributes2);
316+
317+
BatchGetItemResponse fakeResponse =
318+
BatchGetItemResponse.builder()
319+
.unprocessedKeys(keysAndAttributesMap)
320+
.build();
321+
322+
BatchGetItemOperation operation = BatchGetItemOperation.create(emptyRequest());
323+
324+
BatchGetResultPage resultsPage = operation.transformResponse(fakeResponse, null);
325+
326+
List<Key> fakeItemResults1 = resultsPage.unprocessedKeysForTable(fakeItemMappedTable);
327+
List<Key> fakeItemResults2 = resultsPage.unprocessedKeysForTable(fakeItemWithSortMappedTable);
328+
assertThat(fakeItemResults1, containsInAnyOrder(FAKE_ITEM_KEYS.get(0), FAKE_ITEM_KEYS.get(1)));
329+
assertThat(fakeItemResults2, containsInAnyOrder(FAKESORT_ITEM_KEYS.get(0)));
330+
}
331+
332+
@Test
333+
public void transformResponse_multipleTables_multipleItems_no_unprocessedKeys() {
334+
BatchGetItemResponse fakeResponse = BatchGetItemResponse.builder().build();
335+
336+
BatchGetItemOperation operation = BatchGetItemOperation.create(emptyRequest());
337+
338+
BatchGetResultPage resultsPage = operation.transformResponse(fakeResponse, null);
339+
340+
List<Key> fakeItemResults1 = resultsPage.unprocessedKeysForTable(fakeItemMappedTable);
341+
List<Key> fakeItemResults2 = resultsPage.unprocessedKeysForTable(fakeItemWithSortMappedTable);
342+
assertThat(fakeItemResults1, empty());
343+
assertThat(fakeItemResults2, empty());
344+
}
345+
346+
@Test
347+
public void transformResponse_multipleTables_multipleItems_unprocessedKeys_tableNotExists() {
348+
KeysAndAttributes keysAndAttributes1 =
349+
KeysAndAttributes.builder()
350+
.keys(Arrays.asList(FAKE_ITEM_MAPS.get(0), FAKE_ITEM_MAPS.get(1)))
351+
.build();
352+
353+
354+
Map<String, KeysAndAttributes> keysAndAttributesMap = new HashMap<>();
355+
keysAndAttributesMap.put(TABLE_NAME, keysAndAttributes1);
356+
357+
BatchGetItemResponse fakeResponse =
358+
BatchGetItemResponse.builder()
359+
.unprocessedKeys(keysAndAttributesMap)
360+
.build();
361+
362+
BatchGetItemOperation operation = BatchGetItemOperation.create(emptyRequest());
363+
364+
BatchGetResultPage resultsPage = operation.transformResponse(fakeResponse, null);
365+
366+
List<Key> fakeItemResults = resultsPage.unprocessedKeysForTable(fakeItemWithSortMappedTable);
367+
assertThat(fakeItemResults, empty());
368+
}
369+
299370
@Test
300371
public void transformResponse_multipleTables_multipleItems_extensionWithTransformation() {
301372
Map<String, List<Map<String, AttributeValue>>> page = new HashMap<>();

0 commit comments

Comments
 (0)