有效率地同步處理資源

本指南說明如何實作日曆資料的「漸進式同步處理」。您可以使用這個方法來同步處理所有日曆集合的資料,同時節省頻寬。

目錄

總覽

增量同步處理包含兩個階段:

  1. 系統會在一開始執行完整同步處理一次,以便將用戶端的狀態與伺服器的狀態完全同步處理。用戶端會取得需要保留的同步權杖。

  2. 系統會重複執行增量同步處理,並將上次同步處理後至今發生的所有變更更新至用戶端。每次用戶端都會提供從伺服器取得的先前同步權杖,並儲存回應中的新同步權杖。

首次完整同步處理

初始完整同步處理是針對您要同步處理的集合所有資源的原始要求。如果只想同步處理特定資源子集,您可以選擇使用要求參數來限制清單要求。

在清單作業的回應中,您會看到名為 nextSyncToken 的欄位,代表同步處理權杖。您需要儲存 nextSyncToken 的值。如果結果集過大,且回應分頁,則 nextSyncToken 欄位只會顯示在最後一頁。

增量同步處理

漸進式同步處理可讓您擷取自上次同步處理要求以來修改的所有資源。為此,您必須使用 syncToken 欄位中指定的最新同步權杖執行清單要求。請注意,結果一律會包含已刪除的項目,因此用戶端有機會從儲存空間中移除這些項目。

如果自上次同步同步處理要求後有大量資源有所變更,清單結果中可能會顯示 pageToken,而非 syncToken。在這種情況下,您必須執行和用來擷取第一個網頁的清單查詢 (具有相同的 syncToken),然後附加 pageToken 並分頁所有要求,直到在最後一頁中找到另一個 syncToken。請務必儲存這個 syncToken,以便日後使用下一個同步要求。

以下是需要漸進式分頁同步處理的情況查詢範例:

原始查詢

GET /calendars/primary/events?maxResults=10&singleEvents=true&syncToken=CPDAlvWDx70CEPDAlvWDx

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

擷取下一頁

GET /calendars/primary/events?maxResults=10&singleEvents=true&syncToken=CPDAlvWDx70CEPDAlvWDx&pageToken=CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA

伺服器需要完整同步處理

有時伺服器會因為權杖過期或相關 ACL 異動等各種原因,而將同步處理權杖失效。在這種情況下,伺服器會透過回應代碼 410 回應漸進式要求。這應該會觸發用戶端商店的完整抹除作業,以及新的完整同步處理作業。

程式碼範例

下方的程式碼範例示範如何透過 Java 用戶端程式庫使用同步處理權杖。第一次呼叫執行方法時,系統會執行完整同步處理並儲存同步處理權杖。後續每次執行時,系統都會載入已儲存的同步處理權杖,並執行漸進式同步處理。

  private static void run() throws IOException {
    // Construct the {@link Calendar.Events.List} request, but don't execute it yet.
    Calendar.Events.List request = client.events().list("primary");

    // Load the sync token stored from the last execution, if any.
    String syncToken = syncSettingsDataStore.get(SYNC_TOKEN_KEY);
    if (syncToken == null) {
      System.out.println("Performing full sync.");

      // Set the filters you want to use during the full sync. Sync tokens aren't compatible with
      // most filters, but you may want to limit your full sync to only a certain date range.
      // In this example we are only syncing events up to a year old.
      Date oneYearAgo = Utils.getRelativeDate(java.util.Calendar.YEAR, -1);
      request.setTimeMin(new DateTime(oneYearAgo, TimeZone.getTimeZone("UTC")));
    } else {
      System.out.println("Performing incremental sync.");
      request.setSyncToken(syncToken);
    }

    // Retrieve the events, one page at a time.
    String pageToken = null;
    Events events = null;
    do {
      request.setPageToken(pageToken);

      try {
        events = request.execute();
      } catch (GoogleJsonResponseException e) {
        if (e.getStatusCode() == 410) {
          // A 410 status code, "Gone", indicates that the sync token is invalid.
          System.out.println("Invalid sync token, clearing event store and re-syncing.");
          syncSettingsDataStore.delete(SYNC_TOKEN_KEY);
          eventDataStore.clear();
          run();
        } else {
          throw e;
        }
      }

      List<Event> items = events.getItems();
      if (items.size() == 0) {
        System.out.println("No new events to sync.");
      } else {
        for (Event event : items) {
          syncEvent(event);
        }
      }

      pageToken = events.getNextPageToken();
    } while (pageToken != null);

    // Store the sync token from the last request to be used during the next execution.
    syncSettingsDataStore.set(SYNC_TOKEN_KEY, events.getNextSyncToken());

    System.out.println("Sync complete.");
  }

舊版同步處理

如果是事件集合,您仍可透過舊版方式執行同步處理,方法是保留事件清單要求中已更新欄位的值,然後使用 modifiedSince 欄位擷取更新後的事件。我們不建議使用這個方法,因為若是未強制執行查詢限制,會比較容易出錯。 此外,這類活動僅適用於活動。