Override Retry, Backoff, and Idempotency Policies
When it is safe to do so, the library automatically retries requests that fail due to a transient error. The library then uses exponential backoff to backoff before trying again. Which operations are considered safe to retry, which errors are treated as transient failures, the details of the exponential backoff algorithm, and for how long the library retries are all configurable via policies.
This document provides examples showing how to override the default policies.
The policies can be set when the *Connection
object is created. The library provides default policies for any policy that is not set. The application can also override some (or all) policies when the *Client
object is created. This can be useful if multiple *Client
objects share the same *Connection
object, but you want different retry behavior in some of the clients. Finally, the application can override some retry policies when calling a specific member function.
The library uses three different options to control the retry loop. The options have per-client names.
Configuring the transient errors and retry duration
The *RetryPolicyOption
controls:
- Which errors are to be treated as transient errors.
- How long the library will keep retrying transient errors.
You can provide your own class for this option. The library also provides two built-in policies:
*LimitedErrorCountRetryPolicy
: stops retrying after a specified number of transient errors.*LimitedTimeRetryPolicy
: stops retrying after a specified time.
Note that a library may have more than one version of these classes. Their name match the *Client
and *Connection
object they are intended to be used with. Some *Client
objects treat different error codes as transient errors. In most cases, only kUnavailable is treated as a transient error.
Controlling the backoff algorithm
The *BackoffPolicyOption
controls how long the client library will wait before retrying a request that failed with a transient error. You can provide your own class for this option.
The only built-in backoff policy is ExponentialBackoffPolicy
. This class implements a truncated exponential backoff algorithm, with jitter. In summary, it doubles the current backoff time after each failure. The actual backoff time for an RPC is chosen at random, but never exceeds the current backoff. The current backoff is doubled after each failure, but never exceeds (or is "truncated") if it reaches a prescribed maximum.
Controlling which operations are retryable
The *IdempotencyPolicyOption
controls which requests are retryable, as some requests are never safe to retry.
Only one built-in idempotency policy is provided by the library. The name matches the name of the client it is intended for. For example, FooBarClient
will use FooBarIdempotencyPolicy
. This policy is very conservative.
Example
For example, this will override the retry policies for compute_accelerator_types_v1::AcceleratorTypesClient
:
auto options =
google::cloud::Options{}
.set<google::cloud::compute_accelerator_types_v1::
AcceleratorTypesConnectionIdempotencyPolicyOption>(
CustomIdempotencyPolicy().clone())
.set<google::cloud::compute_accelerator_types_v1::
AcceleratorTypesRetryPolicyOption>(
google::cloud::compute_accelerator_types_v1::
AcceleratorTypesLimitedErrorCountRetryPolicy(3)
.clone())
.set<google::cloud::compute_accelerator_types_v1::
AcceleratorTypesBackoffPolicyOption>(
google::cloud::ExponentialBackoffPolicy(
/*initial_delay=*/std::chrono::milliseconds(200),
/*maximum_delay=*/std::chrono::seconds(45),
/*scaling=*/2.0)
.clone());
auto connection = google::cloud::compute_accelerator_types_v1::
MakeAcceleratorTypesConnectionRest(options);
// c1 and c2 share the same retry policies
auto c1 = google::cloud::compute_accelerator_types_v1::AcceleratorTypesClient(
connection);
auto c2 = google::cloud::compute_accelerator_types_v1::AcceleratorTypesClient(
connection);
// You can override any of the policies in a new client. This new client
// will share the policies from c1 (or c2) *except* for the retry policy.
auto c3 = google::cloud::compute_accelerator_types_v1::AcceleratorTypesClient(
connection, google::cloud::Options{}
.set<google::cloud::compute_accelerator_types_v1::
AcceleratorTypesRetryPolicyOption>(
google::cloud::compute_accelerator_types_v1::
AcceleratorTypesLimitedTimeRetryPolicy(
std::chrono::minutes(5))
.clone()));
// You can also override the policies in a single call:
// c3.SomeRpc(..., google::cloud::Options{}
// .set<google::cloud::compute_accelerator_types_v1::AcceleratorTypesRetryPolicyOption>(
// google::cloud::compute_accelerator_types_v1::AcceleratorTypesLimitedErrorCountRetryPolicy(10).clone()));
This assumes you have created a custom idempotency policy. Such as:
class CustomIdempotencyPolicy
: public google::cloud::compute_accelerator_types_v1::
AcceleratorTypesConnectionIdempotencyPolicy {
public:
~CustomIdempotencyPolicy() override = default;
std::unique_ptr<google::cloud::compute_accelerator_types_v1::
AcceleratorTypesConnectionIdempotencyPolicy>
clone() const override {
return std::make_unique<CustomIdempotencyPolicy>(*this);
}
// Override inherited functions to define as needed.
};
Follow these links to find examples for other *Client
classes:
compute_accelerator_types_v1::AcceleratorTypesClient
compute_addresses_v1::AddressesClient
compute_autoscalers_v1::AutoscalersClient
compute_backend_buckets_v1::BackendBucketsClient
compute_backend_services_v1::BackendServicesClient
compute_disk_types_v1::DiskTypesClient
compute_disks_v1::DisksClient
compute_external_vpn_gateways_v1::ExternalVpnGatewaysClient
compute_firewall_policies_v1::FirewallPoliciesClient
compute_firewalls_v1::FirewallsClient
compute_forwarding_rules_v1::ForwardingRulesClient
compute_global_addresses_v1::GlobalAddressesClient
compute_global_forwarding_rules_v1::GlobalForwardingRulesClient
compute_global_network_endpoint_groups_v1::GlobalNetworkEndpointGroupsClient
compute_global_operations_v1::GlobalOperationsClient
compute_global_organization_operations_v1::GlobalOrganizationOperationsClient
compute_global_public_delegated_prefixes_v1::GlobalPublicDelegatedPrefixesClient
compute_health_checks_v1::HealthChecksClient
compute_http_health_checks_v1::HttpHealthChecksClient
compute_https_health_checks_v1::HttpsHealthChecksClient
compute_image_family_views_v1::ImageFamilyViewsClient
compute_images_v1::ImagesClient
compute_instance_group_managers_v1::InstanceGroupManagersClient
compute_instance_groups_v1::InstanceGroupsClient
compute_instance_templates_v1::InstanceTemplatesClient
compute_instances_v1::InstancesClient
compute_interconnect_attachments_v1::InterconnectAttachmentsClient
compute_interconnect_locations_v1::InterconnectLocationsClient
compute_interconnect_remote_locations_v1::InterconnectRemoteLocationsClient
compute_interconnects_v1::InterconnectsClient
compute_license_codes_v1::LicenseCodesClient
compute_licenses_v1::LicensesClient
compute_machine_images_v1::MachineImagesClient
compute_machine_types_v1::MachineTypesClient
compute_network_attachments_v1::NetworkAttachmentsClient
compute_network_edge_security_services_v1::NetworkEdgeSecurityServicesClient
compute_network_endpoint_groups_v1::NetworkEndpointGroupsClient
compute_network_firewall_policies_v1::NetworkFirewallPoliciesClient
compute_networks_v1::NetworksClient
compute_node_groups_v1::NodeGroupsClient
compute_node_templates_v1::NodeTemplatesClient
compute_node_types_v1::NodeTypesClient
compute_packet_mirrorings_v1::PacketMirroringsClient
compute_projects_v1::ProjectsClient
compute_public_advertised_prefixes_v1::PublicAdvertisedPrefixesClient
compute_public_delegated_prefixes_v1::PublicDelegatedPrefixesClient
compute_region_autoscalers_v1::RegionAutoscalersClient
compute_region_backend_services_v1::RegionBackendServicesClient
compute_region_commitments_v1::RegionCommitmentsClient
compute_region_disk_types_v1::RegionDiskTypesClient
compute_region_disks_v1::RegionDisksClient
compute_region_health_check_services_v1::RegionHealthCheckServicesClient
compute_region_health_checks_v1::RegionHealthChecksClient
compute_region_instance_group_managers_v1::RegionInstanceGroupManagersClient
compute_region_instance_groups_v1::RegionInstanceGroupsClient
compute_region_instance_templates_v1::RegionInstanceTemplatesClient
compute_region_instances_v1::RegionInstancesClient
compute_region_network_endpoint_groups_v1::RegionNetworkEndpointGroupsClient
compute_region_network_firewall_policies_v1::RegionNetworkFirewallPoliciesClient
compute_region_notification_endpoints_v1::RegionNotificationEndpointsClient
compute_region_operations_v1::RegionOperationsClient
compute_region_security_policies_v1::RegionSecurityPoliciesClient
compute_region_ssl_certificates_v1::RegionSslCertificatesClient
compute_region_ssl_policies_v1::RegionSslPoliciesClient
compute_region_target_http_proxies_v1::RegionTargetHttpProxiesClient
compute_region_target_https_proxies_v1::RegionTargetHttpsProxiesClient
compute_region_target_tcp_proxies_v1::RegionTargetTcpProxiesClient
compute_region_url_maps_v1::RegionUrlMapsClient
compute_regions_v1::RegionsClient
compute_reservations_v1::ReservationsClient
compute_resource_policies_v1::ResourcePoliciesClient
compute_routers_v1::RoutersClient
compute_routes_v1::RoutesClient
compute_security_policies_v1::SecurityPoliciesClient
compute_service_attachments_v1::ServiceAttachmentsClient
compute_snapshots_v1::SnapshotsClient
compute_ssl_certificates_v1::SslCertificatesClient
compute_ssl_policies_v1::SslPoliciesClient
compute_subnetworks_v1::SubnetworksClient
compute_target_grpc_proxies_v1::TargetGrpcProxiesClient
compute_target_http_proxies_v1::TargetHttpProxiesClient
compute_target_https_proxies_v1::TargetHttpsProxiesClient
compute_target_instances_v1::TargetInstancesClient
compute_target_pools_v1::TargetPoolsClient
compute_target_ssl_proxies_v1::TargetSslProxiesClient
compute_target_tcp_proxies_v1::TargetTcpProxiesClient
compute_target_vpn_gateways_v1::TargetVpnGatewaysClient
compute_url_maps_v1::UrlMapsClient
compute_vpn_gateways_v1::VpnGatewaysClient
compute_vpn_tunnels_v1::VpnTunnelsClient
compute_zone_operations_v1::ZoneOperationsClient
compute_zones_v1::ZonesClient