Envíos y sincronización
Cómo viajan los registros desde Apple Salud hasta tus servidores, qué significan los estados y qué promete Courier (y qué, honestamente, no promete) sobre los tiempos.
Disparadores
- Entrega en segundo plano — Apple Salud recibe nuevos datos de sueño o entrenamiento e iOS despierta brevemente a Courier; este lee la diferencia y envía.
- Abrir la app — sincronización en primer plano al arrancar y al volver.
- Manual — las acciones de envío dentro de la app, o el atajo Enviar ahora.
- Envío por lotes — La redacción → Envío por lotes: elige un rango de fechas y rellena el histórico hacia cualquier suscriptor.
Los cuatro alimentan el mismo pipeline.
Estados de los elementos
Cada registro saliente pasa por una máquina de estados explícita, persistida para que un cierre forzado o un reinicio no le pierdan la pista:
| Estado | Significado |
|---|---|
queued | Esperando su turno |
awaitingRoute | Entrenamiento al aire libre cuyo trazado GPS aún no ha llegado desde el Watch — Courier espera antes que enviar un registro incompleto |
sending | Petición en vuelo |
sent | Entregado (2xx). Anotado en el registro |
failed | Fallido y confirmado — nunca se reintentará automáticamente; usa el reenvío manual |
needsAttention | Fallido/incompleto y aún sin confirmar: reintentos agotados, la ruta nunca llegó, o los datos de origen desaparecieron. Punto rojo + notificación |
Reintentos
- Los envíos en primer plano reintentan los errores de red con retroceso exponencial (2 s → 4 s → 8 s → 16 s).
- Los envíos en segundo plano tienen un único intento con un tiempo límite de 15 segundos — el tiempo en segundo plano de iOS es escaso y Courier no juega con él. Los fallos simplemente pasan a la cola de atención.
- Nada se reintenta jamás de forma automática una vez que llega a
failed— tú mantienes el control de lo que se reenvía.
Idempotencia
Cada petición lleva una cabecera Idempotency-Key:
- Los envíos normales y los reintentos manuales usan el
idcanonical estable del registro — un endpoint que deduplique por clave nunca guardará el mismo entrenamiento dos veces, por muchas veces que se reintente la entrega. - Los duplicados deliberados ("enviar otra copia") rotan la clave a
id#2,id#3, … para que los endpoints idempotentes puedan aceptar igualmente las copias intencionadas.
Si tu servidor respeta Idempotency-Key (o hace upsert por data.id), todo el pipeline se vuelve seguro de reintentar en cualquier punto.
El registro
La redacción → Historial de envíos muestra cada envío con marca de tiempo, suscriptor, código de estado HTTP y un fragmento de la respuesta. El registro conserva 6 meses de historial; las entradas más antiguas se limpian automáticamente — el contenido entregado, por supuesto, sigue viviendo en tus endpoints.
Los tiempos, con honestidad
La entrega en segundo plano está regulada por iOS. Cuenta con un retraso de entre unos minutos y alrededor de una hora y, en el peor de los casos, el envío ocurre la próxima vez que abras la app. Courier lo dice claramente en los textos de su interfaz en lugar de fingir que es instantáneo. Si necesitas un envío garantizado ahora mismo: abre la app, o usa el atajo Enviar ahora.
Notificaciones
Dos modos (La redacción → Notificaciones):
- Siempre — una notificación resumen tras cada ronda de envío automático, con éxito o con fallo. Por defecto.
- Solo fallos — silencio salvo que algo te necesite.
Las notificaciones requieren el permiso del sistema; si fue denegado, Courier muestra el estado real y un acceso directo a los ajustes de iOS en lugar de fingir que funciona.