2012-01-27 11 views
8

Descripción general: Estoy tratando de evitar una condición de carrera con el acceso a un IndexedDB desde una página web y un trabajador web.Acceso a IndexedDB desde múltiples hilos de JavaScript

Configuración: Página web que guarda elementos en el IndexedDB local a medida que el usuario trabaja con el sitio. Cuando un usuario guarda datos en el DB local, el registro se marca como "No enviado".

Hilo de fondo de trabajador web que está extrayendo datos del IndexedDB, enviándolo al servidor y una vez que el servidor lo recibe, marcando los datos en IndexedDB como "Enviados".

Problema: Dado que el acceso a la IndexedDB es asincrónica, no se puede garantizar que el usuario no va a actualizar un registro al mismo tiempo, la web de trabajo está enviando al servidor. La línea de tiempo se muestra a continuación:

  1. Web-trabajador obtiene datos de DB y lo envía al servidor
  2. Mientras que la transferencia está ocurriendo, el usuario actualiza los datos de guardarlo en la base de datos.
  3. La web trabajador recibe la respuesta desde el servidor y actualiza la base de datos a "Sent"
  4. ahora hay datos en la base de datos que no han sido enviados al servidor, pero marcados como "Enviado"

Solución fallida: Después de obtener la respuesta del servidor, puedo volver a verificar para ver si se ha cambiado algo. Sin embargo, aún me queda una pequeña ventana donde los datos se pueden escribir en la base de datos y nunca se enviarán al servidor.

Ejemplo: Después servidor dice que los datos se guarda, entonces:

IndexedDB.HasDataChanged(
    function(changed) { 
     // Since this is async, this changed boolean could be lying. 
     // The data might have been updated after I checked and before I was called. 
     if (!changed){ 
      IndexedDB.UpdateToSent() } 
    }); 

Otras notas: No es una API de sincronización de acuerdo con la especificación W3, pero nadie lo ha implementado todavía, así que puede no ser utilizado (http://www.w3.org/TR/IndexedDB/#sync-database). La API de sincronización fue diseñada para ser utilizada por web-workers, para evitar esta situación exacta, supongo.

Cualquier idea sobre esto sería muy apreciada. Han estado trabajando en ello durante aproximadamente una semana y no han podido encontrar nada que funcione.

Respuesta

2

Creo que encontré un trabajo alrededor de esto por ahora. No es tan limpio como me gustaría, pero parece ser seguro para subprocesos.

Empiezo por almacenar la fecha y hora en un campo LastEdit, cada vez que actualizo los datos. Desde el web-worker, estoy publicando un mensaje en el navegador.

self.postMessage('UpdateDataSent#' + data.ID + '#' + data.LastEdit); 

Luego, en el navegador estoy actualizando mi bandera enviada, siempre que la última fecha de edición no haya cambiado.

// Get the data from the DB in a transaction 
if (data.LastEdit == lastEdit) 
{ 
    data.Sent = true; 
    var saveStore = trans.objectStore("Data"); 
    var saveRequest = saveStore.put(data); 
    console.log('Data updated to Sent'); 
} 

Dado que todo esto se hace en una transacción en el lado del navegador, parece que funciona bien. Una vez que los navegadores soportan la API Sync, puedo descartarlo de todos modos.

Cuestiones relacionadas