Synchronisation efficace des ressources

Ce guide explique comment implémenter la "synchronisation incrémentielle" des données d'agenda. Cette méthode vous permet de synchroniser les données de toutes les collections d'agenda tout en économisant de la bande passante.

Sommaire

Présentation

La synchronisation incrémentielle comprend deux étapes :

  1. La synchronisation complète initiale est effectuée une seule fois au tout début afin de synchroniser entièrement l'état du client avec celui du serveur. Le client obtient un jeton de synchronisation qu'il doit conserver.

  2. La synchronisation incrémentielle est effectuée à plusieurs reprises et met à jour le client avec toutes les modifications apportées depuis la synchronisation précédente. À chaque fois, le client fournit le jeton de synchronisation précédent qu'il a obtenu du serveur et stocke le nouveau jeton de synchronisation de la réponse.

Synchronisation complète initiale

La synchronisation complète initiale correspond à la demande d'origine pour toutes les ressources de la collection que vous souhaitez synchroniser. Vous pouvez éventuellement limiter la requête de liste à l'aide de paramètres de requête si vous ne souhaitez synchroniser qu'un sous-ensemble spécifique de ressources.

Dans la réponse à l'opération de liste, vous trouverez un champ appelé nextSyncToken représentant un jeton de synchronisation. Vous devrez stocker la valeur de nextSyncToken. Si l'ensemble de résultats est trop volumineux et que la réponse est paginée, le champ nextSyncToken n'est présent que sur la toute dernière page.

Synchronisation incrémentielle

La synchronisation incrémentielle vous permet de récupérer toutes les ressources qui ont été modifiées depuis la dernière requête de synchronisation. Pour ce faire, vous devez effectuer une requête list en spécifiant votre jeton de synchronisation le plus récent dans le champ syncToken. N'oubliez pas que le résultat contiendra toujours les entrées supprimées, afin que les clients aient la possibilité de les supprimer du stockage.

Dans les cas où un grand nombre de ressources ont changé depuis la dernière demande de synchronisation incrémentielle, vous pouvez trouver un pageToken au lieu d'un syncToken dans le résultat de la liste. Dans ce cas, vous devrez effectuer exactement la même requête de liste que celle utilisée pour récupérer la première page lors de la synchronisation incrémentielle (avec exactement le même syncToken), y ajouter le pageToken et parcourir toutes les requêtes suivantes jusqu'à ce que vous trouviez un autre syncToken sur la dernière page. Veillez à stocker ce syncToken pour la prochaine demande de synchronisation.

Voici des exemples de requêtes pour un cas nécessitant une synchronisation incrémentielle paginée :

Requête d'origine

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

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

Récupération de la page suivante

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

Synchronisation complète requise par le serveur

Parfois, les jetons de synchronisation sont invalidés par le serveur pour diverses raisons, y compris l'expiration du jeton ou des modifications apportées aux LCA associés. Dans ce cas, le serveur répondra à une requête incrémentielle avec un code de réponse 410. Cela devrait entraîner l'effacement complet du magasin du client et une nouvelle synchronisation complète.

Exemple de code

L'extrait de code exemple ci-dessous montre comment utiliser les jetons de synchronisation avec la bibliothèque cliente Java. La première fois que la méthode "run" est appelée, elle effectue une synchronisation complète et stocke le jeton de synchronisation. À chaque exécution ultérieure, il chargera le jeton de synchronisation enregistré et effectuera une synchronisation incrémentielle.

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

Ancienne synchronisation

Pour les collections d'événements, il est toujours possible d'effectuer la synchronisation de l'ancienne manière en conservant la valeur du champ mis à jour à partir d'une requête de liste d'événements, puis en utilisant le champ modifiedSince pour récupérer les événements mis à jour. Cette approche n'est plus recommandée, car elle est plus sujette aux erreurs en ce qui concerne les mises à jour manquées (par exemple, si elle n'applique pas de restrictions de requête). De plus, elle n'est disponible que pour les événements.