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 ostatniego żądania synchronizacji. 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że pojawić się 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 ACL. 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.");
  }

Starsza synchronizacja

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ń. To podejście nie jest już zalecane, ponieważ jest bardziej podatne na błędy związane z pominiętymi aktualizacjami (np. jeśli nie wymusza ograniczeń zapytań). Poza tym jest ona dostępna tylko w przypadku wydarzeń.