Skip to content

fix(firestore): retry transient connection errors in streaming RPCs#14635

Draft
bhshkh wants to merge 1 commit into
googleapis:mainfrom
bhshkh:fs-fix-transient-errors-cider
Draft

fix(firestore): retry transient connection errors in streaming RPCs#14635
bhshkh wants to merge 1 commit into
googleapis:mainfrom
bhshkh:fs-fix-transient-errors-cider

Conversation

@bhshkh
Copy link
Copy Markdown
Contributor

@bhshkh bhshkh commented May 22, 2026

No description provided.

@product-auto-label product-auto-label Bot added the api: firestore Issues related to the Firestore API. label May 22, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a retry mechanism with exponential backoff for the getAll method in the Firestore client, along with a new isRetryableError helper function to identify transient network and gRPC errors. Feedback identifies a compilation error where the err variable is used without declaration and suggests expanding the retry logic to include the codes.ResourceExhausted status code.

Comment thread firestore/client.go
Comment on lines +328 to +338
var backoff gax.Backoff = gax.Backoff{
Initial: 100 * time.Millisecond,
Max: 60000 * time.Millisecond,
Multiplier: 1.30,
}

// Read and remember all results from the stream.
var resps []*pb.BatchGetDocumentsResponse
for {
resp, err := streamClient.Recv()
if err == io.EOF {
break
}
if err != nil {
return nil, err
var streamClient interface {
Recv() (*pb.BatchGetDocumentsResponse, error)
}
resps = append(resps, resp)
}

// Results may arrive out of order. Put each at the right indices.
docs := make([]*DocumentSnapshot, len(docNames))
for _, resp := range resps {
var (
indices []int
doc *pb.Document
err error
)
switch r := resp.Result.(type) {
case *pb.BatchGetDocumentsResponse_Found:
indices = docIndices[r.Found.Name]
doc = r.Found
case *pb.BatchGetDocumentsResponse_Missing:
indices = docIndices[r.Missing]
doc = nil
default:
return nil, errors.New("firestore: unknown BatchGetDocumentsResponse result type")
}
for _, index := range indices {
if docs[index] != nil {
return nil, fmt.Errorf("firestore: %q seen twice", docRefs[index].Path)
streamClient, err = c.c.BatchGetDocuments(batchGetDocsCtx, req)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The variable err is used in the assignment on line 338 and later checked on line 389, but it is never declared in this scope. In the previous version of the code, it was declared using := on line 327. Since streamClient is now declared as an interface type at line 335, you must explicitly declare err before the loop or within the loop before its first use.

	var err error
	var backoff gax.Backoff = gax.Backoff{
		Initial:    100 * time.Millisecond,
		Max:        60000 * time.Millisecond,
		Multiplier: 1.30,
	}

	for {
		var streamClient interface {
			Recv() (*pb.BatchGetDocumentsResponse, error)
		}
		streamClient, err = c.c.BatchGetDocuments(batchGetDocsCtx, req)

Comment thread firestore/client.go
Comment on lines +416 to +418
if st, ok := status.FromError(err); ok {
return st.Code() == codes.Unavailable
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider also retrying on codes.ResourceExhausted if the intent is to handle transient connection and capacity issues. According to general guidelines, retrying ResourceExhausted is acceptable, though often done without backoff if shifting to a different replica. Given the exponential backoff here, it would be a safe addition.

References
  1. When handling a ResourceExhausted error by forwarding the request to a different replica, it is acceptable to retry immediately without a delay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: firestore Issues related to the Firestore API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant