Эффективно синхронизируйте ресурсы

В этом руководстве описано, как реализовать инкрементальную синхронизацию данных календаря. Используя этот метод, вы можете поддерживать синхронизацию данных для всех коллекций календарей, экономя при этом пропускную способность сети.

Содержание

Обзор

Поэтапная синхронизация состоит из двух этапов:

  1. Первоначальная полная синхронизация : выполняется один раз в начале для полной синхронизации состояния клиента с состоянием сервера. Клиент получает токен синхронизации, который он должен сохранить.

  2. Инкрементальная синхронизация : выполняется многократно для обновления информации о клиенте, внесенной с момента предыдущей синхронизации. Каждый раз клиент предоставляет токен предыдущей синхронизации, полученный от сервера, и сохраняет новый токен синхронизации из ответа.

Первоначальная полная синхронизация

Первоначальная полная синхронизация — это исходный запрос на все ресурсы коллекции, которую вы хотите синхронизировать. При желании вы можете ограничить запрос списка с помощью параметров запроса, если хотите синхронизировать только определенное подмножество ресурсов.

В ответе на операцию получения списка содержится поле с именем nextSyncToken представляющее собой токен синхронизации. Необходимо сохранить значение поля nextSyncToken . Если результирующий набор слишком велик и ответ разбит на страницы , то поле nextSyncToken будет присутствовать только на последней странице.

Постепенная синхронизация

Инкрементальная синхронизация позволяет получить все ресурсы, измененные с момента последнего запроса на синхронизацию. Для этого выполните запрос на получение списка, указав в поле syncToken ваш последний токен синхронизации. Имейте в виду, что результат всегда содержит удаленные записи, поэтому клиенты могут удалить их из хранилища.

В случаях, когда с момента последнего запроса на инкрементальную синхронизацию изменилось большое количество ресурсов, в результатах поиска вместо syncToken может оказаться pageToken . В таких случаях выполните тот же запрос к списку, что и для получения первой страницы в инкрементальной синхронизации (с тем же syncToken ), добавьте к нему pageToken и пройдите по страницам последующих запросов, пока не найдете еще один syncToken на последней странице. Сохраните этот syncToken для следующего запроса на синхронизацию.

Следующие примеры демонстрируют пошаговую синхронизацию:

Исходный запрос

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

В результате отображается следующее:

{
  "nextPageToken": "CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA"
}

Получение следующей страницы

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

Серверу требуется полная синхронизация.

Иногда сервер аннулирует токены синхронизации из-за истечения срока их действия или изменений в соответствующих списках контроля доступа (ACL). В таких случаях сервер отвечает на запрос на инкрементную синхронизацию кодом состояния HTTP 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 из запроса списка событий, а затем используя поле updatedMin для получения обновленных событий. Этот подход больше не рекомендуется, поскольку он более подвержен ошибкам (например, не обеспечивает соблюдение ограничений запроса) и доступен только для событий.