Efektywne synchronizowanie zasobów

Ten poradnik opisuje, jak wdrożyć przyrostową synchronizację danych kalendarza. Dzięki tej metodzie możesz synchronizować dane wszystkich kolekcji kalendarza, 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: wykonywana raz na początku, aby w pełni zsynchronizować stan klienta ze stanem serwera. Klient uzyskuje token synchronizacji, który musi zachować.

  2. Synchronizacja przyrostowa: wykonywana wielokrotnie, aby zaktualizować klienta o wszystkie zmiany wprowadzone 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 pierwotne żądanie dotyczące 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 żądania.

W odpowiedzi na operację listy znajduje się pole o nazwie nextSyncToken reprezentujące token synchronizacji. Musisz zapisać wartość nextSyncToken. Jeśli zestaw wyników jest zbyt duży, a odpowiedź jest podzielona na strony, pole nextSyncToken występuje 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ć, wyślij żądanie listy z najnowszym tokenem synchronizacji określonym w polu syncToken. Pamiętaj, że wynik zawsze zawiera usunięte wpisy, dzięki czemu klienci mogą je usunąć z pamięci.

Jeśli od czasu ostatniego żądania synchronizacji przyrostowej zmieniła się duża liczba zasobów, w wyniku listy możesz znaleźć pageToken zamiast syncToken. W takich przypadkach wykonaj to samo zapytanie listy, które zostało użyte do pobrania pierwszej strony w synchronizacji przyrostowej (z tym samym syncToken), dołącz do niego pageToken i przejdź do kolejnych żądań, aż na ostatniej stronie znajdziesz kolejny syncToken. Zapisz ten syncToken na potrzeby następnego żądania synchronizacji.

Poniższe przykłady pokazują przyrostową synchronizację podzieloną na strony:

Pierwotne zapytanie

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

Wynik zawiera:

{
  "nextPageToken": "CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA"
}

Pobieranie następnej strony

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

Serwer wymaga pełnej synchronizacji

Serwer czasami unieważnia tokeny synchronizacji z powodu wygaśnięcia tokena lub zmian w powiązanych listach ACL. W takich przypadkach serwer odpowiada na żądanie przyrostowe kodem stanu HTTP 410. Gdy tak się stanie, wyczyść pamięć klienta i przeprowadź nową pełną synchronizację.

Przykładowy kod

Poniższy przykład pokazuje, jak używać tokenów synchronizacji z biblioteką klienta Java. Gdy metoda run() jest wywoływana po raz pierwszy, wykonuje pełną synchronizację i zapisuje token synchronizacji. Przy każdym kolejnym wykonaniu wczytuje zapisany token synchronizacji i przeprowadza 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ń możesz przeprowadzić synchronizację starszego typu, zapisując wartość pola updated z żądania listy zdarzeń, a następnie używając updatedMin pola do pobierania zaktualizowanych zdarzeń. To podejście nie jest już zalecane, ponieważ jest bardziej podatne na błędy (np. nie wymusza ograniczeń zapytań) i jest dostępne tylko w przypadku zdarzeń.