Saltar al contenido principal

Sistema de Sincronización Offline — Overview

Resumen

La app mobile (Capacitor + Angular + Ionic) implementa un sistema de queue offline para operaciones de escritura (POST, PUT, PATCH, DELETE). Cuando el dispositivo pierde conexión, las peticiones se encolan localmente en SQLite y se reenvían una a una al recuperar conectividad.

Flujo general

Usuario realiza acción (ej: crear lote)


Servicio de dominio (FarmHttpService, ScoutingService, etc.)


OfflineService.post/put/patch/delete/putf()


Se encola en OfflineStore.data.requestQueue[sender]


Se persiste en SQLite via SWrapperService (key: "offline")


Se intenta enviar inmediatamente (sendNext)

├── OK → se elimina de la cola, se envía la siguiente

└── Error de conexión / timeout → queda en cola


Al recuperar conexión (ConnectivityService.connectivityChanged)


OfflineService.trySync() → itera y reenvía request por request

Componentes clave

ArchivoRol
model/interfaces/IOffline.tsInterfaces: OfflineData, Request, RequestOpts, ValidMethods
services/offline/offline.service.tsLógica central: encolado, envío secuencial, manejo de errores, jerarquía
services/offline/offline.store.tsEstado en memoria: colas, flags de envío, jerarquías
services/http/offline/offline.service.tsHTTP: ejecuta cada Request individual y envía snapshot al backend
services/connectivity/connectivity.service.tsDetecta cambios de conectividad (polling cada 20s + listener nativo)
services/storage-wrapper/swrapper.service.tsPersistencia en SQLite particionada por usuario
utils/consts/functions/sync/offlineDataToApi.tsTransforma OfflineData al formato que se envía a /sync_pending
pages/sync/UI de sincronización: progreso, errores, cola pendiente, eliminados

Persistencia

Los datos offline se guardan en SQLite bajo la key "offline" dentro de la tabla del usuario (U{userId}). La estructura persistida es:

interface OfflineData {
requestQueue: { [sender: string]: Array<Request> };
removedQueue: { [sender: string]: Array<Request> };
transactionId: number; // autoincremental, ID único por request
}

Trigger de sincronización

En app.component.ts:

this.connectivityService.connectivityChanged.subscribe(offline => {
if (!offline) {
this.offlineService.trySync();
}
});

Endpoint de snapshot

Además del envío request-por-request, existe un endpoint POST /sync_pending que recibe un snapshot del estado completo de las colas (pendientes + eliminadas). Se invoca cada vez que se mueve una request a removedQueue o se restaura una. El payload es:

{
"request_pending": { "sender1": [...], "sender2": [...] },
"request_removed": { "sender1": [...], "sender2": [...] }
}