Skip to content

DynamoDB Enhanced Client Custom Versioning startAt parameter does not appear to work when setting to 0 #6435

@balverez

Description

@balverez

Describe the bug

Hey team, I am on a team that has many legacy DDB tables utilizing the previous DDB SDK. We are planning out the migration to SDK v2 and in exploring the SDK differences I discovered a particularly sharp pain point in the handling of versioning for optimistic locking.

I was excited for the custom versioning change released and documented in #6019 but it does not appear to be working as expected.

Our tables (whose DALs use SDK v1) have millions of entries with Number version fields initialized to 0 by the @DynamoDBVersionAttribute optimistic locking annotation of the first SDK. Currently, the startAt parameter set to 0 still cannot process item updates when version is set to 0, throwing a ConditionalCheckException.

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

I've been testing the new custom versioning changes for the DynamoDbVersionAttribute annotation and VersionedRecordExtension extension and the startAt parameter does not appear to be working as expected, specifically with the value 0. I can set a different non-negative positive integer and it works as expected, but any time I call PutItem with a new data model and have startAt set to 0, the version number is persisted as 1. If I set it to any positive integer n, it is persisted as n + 1 on a PutItem call.

Given the startAt parameter is defaulting the 0 for the VersionedRecordExtension, the expectation is that any items with 0 as a version value will be successfully updated on an UpdateItem call and have version incremented to whatever the incrementBy value is set to.

Current Behavior

The issue comes in when the version property is set to 0. If I create a table entry and modify it to have version equal to 0 prior to a programmatic GetItem + UpdateItem call, the UpdateItem call on the model fails with a conditional check exception, even when retrieving the version value and parsing it to be 0. This does not appear to be the intended behavior given the discussion in the #6019 PR.

Reproduction Steps

Create any table instance with a version attribute using the @DynamoDbVersionAttribute annotation for optimistic locking. When using PutItem to create the item in a table, note that version is set to startAt + 1. If the version is set to 0 manually, the version can be parsed and fetched by a GetItem call, but an UpdateItem operation on the entry will fail with a ConditionalCheck exception.

Sample Data Model version attribute

import software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbVersionAttribute;
...
    @Getter(onMethod_ = {
            @DynamoDbAttribute(Fields.version),
            @DynamoDbVersionAttribute(startAt = 0)
    })
    private Long version;

Sample EnhancedClient Configuration

        ClientOverrideConfiguration clientOverrideConfiguration = ClientOverrideConfiguration
                .builder()
                .apiCallAttemptTimeout(CALL_TIME_OUT)
                .apiCallTimeout(REQUEST_TIME_OUT)
                .retryStrategy(RETRY_STRATEGY)
                .build();

        client = DynamoDbClient
                .builder()
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_WEST_2)
                .overrideConfiguration(clientOverrideConfiguration)
                .build();

        enhancedClient = DynamoDbEnhancedClient
                .builder()
                .dynamoDbClient(client)
                .extensions(
                        AutoGeneratedTimestampRecordExtension.create(),
                        VersionedRecordExtension
                                .builder()
                                .startAt(0L)
                                .incrementBy(1L)
                                .build())
                .build();

Possible Solution

No response

Additional Information/Context

No response

AWS Java SDK version used

2

JDK version used

JDK 17

Operating System and version

macOS 15.6.1

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions