How to receive service disruption callbacks and recover each affected service after an internal platform failure.

Este tema incluye las siguientes secciones:


Visión general

La plataforma Vonage Video supervisa continuamente todos los servicios en ejecución. Cuando un fallo interno afecta a un servicio —como un fallo del servidor multimedia, un fallo del archivador, la caída de un nodo de difusión, un problema con la pasarela SIP o un fallo del motor de subtítulos—, el sistema de supervisión de la plataforma detecta el fallo, actualiza el estado del servicio y envía inmediatamente una notificación de devolución de llamada a tu terminal registrado.

Esta guía explica qué funciones de devolución de llamada emite cada servicio en caso de interrupción, cómo son las cargas útiles y cómo recuperar cada servicio mediante programación.

Las interrupciones del servicio pueden afectar a cualquiera de los siguientes servicios de Vonage Video:

Service What is disrupted Primary callback mechanism
Sessions Media Router crashes; participant connections and streams are terminated Server-side session monitoring webhook + client SDK events
Archives (Recordings) Archiver process crashes; the recording is terminated abnormally Archive status webhook ("status": "failed")
Broadcasts Broadcast node fails; the HLS/RTMP stream is terminated Broadcast status webhook ("status": "failed")
SIP Calls SIP gateway fails; the call leg is dropped Session monitoring webhook callDestroyed
Captions Captions engine fails; live transcription stops Captions status webhook ("status": "failed")

En todos los casos, el reason El campo en la carga útil de la llamada de retorno es normalmente establecer en "Internal server failure". Pueden aparecer otros valores de motivo en función de la naturaleza del error, por lo que tu código de recuperación debería tratar cualquier interrupción inesperada (que no esté provocada por tus propias llamadas a la API) como una posible interrupción del servicio.

Nota: La plataforma también envía avisos previos a las interrupciones por rotaciones de servidores (reason: "serverRotation") a través de la sessionNotification evento. Véase Rotación de servidores y migración de sesiones para obtener más información sobre ese caso concreto.


Requisitos previos

Para recibir notificaciones de interrupciones del lado del servidor, debes registrar un Llamada de retorno de la supervisión de sesiones URL para tu proyecto. Consulta Control de la sesión para obtener instrucciones de configuración.

Para las notificaciones de estado de archivos, emisiones y subtítulos, configura la URL de notificación de estado correspondiente en tu Panel de control del proyecto de la Video API de Vonage.


Interrupción de la sesión

Cuando el Media Router que aloja una sesión se bloquea, la sesión se cancela y la plataforma envía un sessionDestroyed evento al punto final de supervisión de tu sesión.

Carga útil de la llamada de retorno

sessionDestroyed

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "event": "sessionDestroyed",
  "reason": "forceDisconnected",
  "timestamp": 1718000050000
}

Eventos del Client SDK

Paralelamente a los webhooks del lado del servidor, los clientes reciben eventos del ciclo de vida a través del SDK:

session.on('sessionReconnecting', () => {
  // Platform is attempting automatic reconnection via session migration
  showReconnectingBanner();
});

session.on('sessionReconnected', () => {
  // Automatic recovery succeeded — no further action needed
  hideReconnectingBanner();
});

session.on('sessionDisconnected', (event) => {
  // Automatic recovery failed or is not enabled
  if (event.reason === 'networkDisconnected' || event.reason === 'networkTimedout') {
    promptUserToRejoin();
  }
});

publisher.on('streamDestroyed', (event) => {
  if (event.reason === 'networkDisconnected') {
    event.preventDefault(); // Keep the publisher element in the DOM
    retryPublish();
  }
});

Para los SDK nativos, utiliza los métodos delegados equivalentes:

  • iOS: OTSessionDelegate.sessionDidBeginReconnecting(_:) / sessionDidReconnect(_:) / sessionDidDisconnect(_:)
  • Android: Session.SessionListener.onReconnecting() / onReconnected() / onDisconnected()

Recuperación

En sessionDisconnected incendios con reason: "forceDisconnected" (o después de sessionReconnecting tiempo de espera):

  1. Crea una nueva sesión a través de la API REST o del SDK del servidor.
  2. Emitir tokens nuevos para todos los participantes.
  3. Avisa a los clientes para que vuelvan a conectarse —a través de tu propio canal de notificación, mediante notificaciones push o mediante un mensaje dentro de la aplicación—.
// Server-side — handle sessionDestroyed with reason "forceDisconnected"
app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason, sessionId } = req.body;

  if (event === 'sessionDestroyed' && reason === 'forceDisconnected') {
    createNewSessionAndNotifyClients(sessionId);
  }

  res.sendStatus(200);
});

Consejo: Si Migración de sesiones está activada, la plataforma puede recuperar la sesión automáticamente. En ese caso sessionReconnected se inicia en el cliente y no es necesario volver a conectarse manualmente.


Interrupción del archivo (grabación)

Cuando un proceso de archivado se bloquea en mitad de la grabación, el sistema de supervisión de la plataforma detecta el fallo y marca el archivo como "failed", y envía una notificación de estado a la URL de estado de tu archivo registrada.

Carga útil de la llamada de retorno

{
  "id": "b40ef09b-3811-4726-b508-e41a0f96c68f",
  "event": "archive",
  "status": "failed",
  "reason": "Internal server failure",
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "name": "My Recording",
  "createdAt": 1718000000000,
  "duration": 0,
  "outputMode": "composed",
  "hasVideo": true,
  "hasAudio": true
}

Campos clave:

Field Value on disruption
status "failed"
reason "Internal server failure"
duration May be 0 if the failure occurred before the first segment was written

Recuperación

app.post('/callbacks/vonage/archive', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Start a new archive for the same session
    opentok.startArchive(sessionId, { name: 'Resumed recording' }, (err, archive) => {
      if (err) console.error('Failed to restart archive:', err);
      else console.log('New archive started:', archive.id);
    });
  }

  res.sendStatus(200);
});

Nota: Verify siempre que la sesión siga teniendo participantes activos antes de reiniciar el archivo. Iniciar un archivo en una sesión vacía provocará un error.


Interrupción de la emisión

Cuando se produce un fallo en un nodo de retransmisión, la transmisión HLS o RTMP se interrumpe y la retransmisión se marca como "failed". Se envía una respuesta de estado a tu URL de estado de difusión.

Carga útil de la llamada de retorno

{
  "id": "1748b707-0a81-464c-9759-c46ad10d3734",
  "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4",
  "applicationId": 100,
  "createdAt": 1437676551000,
  "updatedAt": 1437676551000,
  "event": "broadcast",
  "group": "status",
  "resolution": "640x480",
  "streamMode": "auto",
  "streams": [],
  "broadcastUrls": {
    "hls": "http://server/fakepath/playlist.m3u8",
    "hlsStatus": "error",
    "rtmp": {
      "foo": {
        "serverUrl": "rtmps://myfooserver:443/myfooapp",
        "streamName": "myfoostream",
        "status": "error"
      },
      "bar": {
        "serverUrl": "rtmp://mybarserver:443/mybarapp",
        "streamName": "mybarstream",
        "status": "error"
      }
    }
  },
  "settings": {
    "hls": {
      "dvr": false,
      "lowLatency": false
    }
  },
  "status": "failed",
  "reason": "internal server failure"
}

Recuperación

  1. Recibe el "failed" llamada de retorno de estado.
  2. Espera a que los clientes se hayan vuelto a conectar a la sesión (espera a que se detecte connectionCreated eventos, o participantes en las encuestas).
  3. Iniciar una nueva retransmisión:
app.post('/callbacks/vonage/broadcast', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    waitForParticipants(sessionId).then(() => {
      opentok.startBroadcast(sessionId, broadcastOptions, (err, broadcast) => {
        if (err) console.error('Failed to restart broadcast:', err);
        else notifyViewersOfNewStreamUrl(broadcast.broadcastUrls);
      });
    });
  }

  res.sendStatus(200);
});

Importante: La URL de HLS cambia con cada nueva emisión. Asegúrate de actualizar cualquier reproductor o sistema posterior que utilice la transmisión con la nueva URL.


Interrupción de una llamada SIP

Cuando un fallo en la pasarela SIP provoca la interrupción de un tramo de llamada activo, la conexión SIP se interrumpe y la plataforma envía callDestroyed a tu punto final de supervisión de sesiones con reason_message: "Unexpected Clearing".

Carga útil de la llamada de retorno

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "applicationId": "123456",
  "event": "callDestroyed",
  "reason_code": "703",
  "reason_message": "Unexpected Clearing",
  "timestamp": 1718000050000,
  "call": {
    "id": "<conference-id>",
    "connectionId": "<sip-ot-connection-id>",
    "createdAt": 1470257688143
  }
}

Recuperación

app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason_message, call, sessionId } = req.body;

  if (event === 'callDestroyed' && reason_message === 'Unexpected Clearing') {
    // Re-initiate the SIP call
    const sipUri = getSipUriForCall(call.id);
    opentok.dial(sessionId, token, sipUri, sipOptions, (err, newCall) => {
      if (err) console.error('SIP redial failed:', err);
      else console.log('SIP call re-established:', newCall.id);
    });
  }

  res.sendStatus(200);
});

Interrupción de los subtítulos

Cuando el motor de subtítulos falla, la transcripción en directo se detiene y la sesión de subtítulos se marca como "failed". Se envía una respuesta de estado a la URL de estado de tus subtítulos.

Carga útil de la llamada de retorno

{
  "captionsId": "<captionsId>",
  "projectId": "<applicationId>",
  "sessionId": "<sessionId>",
  "status": "failed",
  "createdAt": 1651253477,
  "updatedAt": 1651253837,
  "duration": 360,
  "languageCode": "en-US",
  "reason": "Internal server failure",
  "provider": "aws-transcribe",
  "event": "sessionStatus"
}

Recuperación

app.post('/callbacks/vonage/captions', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Restart captions for the session
    fetch(`https://video.api.vonage.com/v2/project/${PROJECT_ID}/captions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${jwt}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ sessionId, token: generateToken(sessionId) })
    })
    .then(res => res.json())
    .then(data => console.log('Captions restarted:', data.captionsId))
    .catch(err => console.error('Failed to restart captions:', err));
  }

  res.sendStatus(200);
});

Buenas prácticas

  • Comprueba siempre el reason campo, pero no te bases exclusivamente en ello. Aunque las interrupciones suelen conllevar "Internal server failure", tu lógica de recuperación debería gestionar cualquier "failed" estado o <something>Destroyed acontecimiento como una posible disrupción de la plataforma.
  • Implementar controladores de recuperación idempotentes. Las llamadas de retorno pueden recibirse más de una vez. Utiliza el ID del recurso (archive.id, captionsId, session.id) para eliminar los duplicados.
  • Utiliza las advertencias previas a la rotación. En sessionNotification evento (con remainingTime: 3600 o 14400) te avisa con antelación de las rotaciones previstas. Úsalo para detener de forma ordenada los archivos, las emisiones y los subtítulos antes de la rotación, evitando así un "forceDisconnected" rescisión.
  • Registrar todos los incidentes de interrupción del servicio con toda su carga útil para el análisis posterior al incidente. El timestamp Este campo es el valor de referencia para calcular la duración del impacto.
  • Para las sesiones, es preferible utilizar la migración de sesiones. La activación de la migración de sesiones reduce drásticamente el alcance de los fallos del Media Router, ya que traslada de forma transparente a los clientes a un servidor en buen estado. Ver Rotación de servidores y migración de sesiones.
  • Configura alertas en "Internal server failure" funciones de devolución de llamada. Un repunte en Internal server failure La aparición de eventos a lo largo de varias sesiones es un indicio temprano de un incidente más amplio en la plataforma.

Véase también