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 metodo, puedes mantener sincronizados los datos de todas las colecciones de calendarios 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 deberá 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 recopilación que deseas sincronizar. De manera opcional, puedes restringir la solicitud de lista con 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 que una gran cantidad de recursos cambió 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 estos casos, deberás realizar la misma consulta de lista que se usó para recuperar la primera página en la sincronización incremental (con el mismo syncToken), agregarle el pageToken y paginar todas las solicitudes siguientes hasta que encuentres otro 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 una sincronización paginada incremental:

Búsqueda 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 una 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 ACL 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

En el siguiente fragmento de código de muestra, se muestra cómo usar tokens de sincronización con la biblioteca cliente de Java. La primera vez que se llame al método run, 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, aún es posible realizar la sincronización de la manera tradicional 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. Ya no se recomienda este enfoque, ya que es más propenso a errores con respecto a las actualizaciones perdidas (por ejemplo, si no aplica restricciones de consulta). Además, solo está disponible para eventos.