Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(generator): separate page for retry policy overrides #11950

Merged
merged 9 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions ci/generate-markdown/update-library-landing-dox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ readonly EXPECTED=(
"environment-variables.dox"
"override-authentication.dox"
"override-endpoint.dox"
"override-retry-policies.dox"
)
for file in "${EXPECTED[@]}"; do
if [[ ! -r "${DOCDIR}/${file}" ]]; then
Expand All @@ -49,6 +50,7 @@ readonly MAIN_DOX="${DOCDIR}/main.dox"
readonly ENVIRONMENT_DOX="${DOCDIR}/environment-variables.dox"
readonly OVERRIDE_AUTHENTICATION_DOX="${DOCDIR}/override-authentication.dox"
readonly OVERRIDE_ENDPOINT_DOX="${DOCDIR}/override-endpoint.dox"
readonly OVERRIDE_RETRY_POLICIES_DOX="${DOCDIR}/override-retry-policies.dox"

inject_start="<!-- inject-endpoint-env-vars-start -->"
inject_end="<!-- inject-endpoint-env-vars-end -->"
Expand Down Expand Up @@ -189,3 +191,55 @@ _EOF_
done
sed -n '/<!-- inject-endpoint-pages-end -->/,$p' "${OVERRIDE_ENDPOINT_DOX}"
) | sponge "${OVERRIDE_ENDPOINT_DOX}"

(
sed '/<!-- inject-retry-snippet-start -->/q' "${OVERRIDE_RETRY_POLICIES_DOX}"
if [[ ${#samples_cc[@]} -gt 0 ]]; then
sample_cc="${samples_cc[0]}"
client_name="${clients[${sample_cc}]}"
cat <<_EOF_
For example, this will override the retry policies for \`${client_name}\`:

@snippet $(basename "${sample_cc}") set-retry-policy

This assumes you have created a custom idempotency policy. Such as:

@snippet $(basename "${sample_cc}") custom-idempotency-policy

_EOF_
if [[ ${#samples_cc[@]} -gt 1 ]]; then
echo
echo "Follow these links to find examples for other \\c *Client classes:"
echo
for sample_cc in "${samples_cc[@]}"; do
client_name="${clients[${sample_cc}]}"
# shellcheck disable=SC2016
printf -- '- [\c %s](@ref %s-retry-snippet)\n' "${client_name}" "${client_name}"
done
fi
fi
echo
sed -n '/<!-- inject-retry-snippet-end -->/,$p' "${OVERRIDE_RETRY_POLICIES_DOX}"
) | sponge "${OVERRIDE_RETRY_POLICIES_DOX}"

(
sed '/<!-- inject-retry-pages-start -->/q' "${OVERRIDE_RETRY_POLICIES_DOX}"
for sample_cc in "${samples_cc[@]}"; do
client_name="${clients[${sample_cc}]}"
cat <<_EOF_

/*! @page ${client_name}-retry-snippet Override ${client_name} Retry Policies

This shows how to override the retry policies for ${client_name}:

@snippet ${sample_cc} set-retry-policy

Assuming you have created a custom idempotency policy. Such as:

@snippet ${sample_cc} custom-idempotency-policy

*/
_EOF_
done
sed -n '/<!-- inject-retry-pages-end -->/,$p' "${OVERRIDE_RETRY_POLICIES_DOX}"
) | sponge "${OVERRIDE_RETRY_POLICIES_DOX}"
101 changes: 94 additions & 7 deletions generator/internal/scaffold_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ void GenerateScaffold(
{"doc/environment-variables.dox", GenerateDoxygenEnvironmentPage},
{"doc/override-authentication.dox", GenerateOverrideAuthenticationPage},
{"doc/override-endpoint.dox", GenerateOverrideEndpointPage},
{"doc/override-retry-policies.dox", GenerateOverrideRetryPoliciesPage},
{"doc/options.dox", GenerateDoxygenOptionsPage},
{"quickstart/README.md", GenerateQuickstartReadme},
{"quickstart/quickstart.cc", GenerateQuickstartSkeleton},
Expand Down Expand Up @@ -700,24 +701,19 @@ which should give you a taste of the $title$ C++ client library API.
<!-- inject-client-list-start -->
<!-- inject-client-list-end -->

## Retry, Backoff, and Idempotency Policies.

The library automatically retries requests that fail with transient errors, and
uses [exponential backoff] to backoff between retries. Application developers
can override the default policies.

## More Information

- @ref common-error-handling - describes how the library reports errors.
- @ref $library$-override-endpoint - describes how to override the default
endpoint.
- @ref $library$-override-authentication - describes how to change the
authentication credentials used by the library.
- @ref $library$-override-retry - describes how to change the default retry
policies.
- @ref $library$-env - describes environment variables that can configure the
behavior of the library.

[cloud-service-docs]: https://cloud.google.com/$site_root$
[exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff

*/
)""";
Expand Down Expand Up @@ -838,6 +834,97 @@ client library to change this default.
printer.Print(variables, kText);
}

void GenerateOverrideRetryPoliciesPage(
std::ostream& os, std::map<std::string, std::string> const& variables) {
auto constexpr kText = R"""(/*!
@page $library$-override-retry 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

@section $library$-override-retry-retry-policy Configuring the transient errors and retry duration

The `*RetryPolicyOption` controls:

- Which errors are to be treated as transient errors.
- How long will 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](@ref google::cloud::StatusCode) is treated
as a transient error.

@section $library$-override-retry-backoff-policy 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`](@ref google::cloud::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.

@section $library$-override-retry-idempotency-policy 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.

@section $library$-override-retry-example Example

<!-- inject-retry-snippet-start -->
<!-- inject-retry-snippet-end -->

@section $library$-override-retry-more-information More Information

@see google::cloud::Options
@see google::cloud::BackoffPolicy
@see google::cloud::ExponentialBackoffPolicy

[exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff

*/

// <!-- inject-retry-pages-start -->
// <!-- inject-retry-pages-end -->
)""";
google::protobuf::io::OstreamOutputStream output(&os);
google::protobuf::io::Printer printer(&output, '$');
printer.Print(variables, kText);
}

void GenerateDoxygenOptionsPage(
std::ostream& os, std::map<std::string, std::string> const& variables) {
auto constexpr kText = R"""(/*!
Expand Down
2 changes: 2 additions & 0 deletions generator/internal/scaffold_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ void GenerateOverrideAuthenticationPage(
std::ostream& os, std::map<std::string, std::string> const& variables);
void GenerateOverrideEndpointPage(
std::ostream& os, std::map<std::string, std::string> const& variables);
void GenerateOverrideRetryPoliciesPage(
std::ostream& os, std::map<std::string, std::string> const& variables);
void GenerateQuickstartReadme(
std::ostream& os, std::map<std::string, std::string> const& variables);
void GenerateQuickstartSkeleton(
Expand Down
12 changes: 12 additions & 0 deletions generator/internal/scaffold_generator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ to Provides a placeholder to write this test.
endpoint.
- @ref test-override-authentication - describes how to change the
authentication credentials used by the library.
- @ref test-override-retry - describes how to change the default retry
policies.
)"""));
}

Expand Down Expand Up @@ -335,6 +337,16 @@ TEST_F(ScaffoldGenerator, OverrideEndpointPage) {
)""")));
}

TEST_F(ScaffoldGenerator, OverrideRetryPoliciesPage) {
auto const vars = ScaffoldVars(path(), MockIndex(), service(), false);
std::ostringstream os;
GenerateOverrideRetryPoliciesPage(os, vars);
auto const actual = std::move(os).str();
EXPECT_THAT(actual, AllOf(HasSubstr(R"""(
@page test-override-retry Override Retry, Backoff, and Idempotency Policies
)""")));
}

TEST_F(ScaffoldGenerator, QuickstartReadme) {
auto const vars = ScaffoldVars(path(), MockIndex(), service(), false);
std::ostringstream os;
Expand Down
9 changes: 2 additions & 7 deletions google/cloud/accessapproval/doc/main.dox
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,16 @@ parameters, and infrastructure to mock
application.
<!-- inject-client-list-end -->

## Retry, Backoff, and Idempotency Policies.

The library automatically retries requests that fail with transient errors, and
uses [exponential backoff] to backoff between retries. Application developers
can override the default policies.

## More Information

- @ref common-error-handling - describes how the library reports errors.
- @ref accessapproval-override-endpoint - describes how to override the default
endpoint.
- @ref accessapproval-override-authentication - describes how to change the
authentication credentials used by the library.
- @ref accessapproval-override-retry - describes how to change the default retry
policies.
- @ref accessapproval-env - describes environment variables that can configure the behavior of the library.

[exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff

*/
105 changes: 105 additions & 0 deletions google/cloud/accessapproval/doc/override-retry-policies.dox
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*!

@page accessapproval-override-retry 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

@section accessapproval-override-retry-retry-policy Configuring the transient errors and retry duration

The `*RetryPolicyOption` controls:

- Which errors are to be treated as transient errors.
- How long will 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](@ref google::cloud::StatusCode) is treated
as a transient error.

@section accessapproval-override-retry-backoff-policy 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`](@ref google::cloud::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.

@section accessapproval-override-retry-idempotency-policy 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.

@section accessapproval-override-retry-example Example

<!-- inject-retry-snippet-start -->
For example, this will override the retry policies for `accessapproval_v1::AccessApprovalClient`:

@snippet access_approval_client_samples.cc set-retry-policy

This assumes you have created a custom idempotency policy. Such as:

@snippet access_approval_client_samples.cc custom-idempotency-policy


<!-- inject-retry-snippet-end -->

@section accessapproval-override-retry-more-information More Information

@see google::cloud::Options
@see google::cloud::BackoffPolicy
@see google::cloud::ExponentialBackoffPolicy

[exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff

*/

// <!-- inject-retry-pages-start -->

/*! @page accessapproval_v1::AccessApprovalClient-retry-snippet Override accessapproval_v1::AccessApprovalClient Retry Policies

This shows how to override the retry policies for accessapproval_v1::AccessApprovalClient:

@snippet google/cloud/accessapproval/v1/samples/access_approval_client_samples.cc set-retry-policy

Assuming you have created a custom idempotency policy. Such as:

@snippet google/cloud/accessapproval/v1/samples/access_approval_client_samples.cc custom-idempotency-policy

*/
// <!-- inject-retry-pages-end -->
9 changes: 2 additions & 7 deletions google/cloud/accesscontextmanager/doc/main.dox
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,17 @@ parameters, and infrastructure to mock
application.
<!-- inject-client-list-end -->

## Retry, Backoff, and Idempotency Policies.

The library automatically retries requests that fail with transient errors, and
uses [exponential backoff] to backoff between retries. Application developers
can override the default policies.

## More Information

- @ref common-error-handling - describes how the library reports errors.
- @ref accesscontextmanager-override-endpoint - describes how to override the default
endpoint.
- @ref accesscontextmanager-override-authentication - describes how to change the
authentication credentials used by the library.
- @ref accesscontextmanager-override-retry - describes how to change the default retry
policies.
- @ref accesscontextmanager-env - describes environment variables that can configure the behavior of the library.

[cloud-service-docs]: https://cloud.google.com/access-context-manager
[exponential backoff]: https://en.wikipedia.org/wiki/Exponential_backoff

*/
Loading