Ir al contenido principal
Versión: 4.x

Garantías de entrega

Orden de los mensajes​

Socket.IO garantiza el orden de los mensajes, sin importar qué transporte de bajo nivel se utilice (incluso durante una actualización de HTTP long-polling a WebSocket).

Esto se logra gracias a:

Ejemplo:

socket.emit("event1");
socket.emit("event2");
socket.emit("event3");

En el ejemplo anterior, los eventos siempre serán recibidos en el mismo orden por el otro lado (siempre que realmente lleguen, ver abajo).

Llegada de mensajes​

Como máximo una vez​

Por defecto, Socket.IO proporciona una garantía de entrega de como máximo una vez:

  • si la conexión se interrumpe mientras se envía un evento, entonces no hay garantía de que el otro lado lo haya recibido y no habrá reintento tras la reconexión
  • un cliente desconectado almacenará eventos en búfer hasta la reconexión (aunque el punto anterior sigue aplicando)
  • no hay tal búfer en el servidor, lo que significa que cualquier evento que haya perdido un cliente desconectado no será transmitido a ese cliente tras la reconexión
información

Actualmente, garantías de entrega adicionales deben implementarse en tu aplicación.

Al menos una vez​

Del cliente al servidor​

Desde el lado del cliente, puedes lograr una garantía de al menos una vez con la opción retries:

const socket = io({
retries: 3,
ackTimeout: 10000
});

El cliente intentará enviar el evento (hasta retries + 1 veces), hasta que obtenga una confirmación del servidor.

precaución

Incluso en ese caso, cualquier evento pendiente se perderá si el usuario actualiza su pestaña.

Del servidor al cliente​

Para eventos enviados por el servidor, garantías de entrega adicionales pueden implementarse:

  • asignando un ID único a cada evento
  • persistiendo los eventos en una base de datos
  • almacenando el offset del último evento recibido en el lado del cliente, y enviándolo tras la reconexión

Ejemplo:

Cliente

const socket = io({
auth: {
offset: undefined
}
});

socket.on("my-event", ({ id, data }) => {
// hacer algo con los datos, y luego actualizar el offset
socket.auth.offset = id;
});

Servidor

io.on("connection", async (socket) => {
const offset = socket.handshake.auth.offset;
if (offset) {
// esto es una reconexión
for (const event of await fetchMissedEventsFromDatabase(offset)) {
socket.emit("my-event", event);
}
} else {
// esta es una primera conexión
}
});

setInterval(async () => {
const event = {
id: generateUniqueId(),
data: new Date().toISOString()
}

await persistEventToDatabase(event);
io.emit("my-event", event);
}, 1000);

Implementar los métodos faltantes (fetchMissedEventsFromDatabase(), generateUniqueId() y persistEventToDatabase()) es específico de la base de datos y se deja como ejercicio para el lector.

Referencias: