Volver al blogDesarrollo 4 min de lectura

Cómo sincroniza TerraCore cuando no hay señal

Base local, cola de cambios, versiones por registro y ajustes de inventario como diferencia: las decisiones detrás del modo sin conexión de TerraCore.

Cómo sincroniza TerraCore cuando no hay señal

Una app que solo funciona con internet no sirve en un potrero. Alguien registra una vacuna a las seis de la mañana, sin señal, y espera que el dato siga ahí cuando vuelva a la casa.

Guardar localmente es la parte fácil. Lo difícil empieza cuando dos dispositivos editan lo mismo sin haberse visto, y toca decidir qué dato gana sin pisar el trabajo de nadie.

Qué funciona sin conexión

TerraCore es una aplicación web instalable como PWA. Funcionan sin conexión Animales, Cultivos, Insumos, Producción, Salud animal (las vacunas), Sedes y el Panel. Las cifras de Finanzas se recalculan en el dispositivo y la pantalla lo avisa.

Hay cosas que siempre necesitan red, por su naturaleza: iniciar sesión, registrarse, restablecer la contraseña y todo lo que tenga que ver con pagar. La primera vez que se abre la app en un dispositivo también hace falta conexión.

Base local y cola de cambios

En el navegador, los datos viven en IndexedDB a través de Dexie. Los cambios que todavía no llegaron al servidor esperan en una cola de salida, el outbox.

Esa cola se envía cada 60 segundos mientras la app está abierta y cada vez que vuelve la conexión. Además, cada dispositivo hace una descarga completa cada 24 horas.

El Panel se calcula entero en el navegador, a partir de esa base local, y no consulta un resumen ya armado en el servidor. Por eso también funciona sin red. Otras escrituras, como invitar a un usuario o cambiar el perfil, se encolan igual y se envían cuando hay conexión.

Una versión por registro

Para detectar conflictos, cada registro lleva un número de versión. Cualquier edición lo sube, venga de la sincronización o de la API normal, y no solo las que se hacen sin conexión.

Cuando el cliente envía un cambio, manda también la versión sobre la que trabajó. El servidor compara y responde con tres listas:

{
  "accepted": [],
  "conflicts": [],
  "rejected": []
}
  • accepted: el cambio se aplicó.
  • conflicts: el registro cambió en el servidor desde la copia del cliente. El servidor no aplica el cambio viejo.
  • rejected: el cambio no es válido, y la respuesta trae el motivo.

La clave está en el segundo grupo: una copia vieja que llega tarde no pisa lo que otra persona ya guardó.

No perder lo que se editó mientras tanto

Hay un caso incómodo: la persona edita un registro mientras su envío anterior sigue en camino, y el servidor lo devuelve como conflicto o rechazo.

Si el cliente descartara todo, esa última edición se perdería. En cambio, la conserva y la reenvía sobre la copia que ahora tiene el servidor.

Los rechazos, además, no se reintentan solos. Se guardan en su propia tabla local y la persona solo puede descartarlos, para que una escritura inválida no se quede en la cola intentando enviarse para siempre.

Inventario como diferencia, no como valor

Este es el ejemplo que mejor explica el problema. Dos personas ajustan el mismo insumo sin conexión: una resta 10 kilos porque dio concentrado, otra suma 25 porque llegó una compra.

Si cada una enviara el valor final de stock, la última en sincronizar borraría el ajuste de la otra. Por eso los ajustes viajan como una diferencia relativa a una base. Restar 10 y sumar 25 se componen, sin importar el orden.

El servidor refuerza la misma idea: si llega una cantidad absoluta desde un cliente cuya copia es más vieja que la del servidor, no la aplica y devuelve el registro como conflicto.

Traer los cambios sin traer todo

El camino de vuelta, del servidor al dispositivo, tiene su propio cuidado. Las descargas se paginan por cursor, para no bajar todo de una vez.

La descarga completa, sin cursor, también elimina las filas locales que el servidor ya no devuelve. Es la forma de que un registro borrado desaparezca del dispositivo.

Y al cambiar de usuario en el mismo equipo, los datos locales de la persona anterior se limpian. Un celular compartido en la finca no puede dejar visible el trabajo de otro.

Lo que aprendimos probando esto

Los errores de sincronización casi nunca aparecen en un test feliz. Aparecen con dos dispositivos y un envío a medias. Por eso probamos las guardas y la sincronización con el enrutador real de la aplicación y una base local simulada, y cada corrección de este tipo debe traer pruebas que fallen sin el cambio.

La idea que nos dejó este trabajo cabe en una frase: en un sistema offline, lo que se envía no es el valor que quedó, sino lo que cambió y sobre qué versión.


Comentarios

0 respuestas

Todavía no hay comentarios. Abre la conversación.