Skip to content

Commit 30c2b72

Browse files
committed
fix #1200
1 parent c96c0ad commit 30c2b72

File tree

4 files changed

+49
-19
lines changed

4 files changed

+49
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package software.amazon.lambda.powertools.idempotency.exceptions;
2+
3+
/**
4+
* Exception that occurs when the Idepmpotency Key is null or could not be found with the provided JMESPath
5+
*/
6+
public class NullIdempotencyKeyException extends Exception {
7+
private static final long serialVersionUID = 5115004524004542891L;
8+
9+
public NullIdempotencyKeyException(String message) {
10+
super(message);
11+
}
12+
}

powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ private Object processIdempotency() throws Throwable {
8484
persistenceStore.saveInProgress(data, Instant.now(), getRemainingTimeInMillis());
8585
} catch (IdempotencyItemAlreadyExistsException iaee) {
8686
DataRecord record = getIdempotencyRecord();
87-
return handleForStatus(record);
87+
if (record != null) {
88+
return handleForStatus(record);
89+
}
8890
} catch (IdempotencyKeyException ike) {
8991
throw ike;
9092
} catch (Exception e) {
@@ -111,7 +113,7 @@ private OptionalInt getRemainingTimeInMillis() {
111113
/**
112114
* Retrieve the idempotency record from the persistence layer.
113115
*
114-
* @return the record if available
116+
* @return the record if available, potentially null
115117
*/
116118
private DataRecord getIdempotencyRecord() {
117119
try {

powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java

+30-14
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import org.slf4j.LoggerFactory;
2222
import software.amazon.awssdk.utils.StringUtils;
2323
import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
24-
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
25-
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
26-
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException;
27-
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException;
24+
import software.amazon.lambda.powertools.idempotency.exceptions.*;
2825
import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache;
2926
import software.amazon.lambda.powertools.utilities.JsonConfig;
3027

@@ -34,12 +31,8 @@
3431
import java.security.NoSuchAlgorithmException;
3532
import java.time.Instant;
3633
import java.time.temporal.ChronoUnit;
37-
import java.util.Map;
38-
import java.util.OptionalLong;
39-
import java.util.OptionalInt;
34+
import java.util.*;
4035
import java.util.stream.Stream;
41-
import java.util.Spliterators;
42-
import java.util.Spliterator;
4336
import java.util.stream.StreamSupport;
4437

4538
import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
@@ -130,6 +123,9 @@ public void saveSuccess(JsonNode data, Object result, Instant now) {
130123
} catch (JsonProcessingException e) {
131124
// TODO : throw ?
132125
throw new RuntimeException("Error while serializing the response", e);
126+
} catch (NullIdempotencyKeyException e) {
127+
// missing idempotency key => non-idempotent transaction, we do not store the data, simply return
128+
return;
133129
}
134130
}
135131

@@ -140,7 +136,13 @@ public void saveSuccess(JsonNode data, Object result, Instant now) {
140136
* @param now
141137
*/
142138
public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTimeInMs) throws IdempotencyItemAlreadyExistsException {
143-
String idempotencyKey = getHashedIdempotencyKey(data);
139+
String idempotencyKey;
140+
try {
141+
idempotencyKey = getHashedIdempotencyKey(data);
142+
} catch (NullIdempotencyKeyException e) {
143+
// missing idempotency key => non-idempotent transaction, we do not store the data, simply return
144+
return;
145+
}
144146

145147
if (retrieveFromCache(idempotencyKey, now) != null) {
146148
throw new IdempotencyItemAlreadyExistsException();
@@ -170,7 +172,13 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime
170172
* @param throwable The throwable thrown by the function
171173
*/
172174
public void deleteRecord(JsonNode data, Throwable throwable) {
173-
String idemPotencyKey = getHashedIdempotencyKey(data);
175+
String idemPotencyKey;
176+
try {
177+
idemPotencyKey = getHashedIdempotencyKey(data);
178+
} catch (NullIdempotencyKeyException e) {
179+
// missing idempotency key => non-idempotent transaction, we do not delete the data, simply return
180+
return;
181+
}
174182

175183
LOG.debug("Function raised an exception {}. " +
176184
"Clearing in progress record in persistence store for idempotency key: {}",
@@ -190,7 +198,13 @@ public void deleteRecord(JsonNode data, Throwable throwable) {
190198
* @throws IdempotencyItemNotFoundException Exception thrown if no record exists in persistence store with the idempotency key
191199
*/
192200
public DataRecord getRecord(JsonNode data, Instant now) throws IdempotencyValidationException, IdempotencyItemNotFoundException {
193-
String idemPotencyKey = getHashedIdempotencyKey(data);
201+
String idemPotencyKey;
202+
try {
203+
idemPotencyKey = getHashedIdempotencyKey(data);
204+
} catch (NullIdempotencyKeyException e) {
205+
// missing idempotency key => non-idempotent transaction, we do not get the data, simply return nothing
206+
return null;
207+
}
194208

195209
DataRecord cachedRecord = retrieveFromCache(idemPotencyKey, now);
196210
if (cachedRecord != null) {
@@ -211,7 +225,7 @@ public DataRecord getRecord(JsonNode data, Instant now) throws IdempotencyValida
211225
* @param data incoming data
212226
* @return Hashed representation of the data extracted by the jmespath expression
213227
*/
214-
private String getHashedIdempotencyKey(JsonNode data) {
228+
private String getHashedIdempotencyKey(JsonNode data) throws NullIdempotencyKeyException {
215229
JsonNode node = data;
216230

217231
if (eventKeyJMESPath != null) {
@@ -221,8 +235,10 @@ private String getHashedIdempotencyKey(JsonNode data) {
221235
if (isMissingIdemPotencyKey(node)) {
222236
if (throwOnNoIdempotencyKey) {
223237
throw new IdempotencyKeyException("No data found to create a hashed idempotency key");
238+
} else {
239+
LOG.warn("No data found to create a hashed idempotency key. JMESPath: {}", eventKeyJMESPath);
240+
throw new NullIdempotencyKeyException("No data found to create a hashed idempotency key");
224241
}
225-
LOG.warn("No data found to create a hashed idempotency key. JMESPath: {}", eventKeyJMESPath);
226242
}
227243

228244
String hash = generateHash(node);

powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,15 @@ public void saveInProgress_jmespath_NotFound_shouldThrowException() {
143143
}
144144

145145
@Test
146-
public void saveInProgress_jmespath_NotFound_shouldNotThrowException() {
146+
public void saveInProgress_jmespath_NotFound_shouldNotPersist() {
147147
APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json");
148148
persistenceStore.configure(IdempotencyConfig.builder()
149149
.withEventKeyJMESPath("unavailable")
150150
.build(), "");
151151
Instant now = Instant.now();
152152
persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty());
153-
assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS);
154-
assertThat(status).isEqualTo(1);
153+
assertThat(dr).isNull();
154+
assertThat(status).isEqualTo(-1);
155155
}
156156

157157
@Test

0 commit comments

Comments
 (0)