設定輪詢政策

瞭解如何設定長時間執行作業的輪詢政策。Rust 的Google Cloud 用戶端程式庫提供輔助函式,可簡化長時間執行的作業 (LRO) 的進度監控作業。這些輔助程式會使用政策設定輪詢頻率,並判斷哪些輪詢錯誤是暫時性錯誤 (可安全地重試),哪些是無法復原的錯誤。

有兩項政策可控管 LRO 迴圈的行為:

  • 輪詢輪詢政策會控管迴圈等待時間,之後輪詢仍在進行中的 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 毫秒,然後在第二次嘗試後等待 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?;

注意:用戶端程式庫只會將 UNAVAILABLE (請參閱 AIP-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?;