Skip to content

Commit 3d505a6

Browse files
committed
porting version from Integer to Long, removing refactoring
1 parent e8a6075 commit 3d505a6

File tree

6 files changed

+109
-171
lines changed

6 files changed

+109
-171
lines changed

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,8 @@
679679
<includeModule>polly</includeModule>
680680
</includeModules>
681681
<excludes>
682+
<exclude>software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbVersionAttribute#incrementBy()</exclude>
683+
<exclude>software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbVersionAttribute#startAt()</exclude>
682684
<exclude>*.internal.*</exclude>
683685
<exclude>software.amazon.awssdk.thirdparty.*</exclude>
684686
<exclude>software.amazon.awssdk.regions.*</exclude>

services-custom/dynamodb-enhanced/pom.xml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,6 @@
7676
</archive>
7777
</configuration>
7878
</plugin>
79-
<plugin>
80-
<groupId>com.github.siom79.japicmp</groupId>
81-
<artifactId>japicmp-maven-plugin</artifactId>
82-
<version>${japicmp-maven-plugin.version}</version>
83-
<configuration>
84-
<parameter>
85-
<excludes>
86-
<!-- japicmp flagging these incorrectly as a breaking change -->
87-
<exclude>software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbVersionAttribute#incrementBy()</exclude>
88-
<exclude>software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbVersionAttribute#startAt()</exclude>
89-
</excludes>
90-
</parameter>
91-
</configuration>
92-
</plugin>
9379
</plugins>
9480
<pluginManagement>
9581
<plugins>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ public String toString() {
321321
}
322322

323323
/**
324-
* A builder for {@link Expression}v
324+
* A builder for {@link Expression}
325325
*/
326326
@NotThreadSafe
327327
public static final class Builder {

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.java

Lines changed: 73 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTag;
3535
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableMetadata;
3636
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
37-
import software.amazon.awssdk.utils.Pair;
37+
import software.amazon.awssdk.utils.Validate;
3838

3939
/**
4040
* This extension implements optimistic locking on record writes by means of a 'record version number' that is used
@@ -61,20 +61,19 @@ public final class VersionedRecordExtension implements DynamoDbEnhancedClientExt
6161
private static final Function<String, String> VERSIONED_RECORD_EXPRESSION_VALUE_KEY_MAPPER = key -> ":old_" + key + "_value";
6262
private static final String CUSTOM_METADATA_KEY = "VersionedRecordExtension:VersionAttribute";
6363
private static final VersionAttribute VERSION_ATTRIBUTE = new VersionAttribute();
64-
private static final AttributeValue DEFAULT_VALUE = AttributeValue.fromNul(Boolean.TRUE);
65-
66-
private final int startAt;
67-
private final int incrementBy;
68-
69-
/**
70-
* Creates a new {@link VersionedRecordExtension} using the supplied starting and incrementing value.
71-
*
72-
* @param startAt the value used to compare if a record is the initial version of a record.
73-
* @param incrementBy the amount to increment the version by with each subsequent update.
74-
*/
75-
private VersionedRecordExtension(int startAt, int incrementBy) {
76-
this.startAt = startAt;
77-
this.incrementBy = incrementBy;
64+
65+
private final long startAt;
66+
private final long incrementBy;
67+
68+
private VersionedRecordExtension(Long startAt, Long incrementBy) {
69+
Validate.isNotNegativeOrNull(startAt, "startAt");
70+
71+
if (incrementBy != null && incrementBy < 1) {
72+
throw new IllegalArgumentException("IncrementBy must be greater than 0.");
73+
}
74+
75+
this.startAt = startAt != null ? startAt : 0L;
76+
this.incrementBy = incrementBy != null ? incrementBy : 1L;
7877
}
7978

8079
public static Builder builder() {
@@ -89,7 +88,7 @@ public static StaticAttributeTag versionAttribute() {
8988
return VERSION_ATTRIBUTE;
9089
}
9190

92-
public static StaticAttributeTag versionAttribute(Integer startAt, Integer incrementBy) {
91+
public static StaticAttributeTag versionAttribute(Long startAt, Long incrementBy) {
9392
return new VersionAttribute(startAt, incrementBy);
9493
}
9594
}
@@ -98,15 +97,15 @@ private static final class VersionAttribute implements StaticAttributeTag {
9897
private static final String START_AT_METADATA_KEY = "VersionedRecordExtension:StartAt";
9998
private static final String INCREMENT_BY_METADATA_KEY = "VersionedRecordExtension:IncrementBy";
10099

101-
private final Integer startAt;
102-
private final Integer incrementBy;
100+
private final Long startAt;
101+
private final Long incrementBy;
103102

104103
private VersionAttribute() {
105104
this.startAt = null;
106105
this.incrementBy = null;
107106
}
108107

109-
private VersionAttribute(Integer startAt, Integer incrementBy) {
108+
private VersionAttribute(Long startAt, Long incrementBy) {
110109
this.startAt = startAt;
111110
this.incrementBy = incrementBy;
112111
}
@@ -120,16 +119,13 @@ public Consumer<StaticTableMetadata.Builder> modifyMetadata(String attributeName
120119
"is supported.", attributeName, attributeValueType.name()));
121120
}
122121

123-
if (startAt != null && startAt < 0) {
124-
throw new IllegalArgumentException("StartAt cannot be negative.");
125-
}
122+
Validate.isNotNegativeOrNull(startAt, "startAt");
126123

127124
if (incrementBy != null && incrementBy < 1) {
128125
throw new IllegalArgumentException("IncrementBy must be greater than 0.");
129126
}
130127

131-
return metadata -> metadata
132-
.addCustomMetadataObject(CUSTOM_METADATA_KEY, attributeName)
128+
return metadata -> metadata.addCustomMetadataObject(CUSTOM_METADATA_KEY, attributeName)
133129
.addCustomMetadataObject(START_AT_METADATA_KEY, startAt)
134130
.addCustomMetadataObject(INCREMENT_BY_METADATA_KEY, incrementBy)
135131
.markAttributeAsKey(attributeName, attributeValueType);
@@ -145,109 +141,69 @@ public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite contex
145141
return WriteModification.builder().build();
146142
}
147143

148-
Pair<AttributeValue, Expression> updates = getRecordUpdates(versionAttributeKey.get(), context);
149-
150-
AttributeValue newVersionValue = updates.left();
151-
Expression condition = updates.right();
152-
153144
Map<String, AttributeValue> itemToTransform = new HashMap<>(context.items());
154-
itemToTransform.put(versionAttributeKey.get(), newVersionValue);
155-
156-
return WriteModification.builder()
157-
.transformedItem(Collections.unmodifiableMap(itemToTransform))
158-
.additionalConditionalExpression(condition)
159-
.build();
160-
}
161-
162-
private Pair<AttributeValue, Expression> getRecordUpdates(String versionAttributeKey,
163-
DynamoDbExtensionContext.BeforeWrite context) {
164-
Map<String, AttributeValue> itemToTransform = context.items();
165-
166-
// Default to NUL if not present to reduce additional checks further along
167-
AttributeValue existingVersionValue = itemToTransform.getOrDefault(versionAttributeKey, DEFAULT_VALUE);
168145

169-
if (isInitialVersion(existingVersionValue, context)) {
170-
return createInitialRecord(versionAttributeKey, context);
171-
}
172-
// Existing record, increment version
173-
return updateExistingRecord(versionAttributeKey, existingVersionValue, context);
174-
}
175-
176-
private boolean isInitialVersion(AttributeValue existingVersionValue, DynamoDbExtensionContext.BeforeWrite context) {
177-
Optional<Integer> versionStartAtFromAnnotation = context.tableMetadata()
178-
.customMetadataObject(VersionAttribute.START_AT_METADATA_KEY,
179-
Integer.class);
180-
181-
return isNullAttributeValue(existingVersionValue)
182-
|| (versionStartAtFromAnnotation.isPresent()
183-
&& getExistingVersion(existingVersionValue) == versionStartAtFromAnnotation.get())
184-
|| getExistingVersion(existingVersionValue) == this.startAt;
185-
}
186-
187-
private Pair<AttributeValue, Expression> createInitialRecord(String versionAttributeKey,
188-
DynamoDbExtensionContext.BeforeWrite context) {
189-
Optional<Integer> versionStartAtFromAnnotation = context.tableMetadata()
190-
.customMetadataObject(VersionAttribute.START_AT_METADATA_KEY,
191-
Integer.class);
192-
193-
AttributeValue newVersionValue = versionStartAtFromAnnotation.isPresent() ?
194-
incrementVersion(versionStartAtFromAnnotation.get(), context) :
195-
incrementVersion(this.startAt, context);
196-
197-
198-
String attributeKeyRef = keyRef(versionAttributeKey);
199-
200-
Expression condition = Expression.builder()
201-
// Check that the version does not exist before setting the initial value.
202-
.expression(String.format("attribute_not_exists(%s)", attributeKeyRef))
203-
.expressionNames(Collections.singletonMap(attributeKeyRef, versionAttributeKey))
204-
.build();
205-
206-
return Pair.of(newVersionValue, condition);
207-
}
208-
209-
private Pair<AttributeValue, Expression> updateExistingRecord(String versionAttributeKey,
210-
AttributeValue existingVersionValue,
211-
DynamoDbExtensionContext.BeforeWrite context) {
212-
int existingVersion = getExistingVersion(existingVersionValue);
213-
AttributeValue newVersionValue = incrementVersion(existingVersion, context);
214-
215-
String attributeKeyRef = keyRef(versionAttributeKey);
216-
String existingVersionValueKey = VERSIONED_RECORD_EXPRESSION_VALUE_KEY_MAPPER.apply(versionAttributeKey);
146+
String attributeKeyRef = keyRef(versionAttributeKey.get());
147+
AttributeValue newVersionValue;
148+
Expression condition;
149+
Optional<AttributeValue> existingVersionValue =
150+
Optional.ofNullable(itemToTransform.get(versionAttributeKey.get()));
151+
152+
Optional<Long> versionStartAtFromAnnotation = context.tableMetadata()
153+
.customMetadataObject(VersionAttribute.START_AT_METADATA_KEY,
154+
Long.class);
155+
156+
Optional<Long> versionIncrementByFromAnnotation = context.tableMetadata()
157+
.customMetadataObject(VersionAttribute.INCREMENT_BY_METADATA_KEY,
158+
Long.class);
159+
160+
if (!existingVersionValue.isPresent() || isNullAttributeValue(existingVersionValue.get()) ||
161+
(existingVersionValue.get().n() != null &&
162+
((versionStartAtFromAnnotation.isPresent() &&
163+
Long.parseLong(existingVersionValue.get().n()) == versionStartAtFromAnnotation.get()) ||
164+
Long.parseLong(existingVersionValue.get().n()) == this.startAt))) {
165+
166+
long startValue = versionStartAtFromAnnotation.orElse(this.startAt);
167+
long increment = versionIncrementByFromAnnotation.orElse(this.incrementBy);
168+
169+
newVersionValue = AttributeValue.builder().n(Long.toString(startValue + increment)).build();
170+
condition = Expression.builder()
171+
.expression(String.format("attribute_not_exists(%s)", attributeKeyRef))
172+
.expressionNames(Collections.singletonMap(attributeKeyRef, versionAttributeKey.get()))
173+
.build();
174+
} else {
175+
// Existing record, increment version
176+
if (existingVersionValue.get().n() == null) {
177+
// In this case a non-null version attribute is present, but it's not an N
178+
throw new IllegalArgumentException("Version attribute appears to be the wrong type. N is required.");
179+
}
217180

218-
Expression condition = Expression.builder()
219-
// Check that the version matches the existing value before setting the updated value.
220-
.expression(String.format("%s = %s", attributeKeyRef, existingVersionValueKey))
221-
.expressionNames(Collections.singletonMap(attributeKeyRef, versionAttributeKey))
222-
.expressionValues(Collections.singletonMap(existingVersionValueKey,
223-
existingVersionValue))
224-
.build();
181+
long existingVersion = Long.parseLong(existingVersionValue.get().n());
182+
String existingVersionValueKey = VERSIONED_RECORD_EXPRESSION_VALUE_KEY_MAPPER.apply(versionAttributeKey.get());
225183

226-
return Pair.of(newVersionValue, condition);
227-
}
184+
long increment = versionIncrementByFromAnnotation.orElse(this.incrementBy);
185+
newVersionValue = AttributeValue.builder().n(Long.toString(existingVersion + increment)).build();
228186

229-
private int getExistingVersion(AttributeValue existingVersionValue) {
230-
if (existingVersionValue.n() == null) {
231-
throw new IllegalArgumentException("Version attribute appears to be the wrong type. N is required.");
187+
condition = Expression.builder()
188+
.expression(String.format("%s = %s", attributeKeyRef, existingVersionValueKey))
189+
.expressionNames(Collections.singletonMap(attributeKeyRef, versionAttributeKey.get()))
190+
.expressionValues(Collections.singletonMap(existingVersionValueKey,
191+
existingVersionValue.get()))
192+
.build();
232193
}
233194

234-
return Integer.parseInt(existingVersionValue.n());
235-
}
195+
itemToTransform.put(versionAttributeKey.get(), newVersionValue);
236196

237-
private AttributeValue incrementVersion(int version, DynamoDbExtensionContext.BeforeWrite context) {
238-
Optional<Integer> versionIncrementByFromAnnotation = context.tableMetadata()
239-
.customMetadataObject(VersionAttribute.INCREMENT_BY_METADATA_KEY,
240-
Integer.class);
241-
if (versionIncrementByFromAnnotation.isPresent()) {
242-
return AttributeValue.fromN(Integer.toString(version + versionIncrementByFromAnnotation.get()));
243-
}
244-
return AttributeValue.fromN(Integer.toString(version + this.incrementBy));
197+
return WriteModification.builder()
198+
.transformedItem(Collections.unmodifiableMap(itemToTransform))
199+
.additionalConditionalExpression(condition)
200+
.build();
245201
}
246202

247203
@NotThreadSafe
248204
public static final class Builder {
249-
private int startAt = 0;
250-
private int incrementBy = 1;
205+
private Long startAt = 0L;
206+
private Long incrementBy = 1L;
251207

252208
private Builder() {
253209
}
@@ -259,10 +215,7 @@ private Builder() {
259215
* @param startAt
260216
* @return the builder instance
261217
*/
262-
public Builder startAt(int startAt) {
263-
if (startAt < 0) {
264-
throw new IllegalArgumentException("StartAt cannot be negative.");
265-
}
218+
public Builder startAt(Long startAt) {
266219
this.startAt = startAt;
267220
return this;
268221
}
@@ -274,10 +227,7 @@ public Builder startAt(int startAt) {
274227
* @param incrementBy
275228
* @return the builder instance
276229
*/
277-
public Builder incrementBy(int incrementBy) {
278-
if (incrementBy < 1) {
279-
throw new IllegalArgumentException("IncrementBy must be greater than 0.");
280-
}
230+
public Builder incrementBy(Long incrementBy) {
281231
this.incrementBy = incrementBy;
282232
return this;
283233
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/annotations/DynamoDbVersionAttribute.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@
3939
*
4040
* @return the starting value
4141
*/
42-
int startAt() default 0;
42+
long startAt() default 0;
4343

4444
/**
4545
* The amount to increment the version by with each update.
4646
* Default value - {@code 1}.
4747
*
4848
* @return the increment value
4949
*/
50-
int incrementBy() default 1;
50+
long incrementBy() default 1;
5151

5252
}

0 commit comments

Comments
 (0)