Repository navigation
fix(firestore): retry idempotent commits on DEADLINE_EXCEEDED - #15010
MarkDuckworth wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces idempotency tracking for Firestore write operations and document transforms to safely retry idempotent commits on DEADLINE_EXCEEDED. It defines which FieldValue operations are idempotent (such as server timestamps, deletes, array unions/removes, and min/max numeric transforms) and which are not (such as increments). UpdateBuilder uses this classification to determine if a write batch or commit request is fully idempotent, enabling retries on DEADLINE_EXCEEDED for non-transactional, idempotent commits. Comprehensive unit tests have been added to validate the idempotency classification and retry behavior. No review comments were provided, so there is no additional feedback to address.
Summary
Automatically enables
DEADLINE_EXCEEDEDretries on non-transactionalCommitrequests when all write operations in the commit are idempotent.Background
The generated GAPIC
FirestoreStubSettings(retry_policy_0) only retriesCommitRPCs onRESOURCE_EXHAUSTEDandUNAVAILABLEbecause aCommitRequestproto can contain non-idempotent operations (such asFieldValue.increment()orcreate()withexists: false). However, most standalone writes (docRef.set(),docRef.set(..., SetOptions.merge()),docRef.update()withoutincrementorupdateTimepreconditions,docRef.delete()without preconditions, andWriteBatches composed of those operations) are idempotent and safe to retry when an attempt times out withDEADLINE_EXCEEDED.Changes
FieldValue: Added package-privateabstract boolean isIdempotent()so all current and futureFieldValueimplementations explicitly declare idempotency (falseforFieldValue.increment(),truefordelete(),serverTimestamp(),arrayUnion(),arrayRemove(),minimum(),maximum()).DocumentTransform: Tracks idempotency across top-level and nested field transforms.UpdateBuilder:Commitbatch is idempotent based onDocumentTransform.isIdempotent(), write preconditions (excludingexists: false,updateTime, anddeletewithexists: true), and a fail-closedFieldTransformcheck.GrpcCallContextwithretryableCodes = [RESOURCE_EXHAUSTED, UNAVAILABLE, DEADLINE_EXCEEDED]for idempotent non-transactional commits.WriteBatchTest: Added unit tests for idempotency classification across write/precondition/transform combinations and end-to-end gRPC retry verification onDEADLINE_EXCEEDED.