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 de calendario y, al mismo tiempo, 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 se 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 token de sincronización nuevo de la respuesta.

Sincronización completa inicial

La sincronización completa inicial es la solicitud original para todos los recursos de la colección que deseas sincronizar. De manera opcional, puedes restringir la solicitud de lista con 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 tu token de sincronización más reciente especificado en el campo syncToken. Ten en cuenta que el resultado siempre contendrá entradas borradas para que los clientes tengan la oportunidad de quitarlas del almacenamiento.

En los casos en los que haya cambiado una gran cantidad de recursos desde la última solicitud de sincronización incremental, es posible que veas un pageToken en lugar de una syncToken en el resultado de la lista. En estos casos, deberás realizar exactamente la misma consulta de lista que se usó para recuperar la primera página de la sincronización incremental (con la misma syncToken), agregarle 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.

Estos son ejemplos de consultas 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",

Cómo recuperar la página siguiente

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

El servidor requiere sincronización completa

A veces, 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 de la tienda del cliente y una nueva sincronización completa.

Código de muestra

El fragmento de código de muestra que aparece a continuación 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 se 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, es posible realizar una sincronización de la manera heredada si se conserva el valor del campo actualizado a partir de una solicitud de lista de eventos y, luego, se usa el campo modifiedSince para recuperar los eventos actualizados. Ya no se recomienda este enfoque, ya que es más propenso a errores con respecto a las actualizaciones omitidas (por ejemplo, si no aplica restricciones de consulta). Además, solo están disponibles para eventos.