ポーリング ポリシーの構成

長時間実行オペレーションのポーリング ポリシーを構成する方法を学習します。Google Cloud Rust 用クライアント ライブラリには、長時間実行オペレーション(LRO)の進行状況のモニタリングを簡素化するヘルパー関数が用意されています。これらのヘルパーは、ポリシーを使用してポーリング頻度を構成し、どのポーリング エラーが一時的(安全に再試行できる)で、どのエラーが回復不能であるかを判断します。

LRO ループの動作を制御するポリシーは次の 2 つです。

  • ポーリング バックオフ ポリシーは、進行中の LRO のステータスをポーリングする前にループが待機する時間を制御します。
  • ポーリング エラー ポリシーは、ポーリング エラーが発生した場合の処理を制御します。一部のポーリング エラーは回復不能であり、オペレーションが中止されたか、呼び出し元に LRO のステータスを確認する権限がないことを示します。その他のポーリング エラーは一時的なもので、クライアント ネットワークまたはサービスの一時的な問題を示します。

これらのポリシーは個別に設定できます。また、クライアントで開始されたすべての LRO にポリシーを適用したり、単一のリクエストのポリシーを変更したりすることもできます。

前提条件

このガイドでは、コード スニペットを具体的にするために Cloud Storage サービスを使用しますが、同じコンセプトは LRO を使用する他のサービスにも適用されます。

このガイドを使用する前に、Rust での Cloud Storage の使用に沿って、Cloud Storage API を有効にして認証してください。

Rust ライブラリの完全な設定手順については、開発環境の設定をご覧ください。

依存関係

次の依存関係を Cargo.toml ファイルに追加します。

cargo add google-cloud-storage google-cloud-lro

クライアント内のすべてのリクエストのポーリング頻度を構成する

同じクライアントでほとんどのリクエストに同じポーリング バックオフ ポリシーを使用する場合は、ポリシーをクライアント オプションとして設定することを検討してください。このコードサンプルは、Cloud Storage サービスに対するすべてのリクエストのポーリング頻度を構成します。

pub async fn client_backoff(bucket: &str, folder: &str, dest: &str) -> Result<()> {
    // Use a type that implements the `PollingBackoffPolicy` trait, in this case
    // `ExponentialBackoffBuilder`.
    use google_cloud_gax::exponential_backoff::ExponentialBackoffBuilder;
    use google_cloud_lro::Poller;
    use std::time::Duration;

    let client = StorageControl::builder()
        // Initialize the policy with a chosen delay duration.
        .with_polling_backoff_policy(
            ExponentialBackoffBuilder::new()
                .with_initial_delay(Duration::from_millis(250))
                .with_maximum_delay(Duration::from_secs(10))
                .build()?,
        )
        .build()
        .await?;

    // Initiate an LRO using polling.
    let response = client
        .rename_folder()
        .set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
        .set_destination_folder_id(dest)
        .poller()
        .until_done()
        .await?;

    println!("LRO completed, response={response:?}");

    Ok(())
}

リクエストごとの設定でポリシーをオーバーライドしない限り、ポリシーはクライアントによって開始された長時間実行オペレーションで有効になります。

たとえば、次の呼び出しではこのポリシーが使用されます。

    let mut operation = client
        .rename_folder()
        /* more stuff */
        .send()
        .await?;

この例の呼び出しでは、クライアント ライブラリは最初のポーリング試行の後に 250 ミリ秒、2 回目の試行の後に 500 ミリ秒待機します。以降の試行では、1 秒、2 秒、4 秒、8 秒待機してから、以降のすべての試行で 10 秒待機します。

特定のリクエストのポーリング頻度を構成する

個々のリクエストのポーリング頻度を構成できます。これにより、クライアント レベルで設定されたポリシーがオーバーライドされます。次に例を示します。

pub async fn rpc_backoff(bucket: &str, folder: &str, dest: &str) -> Result<()> {
    // Use a type that implements the `PollingBackoffPolicy` trait, in this case
    // `ExponentialBackoffBuilder`.
    use google_cloud_gax::exponential_backoff::ExponentialBackoffBuilder;
    use std::time::Duration;

    // To configure the request, bring the RequestOptionsBuilder trait into
    // scope.
    use google_cloud_gax::options::RequestOptionsBuilder;
    use google_cloud_lro::Poller;

    let client = StorageControl::builder().build().await?;
    // Create the request builder.
    let response = client
        .rename_folder()
        // Configure the polling backoff policy.
        .with_polling_backoff_policy(
            ExponentialBackoffBuilder::new()
                .with_initial_delay(Duration::from_millis(250))
                .with_maximum_delay(Duration::from_secs(10))
                .build()?,
        )
        .set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
        .set_destination_folder_id(dest)
        // Issue the polling request as normal.
        .poller()
        .until_done()
        .await?;

    println!("LRO completed, response={response:?}");

    Ok(())
}

クライアント内のすべてのリクエストに対して再試行可能なポーリング エラーを構成する

再試行可能なエラーを構成するには、PollingErrorPolicy トレイトを実装する型を使用します。クライアント ライブラリにはいくつかのポリシーが用意されています。保守的な選択肢は Aip194Strict です。同じクライアントでほとんどのリクエストに同じポーリング ポリシーを使用する場合は、ポリシーをクライアント オプションとして設定することを検討してください。

このコードサンプルは、Cloud Storage サービスに対するすべてのリクエストで再試行可能なポーリング エラーを構成します。

pub async fn client_error_policy(bucket: &str, folder: &str, dest: &str) -> Result<()> {
    // Use a type that implements the `PollingErrorPolicy` trait, in this case
    // `Aip194Strict`.
    use google_cloud_gax::polling_error_policy::Aip194Strict;
    use google_cloud_gax::polling_error_policy::PollingErrorPolicyExt;
    use google_cloud_lro::Poller;
    use std::time::Duration;

    // Add the polling policy that you want to use for all long-running
    // operations.
    let client = StorageControl::builder()
        .with_polling_error_policy(
            Aip194Strict
                .with_attempt_limit(100)
                .with_time_limit(Duration::from_secs(300)),
        )
        .build()
        .await?;

    // Initiate an LRO using polling.
    let response = client
        .rename_folder()
        .set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
        .set_destination_folder_id(dest)
        .poller()
        .until_done()
        .await?;

    println!("LRO completed, response={response:?}");

    Ok(())
}

ポーリング エラー ポリシーは LRO 待機ループ中のエラーを処理しますが、LRO を開始するリクエストを最初に送信するときに発生する可能性のある一時的なエラーを処理するために、標準の再試行ポリシーを追加することもできます。

    let client = StorageControl::builder()
        .with_retry_policy(
            retry_policy::Aip194Strict
                .with_attempt_limit(100)
                .with_time_limit(Duration::from_secs(300)),
        )
        .build()
        .await?;

リクエストごとの設定でポリシーをオーバーライドしない限り、このポリシーはクライアントによって開始された長時間実行オペレーションに有効なままになります。たとえば、次のような呼び出しを行うとします。

    let mut operation = client
        .rename_folder()
        /* more stuff */
        .send()
        .await?;

注: クライアント ライブラリは UNAVAILABLEAIP-194 を参照)のみを再試行可能なエラーとして扱い、100 回の試行または 300 秒のいずれか早い方が経過するとポーリングを停止します。

特定のリクエストに対して再試行可能なポーリング エラーを構成する

PollingErrorPolicy トレイトを実装する型を使用して、RequestOptionsBuilder トレイトをスコープに含めることで、特定のリクエストに対して再試行可能なポーリング エラーを構成できます。

このコードサンプルは、Cloud Storage サービスへの特定のリクエストに対して再試行可能なポーリング エラーを構成します。

pub async fn rpc_error_policy(bucket: &str, folder: &str, dest: &str) -> Result<()> {
    // Use a type that implements the `PollingErrorPolicy` trait, in this case
    // `Aip194Strict`.
    use google_cloud_gax::polling_error_policy::Aip194Strict;
    use google_cloud_gax::polling_error_policy::PollingErrorPolicyExt;
    // Bring `RequestOptionsBuilder` into scope.
    use google_cloud_gax::options::RequestOptionsBuilder;
    use std::time::Duration;
    use google_cloud_lro::Poller;

    let client = StorageControl::builder().build().await?;

    // Create the request builder.
    let response = client
        .rename_folder()
        // Configure the polling error policy.
        .with_polling_error_policy(
            Aip194Strict
                .with_attempt_limit(100)
                .with_time_limit(Duration::from_secs(300)),
        )
        .set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
        .set_destination_folder_id(dest)
        // Initialize the request.
        .poller()
        .until_done()
        .await?;

    println!("LRO completed, response={response:?}");

    Ok(())
}

LRO を開始する最初のリクエストが失敗した場合に備えて、再試行ポリシーを追加することも検討してください。

    let client = StorageControl::builder()
        .with_retry_policy(
            retry_policy::Aip194Strict
                .with_attempt_limit(100)
                .with_time_limit(Duration::from_secs(300)),
        )
        .build()
        .await?;