Ressourcen effizient synchronisieren

In dieser Anleitung wird beschrieben, wie Sie die inkrementelle Synchronisierung von Kalenderdaten implementieren. Mit dieser Methode können Sie Daten für alle Kalendersammlungen synchronisieren und Bandbreite sparen.

Inhalt

Übersicht

Die inkrementelle Synchronisierung besteht aus zwei Phasen:

  1. Die erste vollständige Synchronisierung wird einmal ganz am Anfang ausgeführt, um den Clientstatus mit dem Serverstatus vollständig zu synchronisieren. Der Client erhält ein Synchronisierungstoken, das beibehalten werden muss.

  2. Die inkrementelle Synchronisierung wird wiederholt durchgeführt und aktualisiert den Client mit allen Änderungen, die seit der letzten Synchronisierung vorgenommen wurden. Jedes Mal stellt der Client das vorherige Synchronisierungstoken bereit, das er vom Server erhalten hat, und speichert das neue Synchronisierungstoken aus der Antwort.

Erste vollständige Synchronisierung

Die erste vollständige Synchronisierung ist die ursprüngliche Anfrage für alle Ressourcen der Sammlung, die Sie synchronisieren möchten. Sie können die Listenanfrage optional mit Anfrageparametern einschränken, wenn Sie nur eine bestimmte Teilmenge von Ressourcen synchronisieren möchten.

Als Antwort auf den Listenvorgang enthält das Feld nextSyncToken ein Synchronisierungstoken. Sie müssen den Wert von nextSyncToken speichern. Wenn die Ergebnismenge zu groß ist und die Antwort paginiert wird, ist das Feld nextSyncToken nur auf der letzten Seite vorhanden.

Inkrementelle Synchronisierung

Mit der inkrementellen Synchronisierung können Sie alle Ressourcen abrufen, die seit der letzten Synchronisierungsanfrage geändert wurden. Dazu müssen Sie eine Listenanfrage mit dem neuesten Synchronisierungstoken ausführen, das im Feld syncToken angegeben ist. Denken Sie daran, dass das Ergebnis immer gelöschte Einträge enthält, damit die Clients sie aus dem Speicher entfernen können.

In Fällen, in denen sich eine große Anzahl von Ressourcen seit der letzten inkrementellen Synchronisierungsanfrage geändert hat, wird im Ergebnis der Liste möglicherweise ein pageToken anstelle eines syncToken angezeigt. In diesen Fällen müssen Sie dieselbe Listenabfrage ausführen, die für den Abruf der ersten Seite der inkrementellen Synchronisierung (mit genau derselben syncToken) verwendet wurde. Hängen Sie pageToken an diese Seite an und gehen Sie die folgenden Anfragen durch, bis Sie eine weitere syncToken auf der letzten Seite finden. Bewahren Sie diese syncToken für die nächste Synchronisierungsanfrage auf.

Hier sehen Sie Beispielabfragen für einen Fall, der eine inkrementelle Paginierung erfordert:

Ursprüngliche Abfrage

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

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

Nächste Seite abrufen

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

Vollständige Synchronisierung vom Server erforderlich

Manchmal werden Synchronisierungstoken aus verschiedenen Gründen vom Server ungültig, z. B. aufgrund des Ablaufs von Tokens oder von Änderungen in zugehörigen ACLs. In solchen Fällen antwortet der Server auf eine inkrementelle Anfrage mit dem Antwortcode 410. Dadurch sollte der Speicher des Clients vollständig gelöscht und eine neue vollständige Synchronisierung erfolgen.

Beispielcode

Das folgende Codebeispiel zeigt, wie Synchronisierungstoken mit der Java-Clientbibliothek verwendet werden. Wenn die Ausführungsmethode zum ersten Mal aufgerufen wird, erfolgt eine vollständige Synchronisierung und das Speichern des Synchronisierungstokens. Bei jeder nachfolgenden Ausführung wird das gespeicherte Synchronisierungstoken geladen und eine inkrementelle Synchronisierung durchgeführt.

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

Alte Synchronisierung

Bei Ereignissammlungen ist es weiterhin möglich, die Synchronisierung auf die alte Weise durchzuführen, indem Sie den Wert des aktualisierten Feldes aus einer Ereignislistenanfrage beibehalten und dann das Feld modifiedSince verwenden, um aktualisierte Ereignisse abzurufen. Dieser Ansatz wird nicht mehr empfohlen, da er im Hinblick auf verpasste Aktualisierungen fehleranfälliger ist, z. B. wenn keine Abfrageeinschränkungen erzwungen werden. Außerdem ist sie nur für Veranstaltungen verfügbar.