Efektywne synchronizowanie zasobów

Z tego przewodnika dowiesz się, jak wdrożyć „przyrostową synchronizację” danych kalendarza. Dzięki tej metodzie możesz synchronizować dane wszystkich kolekcji kalendarzy, oszczędzając przy tym przepustowość.

Spis treści

Przegląd

Synchronizacja przyrostowa składa się z 2 etapów:

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

  2. Synchronizacja przyrostowa jest wykonywana wielokrotnie i aktualizuje klienta o wszystkie zmiany, które zaszły od czasu poprzedniej synchronizacji. Za każdym razem klient podaje poprzedni token synchronizacji uzyskany z serwera i zapisuje nowy token synchronizacji z odpowiedzi.

Początkowa pełna synchronizacja

Początkowa pełna synchronizacja to pierwotna prośba o wszystkie zasoby 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 żądania.

W odpowiedzi na operację listy znajdziesz pole nextSyncToken reprezentujące token synchronizacji. Musisz zapisać wartość nextSyncToken. Jeśli zestaw wyników jest zbyt duży i odpowiedź jest stronicowana, pole nextSyncToken występuje tylko na ostatniej stronie.

Synchronizacja przyrostowa

Synchronizacja przyrostowa umożliwia pobranie wszystkich zasobów, które zostały zmodyfikowane od czasu ostatniej prośby o synchronizację. Aby to zrobić, musisz wysłać żądanie list z najnowszym tokenem synchronizacji określonym w polu syncToken. Pamiętaj, że wynik zawsze będzie zawierać usunięte wpisy, aby klienci mogli usunąć je z pamięci.

Jeśli od ostatniego żądania synchronizacji przyrostowej zmieniła się duża liczba zasobów, w wynikach listy możesz zobaczyć symbol pageToken zamiast syncToken. W takich przypadkach musisz wykonać dokładnie to samo zapytanie o listę, które zostało użyte do pobrania pierwszej strony w synchronizacji przyrostowej (z dokładnie tym samym parametrem syncToken), dołączyć do niego parametr pageToken i przejść przez wszystkie kolejne żądania, aż na ostatniej stronie znajdziesz kolejny parametr syncToken. Pamiętaj, aby zapisać ten syncToken na potrzeby przyszłych żądań synchronizacji.

Oto przykładowe zapytania w przypadku, gdy wymagana jest przyrostowa synchronizacja z podziałem na strony:

Pierwotne zapytanie

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

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

Wczytuję następną stronę

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

Serwer wymaga pełnej synchronizacji

Czasami tokeny synchronizacji są unieważniane przez serwer z różnych powodów, np. z powodu wygaśnięcia tokena lub zmian w powiązanych listach kontroli dostępu. W takich przypadkach serwer odpowie na żądanie przyrostowe kodem odpowiedzi 410. Powinno to spowodować całkowite wyczyszczenie sklepu klienta i nową pełną synchronizację.

Przykładowy kod

Poniższy fragment przykładowego kodu pokazuje, jak używać tokenów synchronizacji z biblioteką klienta Java. Gdy metoda run zostanie wywołana po raz pierwszy, wykona pełną synchronizację i zapisze token synchronizacji. Przy każdym kolejnym wykonaniu wczyta zapisany token synchronizacji i przeprowadzi 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.");
  }

Synchronizacja starszego typu

W przypadku kolekcji zdarzeń nadal można przeprowadzać synchronizację w starszy sposób, zachowując wartość zaktualizowanego pola z listy zdarzeń w żądaniu, a następnie używając pola modifiedSince do pobierania zaktualizowanych zdarzeń. Nie jest to już zalecane, ponieważ ta metoda jest bardziej podatna na błędy związane z pominiętymi aktualizacjami (np. nie wymusza ograniczeń zapytań). Poza tym jest ona dostępna tylko w przypadku wydarzeń.