Efektywne synchronizowanie zasobów

Z tego przewodnika dowiesz się, jak zaimplementować „stopniową synchronizację” danych z kalendarza. Dzięki temu możesz zachować synchronizację danych ze wszystkich kolekcji kalendarza, jednocześnie oszczędzając przepustowość.

Spis treści

Omówienie

Incrementalna synchronizacja składa się z 2 etapów:

  1. Początkowa pełna synchronizacja jest wykonywana raz na samym początku, aby w pełni zsynchronizować stan klienta ze stanem serwera. Klient otrzyma token synchronizacji, który musi zachować.

  2. Incrementalna synchronizacja jest wykonywana wielokrotnie i aktualizuje klienta ze wszystkimi zmianami, które zaszły od poprzedniej synchronizacji. Za każdym razem klient przekazuje poprzedni token synchronizacji uzyskany od serwera i zapisują nowy token synchronizacji z odpowiedzi.

Początkowa pełna synchronizacja

Początkowa pełna synchronizacja to pierwotne żądanie wszystkich zasobów kolekcji, którą chcesz zsynchronizować. Jeśli chcesz zsynchronizować tylko określony podzbiór zasobów, możesz opcjonalnie ograniczyć żądanie listy za pomocą parametrów żądań.

W odpowiedzi na operację listowania znajdziesz pole o nazwie nextSyncToken, które reprezentuje token synchronizacji. Musisz przechowywać wartość nextSyncToken. Jeśli zbiór wyników jest zbyt duży i odpowiedź jest przeznaczona do wyświetlenia na wielu stronach, pole nextSyncToken jest obecne tylko na ostatniej stronie.

Synchronizacja przyrostowa

Synchronizacja przyrostowa umożliwia pobieranie wszystkich zasobów, które zostały zmodyfikowane od czasu ostatniego żądania synchronizacji. Aby to zrobić, musisz wykonać żądanie listy z najnowszym tokenem synchronizacji określonym w polu syncToken. Pamiętaj, że wynik zawsze będzie zawierać usunięte wpisy, aby klienci mieli możliwość usunięcia ich z pamięci.

Jeśli od ostatniego żądania synchronizacji przyrostowej zmieniła się duża liczba zasobów, w wyniku listy zamiast wartości syncToken może pojawić się wartość pageToken. W takich przypadkach musisz wykonać dokładnie to samo zapytanie o listę, które zostało użyte do pobrania pierwszej strony w ramach synchronizacji przyrostowej (z dokładnie tym samym syncToken), dodać do niego pageToken i przechodzić przez wszystkie kolejne żądania, aż znajdziesz kolejne syncToken na ostatniej stronie. Zapisz ten identyfikator syncToken, aby użyć go w przyszłości podczas kolejnego żądania synchronizacji.

Oto przykładowe zapytania w przypadku wymagającym stopniowej synchronizacji stron:

Pierwotne zapytanie

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

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

Pobieranie następnej strony

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

Pełna synchronizacja wymagana przez serwer

Czasami serwer unieważnia tokeny synchronizacji z różnych powodów, m.in. z powodu wygaśnięcia tokenu lub zmian w powiązanych listach kontroli dostępu ACL. W takich przypadkach serwer odpowiada na żądanie przyrostowe kodem odpowiedzi 410. Powinna ona spowodować pełne wyczyszczenie pamięci podręcznej klienta i ponowną pełną synchronizację.

Przykładowy kod

Poniżej znajduje się fragment kodu, który pokazuje, jak używać tokenów synchronizacji z biblioteką klienta Java. Podczas pierwszego wywołania metody run zostanie przeprowadzona pełna synchronizacja i zapisany zostanie token synchronizacji. Przy każdym kolejnym wywołaniu skrypt wczyta zapisany token synchronizacji i wykonuje synchronizację przyrostową.

  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.");
  }

Starsza synchronizacja

W przypadku zbiorów zdarzeń nadal można synchronizować dane w sposób tradycyjny, zachowując wartość zaktualizowanego pola z zapytania o listę zdarzeń, a potem pobierając zaktualizowane zdarzenia za pomocą pola modifiedSince. Nie zalecamy już tego podejścia, ponieważ jest ono bardziej podatne na błędy w przypadku pominięcia aktualizacji (np. jeśli nie egzekwuje ograniczeń zapytań). Jest ona dostępna tylko w przypadku zdarzeń.