Skip to content

Missing support for ReturnValuesOnConditionCheckFailure #60

@vincent-ogury

Description

@vincent-ogury

Hi,

This option is excellent and reduce cost on a highly concurrent update environment.
https://aws.amazon.com/blogs/database/handle-conditional-write-errors-in-high-concurrency-scenarios-with-amazon-dynamodb/

Here an short exemple:

package main

import (
	"errors"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"

	"github.com/aws/aws-dax-go/dax"
)

func main() {
	daxUrl := "dax://DAX_URL_HERE"
	cfg := dax.DefaultConfig()
	cfg.HostPorts = []string{daxUrl}
	cfg.Region = "eu-west-1"
	cli, err := dax.New(cfg)
	if err != nil {
		log.Fatal(err)
	}

	_, err = cli.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String("odid-provider-pivot-devc"),
		Item: map[string]*dynamodb.AttributeValue{
			"_id":     {S: aws.String("test")},
			"test":    {S: aws.String("init")},
			"version": {N: aws.String("0")},
		},
	})
	if err != nil {
		log.Fatal(err)
	}

	item, err := cli.UpdateItem(&dynamodb.UpdateItemInput{
		ExpressionAttributeNames: map[string]*string{
			"#T": aws.String("test"),
			"#V": aws.String("version"),
		},
		ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
			":T":  {S: aws.String("ok")},
			":V":  {N: aws.String("1")},
			":VN": {N: aws.String("2")},
		},
		Key: map[string]*dynamodb.AttributeValue{
			"_id": {S: aws.String("test")},
		},
		ReturnValues:                        aws.String("ALL_NEW"),
		ReturnValuesOnConditionCheckFailure: aws.String("ALL_OLD"),
		TableName:                           aws.String("odid-provider-pivot-devc"),
		UpdateExpression:                    aws.String("SET #T=:T, #V=:VN"),
		ConditionExpression:                 aws.String("#V=:V"),
	})
	if err != nil {
		var cfeErr *dynamodb.ConditionalCheckFailedException
		if errors.As(err, &cfeErr) {
			log.Println("item", cfeErr.Item)
		}
		log.Fatal(err)
	}
	log.Println(item)
}

The ReturnValuesOnConditionCheckFailure is suppose in case of error to return the document present on dynamo. It's the case when we are using dynamo but not with this dax driver.

Here the difference when I use dynamo and dax in the output:

### DAX
➜  aws-dax-go git:(master) ✗ go run ./cmd/play
2024/10/11 15:00:50 item map[] <<<<<<<<<<<<<<<<< NOTHING HERE
2024/10/11 15:00:50 ConditionalCheckFailedException: The conditional request failed
{
  RespMetadata: {
    StatusCode: 400,
    RequestID: "963TTCKR0P0SJ91BL1CO4SB3P7VV4KQNSO5AEMVJF66Q9ASUAAJG"
  },
  Message_: "The conditional request failed"
}
exit status 1

### DYNAMO
➜  aws-dax-go git:(master) ✗ go run ./cmd/play2
2024/10/11 15:00:57 item map[_id:{ <<<<<<<<<<<<<<<<<<<<< EXISTING DOCUMENT HERE
  S: "test"
} test:{
  S: "init"
} version:{
  N: "0"
}]
2024/10/11 15:00:57 ConditionalCheckFailedException: The conditional request failed
{
  RespMetadata: {
    StatusCode: 400,
    RequestID: "H7JR8TK2M7J3NQKI4363IJ3KCBVV4KQNSO5AEMVJF66Q9ASUAAJG"
  },
  Item: {
    _id: {
      S: "test"
    },
    version: {
      N: "0"
    },
    test: {
      S: "init"
    }
  },
  Message_: "The conditional request failed"
}
exit status 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions