Skip to content

Commit

Permalink
Retry more Google API failures.
Browse files Browse the repository at this point in the history
The default retry policy (documented
[here](https://github.com/googleapis/gaxios/#request-options)) does not
retry POST requests. But most Google API calls use POST requests under
the covers, including read-only APIs like [Drive
Activity](https://developers.google.com/drive/activity/v2/reference/rest/v2/activity/query).
So we can also ask to retry POST requests.

We retain other aspects of the default policy, such as the number of
attempts (3) and the HTTP status codes to retry (100-109, 408, 429,
5xx). If a request succeeds on a retry, the failure is kept silent and
does not pollute the logs.

The main risk is that a POST method might mutate some state despite
returning a failure, and that inline retries might handle that
incorrectly or otherwise make things worse than retrying the full flow
from the ground up. This doesn't seem likely to be an issue with the
current set of API calls, but if desired, we could narrow this change to
specific known-safe requests.

See deathandmayhem#2160
See deathandmayhem#2161
  • Loading branch information
jpd236 committed Jun 28, 2024
1 parent e2dd434 commit 2749f40
Show file tree
Hide file tree
Showing 3 changed files with 1,287 additions and 2,152 deletions.
27 changes: 24 additions & 3 deletions imports/server/googleClientRefresher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { people_v1 } from "@googleapis/people";
import { people } from "@googleapis/people";
import type { script_v1 } from "@googleapis/script";
import { script } from "@googleapis/script";
import type { RetryConfig } from "gaxios";
import type { SettingType } from "../lib/models/Settings";
import Settings from "../lib/models/Settings";

Expand All @@ -32,12 +33,19 @@ class GoogleClientRefresher {

private oauthCredentialCursor: Mongo.Cursor<SettingType>;

private retryConfig: RetryConfig;

constructor() {
this.drive = undefined;
this.oauthClient = undefined;
this.oauthConfig = undefined;
this.oauthRefreshToken = undefined;

this.retryConfig = {
// Retry POST failures as well, since most APIs use POST requests under the covers.
httpMethodsToRetry: ["GET", "PUT", "HEAD", "OPTIONS", "DELETE", "POST"],
};

// Watch for config changes, and refresh the gdrive instance if anything changes
this.oauthConfigCursor = ServiceConfiguration.configurations.find({
service: "google",
Expand Down Expand Up @@ -97,13 +105,26 @@ class GoogleClientRefresher {
});

// Construct the clients, using that OAuth2 client.
this.drive = drive({ version: "v3", auth: this.oauthClient });
this.drive = drive({
version: "v3",
auth: this.oauthClient,
retryConfig: this.retryConfig,
});
this.driveactivity = driveactivity({
version: "v2",
auth: this.oauthClient,
retryConfig: this.retryConfig,
});
this.script = script({
version: "v1",
auth: this.oauthClient,
retryConfig: this.retryConfig,
});
this.people = people({
version: "v1",
auth: this.oauthClient,
retryConfig: this.retryConfig,
});
this.script = script({ version: "v1", auth: this.oauthClient });
this.people = people({ version: "v1", auth: this.oauthClient });
}
}

Expand Down
Loading

0 comments on commit 2749f40

Please sign in to comment.