|
1 | 1 | package utils |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "errors" |
4 | 5 | "fmt" |
5 | 6 |
|
6 | 7 | "github.com/aws/aws-sdk-go/aws" |
| 8 | + "github.com/aws/aws-sdk-go/aws/awserr" |
7 | 9 | "github.com/aws/aws-sdk-go/aws/session" |
8 | 10 | "github.com/aws/aws-sdk-go/service/dynamodb" |
9 | 11 | "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" |
@@ -50,6 +52,7 @@ type ContractSizeEntry struct { |
50 | 52 | KeyCount uint64 `json:"key_count"` |
51 | 53 | } |
52 | 54 |
|
| 55 | +// PrefixSize is a helper structure kept for completeness (unused here) |
53 | 56 | type PrefixSize struct { |
54 | 57 | KeySize uint64 `json:"key_size"` |
55 | 58 | ValueSize uint64 `json:"value_size"` |
@@ -88,3 +91,32 @@ func (d *DynamoDBClient) ExportMultipleAnalyses(analyses []*StateSizeAnalysis) e |
88 | 91 | } |
89 | 92 | return nil |
90 | 93 | } |
| 94 | + |
| 95 | +// UpdateLatestHeightIfGreater keeps exactly one item in the metadata table using the schema: |
| 96 | +// Partition key: keyname (S). Numeric attribute: height (N) stores the latest height. |
| 97 | +// Upserts the row keyname = "latest_height" and sets height = :h only if missing or lower. |
| 98 | +func (d *DynamoDBClient) UpdateLatestHeightIfGreater(metadataTable string, height int64) (bool, error) { |
| 99 | + input := &dynamodb.UpdateItemInput{ |
| 100 | + TableName: aws.String(metadataTable), |
| 101 | + Key: map[string]*dynamodb.AttributeValue{ |
| 102 | + "keyname": {S: aws.String("latest_height")}, |
| 103 | + }, |
| 104 | + UpdateExpression: aws.String("SET height = :h"), |
| 105 | + ConditionExpression: aws.String("attribute_not_exists(height) OR height < :h"), |
| 106 | + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ |
| 107 | + ":h": {N: aws.String(fmt.Sprintf("%d", height))}, |
| 108 | + }, |
| 109 | + ReturnValues: aws.String("NONE"), |
| 110 | + } |
| 111 | + |
| 112 | + _, err := d.client.UpdateItem(input) |
| 113 | + if err != nil { |
| 114 | + var aerr awserr.Error |
| 115 | + if errors.As(err, &aerr) && aerr.Code() == dynamodb.ErrCodeConditionalCheckFailedException { |
| 116 | + return false, nil |
| 117 | + } |
| 118 | + return false, fmt.Errorf("failed to update latest height: %w", err) |
| 119 | + } |
| 120 | + fmt.Printf("Updated Dynamodb with latest height %d\n", height) |
| 121 | + return true, nil |
| 122 | +} |
0 commit comments