Skip to content

Commit a418f4e

Browse files
Merge pull request #4875 from linuxfoundation/unicron-fix-backfill-script
Unicron fix backfill script
2 parents 95d3c0b + 967dfe9 commit a418f4e

File tree

2 files changed

+56
-14
lines changed

2 files changed

+56
-14
lines changed

cla-backend-go/cmd/signatures_timestamp_backfill/main.go

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -408,17 +408,15 @@ func firstPassScanAndUpdate(
408408

409409
updateExpr := setPrefix
410410
vals := map[string]*dynamodb.AttributeValue{":empty": {S: aws.String("")}}
411-
names := map[string]*string{
412-
"#date_created": aws.String(attrDateCreated),
413-
"#date_modified": aws.String(attrDateModified),
414-
}
411+
names := map[string]*string{}
415412
first := true
416413
if setCreated {
417414
if !first {
418415
updateExpr += commaSep
419416
}
420417
updateExpr += exprSetDateCreated
421418
vals[":date_created"] = &dynamodb.AttributeValue{S: aws.String(finalC)}
419+
names["#date_created"] = aws.String(attrDateCreated)
422420
first = false
423421
}
424422
if setModified {
@@ -427,6 +425,7 @@ func firstPassScanAndUpdate(
427425
}
428426
updateExpr += exprSetDateModified
429427
vals[":date_modified"] = &dynamodb.AttributeValue{S: aws.String(finalM)}
428+
names["#date_modified"] = aws.String(attrDateModified)
430429
}
431430

432431
if debug {
@@ -450,7 +449,8 @@ func firstPassScanAndUpdate(
450449
}
451450

452451
// Build CLI (always emitted in dry-run; emitted on failure in live-run)
453-
cmd := buildAwsCliUpdate(region, stage, tableName, sig.SignatureID, updateExpr, names, vals, condAnyMissing)
452+
condExpr := buildConditionExpression(names)
453+
cmd := buildAwsCliUpdate(region, stage, tableName, sig.SignatureID, updateExpr, names, vals, condExpr)
454454
dbg(" CLI: %s", cmd)
455455

456456
if dryRun {
@@ -468,7 +468,7 @@ func firstPassScanAndUpdate(
468468
UpdateExpression: aws.String(updateExpr),
469469
ExpressionAttributeNames: names,
470470
ExpressionAttributeValues: vals,
471-
ConditionExpression: aws.String(condAnyMissing),
471+
ConditionExpression: aws.String(condExpr),
472472
})
473473
if uerr != nil {
474474
log.Printf("Update failed %s: %v", sig.SignatureID, uerr)
@@ -604,12 +604,7 @@ func snowflakeFix(
604604

605605
updateExpr := setPrefix
606606
vals := map[string]*dynamodb.AttributeValue{":empty": {S: aws.String("")}}
607-
names := map[string]*string{
608-
"#date_created": aws.String(attrDateCreated),
609-
"#date_modified": aws.String(attrDateModified),
610-
"#approx_date_created": aws.String(attrApproxDateCreated),
611-
"#approx_date_modified": aws.String(attrApproxDateModified),
612-
}
607+
names := map[string]*string{}
613608
first := true
614609
if setCreated {
615610
if !first {
@@ -619,9 +614,11 @@ func snowflakeFix(
619614
if srcC == labelFivetranSynced {
620615
updateExpr += exprSetApproxDateCreated
621616
vals[":approx_date_created"] = &dynamodb.AttributeValue{S: aws.String(finalC)}
617+
names["#approx_date_created"] = aws.String(attrApproxDateCreated)
622618
} else {
623619
updateExpr += exprSetDateCreated
624620
vals[":date_created"] = &dynamodb.AttributeValue{S: aws.String(finalC)}
621+
names["#date_created"] = aws.String(attrDateCreated)
625622
}
626623
first = false
627624
}
@@ -633,9 +630,11 @@ func snowflakeFix(
633630
if srcM == labelFivetranSynced {
634631
updateExpr += exprSetApproxDateModified
635632
vals[":approx_date_modified"] = &dynamodb.AttributeValue{S: aws.String(finalM)}
633+
names["#approx_date_modified"] = aws.String(attrApproxDateModified)
636634
} else {
637635
updateExpr += exprSetDateModified
638636
vals[":date_modified"] = &dynamodb.AttributeValue{S: aws.String(finalM)}
637+
names["#date_modified"] = aws.String(attrDateModified)
639638
}
640639
}
641640

@@ -659,7 +658,9 @@ func snowflakeFix(
659658
}
660659
}
661660

662-
cmd := buildAwsCliUpdate(region, stage, tableName, id, updateExpr, names, vals, condAnyMissing)
661+
// Build condition expression with names that are actually defined
662+
condExpr := buildConditionExpression(names)
663+
cmd := buildAwsCliUpdate(region, stage, tableName, id, updateExpr, names, vals, condExpr)
663664
dbg(" SF CLI: %s", cmd)
664665

665666
if dryRun {
@@ -672,13 +673,16 @@ func snowflakeFix(
672673
continue
673674
}
674675

676+
// Build condition expression with names that are actually defined
677+
condExpr = buildConditionExpression(names)
678+
675679
_, uerr := ddb.UpdateItem(&dynamodb.UpdateItemInput{
676680
TableName: aws.String(tableName),
677681
Key: map[string]*dynamodb.AttributeValue{"signature_id": {S: aws.String(id)}},
678682
UpdateExpression: aws.String(updateExpr),
679683
ExpressionAttributeNames: names,
680684
ExpressionAttributeValues: vals,
681-
ConditionExpression: aws.String(condAnyMissing),
685+
ConditionExpression: aws.String(condExpr),
682686
})
683687
if uerr != nil {
684688
log.Printf("Update failed (SF) %s: %v", id, uerr)
@@ -1058,6 +1062,39 @@ func parseSnowflakeCSV(b []byte) map[string]string {
10581062
return res
10591063
}
10601064

1065+
// buildConditionExpression builds a condition expression using only the attribute names
1066+
// that are actually defined in the names map to avoid DynamoDB validation errors
1067+
func buildConditionExpression(names map[string]*string) string {
1068+
var conditions []string
1069+
1070+
// Check for regular date_created field
1071+
if _, hasDateCreated := names["#date_created"]; hasDateCreated {
1072+
conditions = append(conditions, "attribute_not_exists(#date_created) OR #date_created = :empty")
1073+
}
1074+
1075+
// Check for regular date_modified field
1076+
if _, hasDateModified := names["#date_modified"]; hasDateModified {
1077+
conditions = append(conditions, "attribute_not_exists(#date_modified) OR #date_modified = :empty")
1078+
}
1079+
1080+
// Check for approx_date_created field
1081+
if _, hasApproxDateCreated := names["#approx_date_created"]; hasApproxDateCreated {
1082+
conditions = append(conditions, "attribute_not_exists(#approx_date_created) OR #approx_date_created = :empty")
1083+
}
1084+
1085+
// Check for approx_date_modified field
1086+
if _, hasApproxDateModified := names["#approx_date_modified"]; hasApproxDateModified {
1087+
conditions = append(conditions, "attribute_not_exists(#approx_date_modified) OR #approx_date_modified = :empty")
1088+
}
1089+
1090+
// If no specific conditions, use a basic condition that should always allow updates
1091+
if len(conditions) == 0 {
1092+
return "attribute_exists(signature_id)"
1093+
}
1094+
1095+
return strings.Join(conditions, " OR ")
1096+
}
1097+
10611098
// -----------------------------------------------------------------------------
10621099
// AWS CLI builder & stats print
10631100
// -----------------------------------------------------------------------------

utils/signature_dates_stats.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
aws --profile lfproduct-prod dynamodb scan --table-name cla-prod-signatures --filter-expression "attribute_not_exists(#a) OR #a = :nullval" --expression-attribute-names '{"#a":"date_created"}' --expression-attribute-values '{":nullval":{"NULL":true}}' --select "COUNT"
3+
aws --profile lfproduct-prod dynamodb scan --table-name cla-prod-signatures --filter-expression "attribute_exists(#a)" --expression-attribute-names '{"#a":"approx_date_created"}' --select "COUNT"
4+
aws --profile lfproduct-prod dynamodb scan --table-name cla-prod-signatures --filter-expression "attribute_not_exists(#a) OR #a = :nullval" --expression-attribute-names '{"#a":"date_modified"}' --expression-attribute-values '{":nullval":{"NULL":true}}' --select "COUNT"
5+
aws --profile lfproduct-prod dynamodb scan --table-name cla-prod-signatures --filter-expression "attribute_exists(#a)" --expression-attribute-names '{"#a":"approx_date_modified"}' --select "COUNT"

0 commit comments

Comments
 (0)