Sincroniza recursos de forma eficiente

En esta guía, se describe cómo implementar la "sincronización incremental" de los datos del calendario. Con este método, puedes mantener sincronizados los datos de todas las colecciones del calendario y ahorrar ancho de banda.

Contenido

Descripción general

La sincronización incremental consta de dos etapas:

  1. La sincronización completa inicial se realiza una vez al principio para sincronizar por completo el estado del cliente con el estado del servidor. El cliente obtendrá un token de sincronización que debe conservar.

  2. La sincronización incremental se realiza de forma repetida y actualiza el cliente con todos los cambios que se produjeron desde la sincronización anterior. Cada vez, el cliente proporciona el token de sincronización anterior que obtuvo del servidor y almacena el nuevo token de sincronización de la respuesta.

Sincronización completa inicial

La sincronización completa inicial es la solicitud original de todos los recursos de la colección que deseas sincronizar. De manera opcional, puedes restringir la solicitud de lista mediante los parámetros de solicitud si solo deseas sincronizar un subconjunto específico de recursos.

En la respuesta a la operación de lista, encontrarás un campo llamado nextSyncToken que representa un token de sincronización. Deberás almacenar el valor de nextSyncToken. Si el conjunto de resultados es demasiado grande y la respuesta se pagina, el campo nextSyncToken solo estará presente en la última página.

Sincronización incremental

La sincronización incremental te permite recuperar todos los recursos que se modificaron desde la última solicitud de sincronización. Para ello, debes realizar una solicitud de lista con el token de sincronización más reciente especificado en el campo syncToken. Ten en cuenta que el resultado siempre contendrá entradas borradas, de modo que los clientes tengan la oportunidad de quitarlas del almacenamiento.

En los casos en los que una gran cantidad de recursos cambiaron desde la última solicitud de sincronización incremental, es posible que encuentres un pageToken en lugar de un syncToken en el resultado de la lista. En esos casos, deberás realizar la misma consulta de lista que se usó para la recuperación de la primera página de la sincronización incremental (con exactamente el mismo syncToken), agregar pageToken y paginar todas las solicitudes siguientes hasta que encuentres otra syncToken en la última página. Asegúrate de almacenar este syncToken para la próxima solicitud de sincronización en el futuro.

A continuación, se muestran las consultas de ejemplo para un caso que requiere sincronización paginada incremental:

Consulta original

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

// Result contains the following

"nextPageToken":"CiAKGjBpNDd2Nmp2Zml2cXRwYjBpOXA",

Recuperando la página siguiente

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

El servidor requiere sincronización completa

En ocasiones, el servidor invalida los tokens de sincronización por varios motivos, como el vencimiento del token o los cambios en las LCA relacionadas. En esos casos, el servidor responderá a una solicitud incremental con un código de respuesta 410. Esto debería activar una limpieza completa del almacenamiento del cliente y una nueva sincronización completa.

Código de muestra

En el fragmento de código de muestra que aparece a continuación, se demuestra cómo usar tokens de sincronización con la biblioteca cliente de Java. La primera vez que se llame al método de ejecución, se realizará una sincronización completa y se almacenará el token de sincronización. En cada ejecución posterior, se cargará el token de sincronización guardado y realizará una sincronización incremental.

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

Sincronización heredada

En el caso de las colecciones de eventos, aún es posible realizar la sincronización de forma heredada si se conserva el valor del campo actualizado de una solicitud de lista de eventos y, luego, se usa el campo modifiedSince para recuperar los eventos actualizados. Este enfoque ya no se recomienda, ya que es más propenso a errores con respecto a las actualizaciones omitidas (por ejemplo, si no se aplican restricciones de consulta). Además, solo está disponible para eventos.