このガイドでは、カレンダーデータの「増分同期」を実装する方法について説明します。この方法を使用すると、帯域幅を節約しながら、すべてのカレンダー コレクションのデータを同期できます。
目次
概要
増分同期は次の 2 つの段階で構成されます。
クライアントの状態をサーバーの状態と完全に同期するために、最初の完全同期が最初に 1 回実行されます。クライアントは、保持する必要がある同期トークンを取得します。
増分同期は繰り返し実行され、前回の同期以降に行われたすべての変更でクライアントが更新されます。毎回、クライアントはサーバーから取得した前回の同期トークンを提供し、レスポンスから新しい同期トークンを保存します。
最初の完全同期
最初の完全同期は、同期するコレクションのすべてのリソースに対する元のリクエストです。リソースの特定のサブセットのみを同期する場合は、リクエスト パラメータを使用してリスト リクエストを制限できます。
リスト オペレーションのレスポンスには、同期トークンを表す
nextSyncToken というフィールドがあります。 nextSyncToken の値を保存する必要があります。結果セットが大きすぎてレスポンスが
ページ分割される場合、nextSyncToken
フィールドは最後のページにのみ存在します。
増分同期
増分同期を使用すると、前回の同期リクエスト以降に変更されたすべてのリソースを取得できます。これを行うには、`syncToken` フィールドに最新の同期トークンを指定してリスト
リクエストを実行する必要があります。
結果には常に削除されたエントリが含まれるため、クライアントはストレージから削除できます。
前回の増分同期リクエスト以降に多数のリソースが変更された場合、リスト結果に syncToken ではなく pageToken が表示されることがあります。このような場合は、増分同期で最初のページの取得に使用したリストクエリ(まったく同じ 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 クライアント ライブラリで同期トークンを使用する方法を示しています。run メソッドが最初に呼び出されると、完全同期が実行され、同期トークンが保存されます。以降の実行では、保存された同期トークンが読み込まれ、増分同期が実行されます。
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."); }
従来の同期
イベント コレクションの場合、イベント リスト リクエストから updated フィールドの値を保持し、modifiedSince フィールドを使用して更新されたイベントを取得することで、
従来の方法で同期を行うことができます。この方法は、更新の見落とし( がクエリ制限を適用しない場合など)に関してエラーが発生しやすいため、現在では推奨されていません。
また、イベントでのみ使用できます。