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
| Archivo | Rol |
|---|---|
model/interfaces/IOffline.ts | Interfaces: OfflineData, Request, RequestOpts, ValidMethods |
services/offline/offline.service.ts | Lógica central: encolado, envío secuencial, manejo de errores, jerarquía |
services/offline/offline.store.ts | Estado en memoria: colas, flags de envío, jerarquías |
services/http/offline/offline.service.ts | HTTP: ejecuta cada Request individual y envía snapshot al backend |
services/connectivity/connectivity.service.ts | Detecta cambios de conectividad (polling cada 20s + listener nativo) |
services/storage-wrapper/swrapper.service.ts | Persistencia en SQLite particionada por usuario |
utils/consts/functions/sync/offlineDataToApi.ts | Transforma 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": [...] }
}