diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 1b9ec7323130..877cdca86cb3 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -16,6 +16,8 @@ name: 'Index' base_url: projects/{{project}}/databases/{{database}}/collectionGroups/{{collection}}/indexes self_link: '{{name}}' immutable: true +error_retry_predicates: + ["transport_tpg.FirestoreIndex409CrossTransactionContetion"] description: | Cloud Firestore indexes enable simple and complex queries against documents in a database. This resource manages composite indexes and not single diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates.go b/mmv1/third_party/terraform/transport/error_retry_predicates.go index d7c21e6fef94..c37cce72c484 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates.go @@ -330,6 +330,16 @@ func FirestoreField409RetryUnderlyingDataChanged(err error) (bool, string) { return false, "" } +// relevant for firestore in datastore mode +func FirestoreIndex409CrossTransactionContetion(err error) (bool, string) { + if gerr, ok := err.(*googleapi.Error); ok { + if gerr.Code == 409 && strings.Contains(gerr.Body, "Aborted due to cross-transaction contention") { + return true, "aborted due to cross-transaction contention - retrying" + } + } + return false, "" +} + func IapClient409Operation(err error) (bool, string) { if gerr, ok := err.(*googleapi.Error); ok { if gerr.Code == 409 && strings.Contains(strings.ToLower(gerr.Body), "operation was aborted") { diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go index a5f9b61e044a..317a7b0da9e9 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go @@ -181,3 +181,14 @@ func TestFirestoreField409_retryUnderlyingDataChanged(t *testing.T) { t.Errorf("Error not detected as retryable") } } + +func TestFirestoreIndex409_crossTransactionContetion(t *testing.T) { + err := googleapi.Error{ + Code: 409, + Body: "Aborted due to cross-transaction contention", + } + isRetryable, _ := FirestoreIndex409CrossTransactionContetion(&err) + if !isRetryable { + t.Errorf("Error not detected as retryable") + } +}