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

Este tópico inclui as seguintes seções:


Visão geral

A plataforma Vonage Video monitora continuamente todos os serviços em execução. Quando uma falha interna afeta um serviço — como uma falha no servidor de mídia, uma falha no arquivador, a indisponibilidade de um nó de transmissão, um problema no gateway SIP ou uma falha no mecanismo de legendas —, o sistema de monitoramento da plataforma detecta a falha, atualiza o status do serviço e envia imediatamente uma notificação de retorno de chamada para o seu terminal registrado.

Este guia explica quais callbacks cada serviço emite em caso de interrupção, como são as cargas de dados e como recuperar cada serviço por meio de programação.

Interrupções no serviço podem afetar qualquer um dos seguintes serviços de vídeo da Vonage:

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")

Em todos os casos, o reason O campo no Callback Payload é normalmente definir como "Internal server failure". Outros valores de motivo podem aparecer, dependendo da natureza da falha; portanto, seu código de recuperação deve tratar qualquer encerramento inesperado (não causado por suas próprias chamadas de API) como uma possível interrupção.

Observação: A plataforma também envia alertas prévios sobre interrupções para as rotações de servidores (reason: "serverRotation") por meio do sessionNotification evento. Veja Rotação de servidores e migração de sessões para obter mais detalhes sobre esse cenário específico.


Pré-requisitos

Para receber chamadas de retorno em caso de interrupções no lado do servidor, é necessário registrar um Callback de monitoramento de sessão URL para o seu projeto. Veja Monitoramento de sessões para obter instruções de configuração.

Para callbacks de status de arquivo, transmissão e legendas, configure a URL de callback de status correspondente em seu Painel do projeto da Video API da Vonage.


Interrupção da sessão

Quando o Media Router que hospeda uma sessão apresenta falha, a sessão é encerrada e a plataforma envia um sessionDestroyed evento para o seu endpoint de monitoramento de sessão.

Carga útil da chamada de retorno

sessionDestroyed

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

Eventos do Client SDK

Paralelamente aos webhooks do lado do servidor, os clientes recebem eventos do ciclo de vida por meio do 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 SDKs nativos, use os métodos delegados equivalentes:

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

Recuperação

Quando sessionDisconnected incêndios com reason: "forceDisconnected" (ou depois de sessionReconnecting tempo limite):

  1. Crie uma nova sessão por meio da API REST ou de um SDK de servidor.
  2. Emitir novos tokens para todos os participantes.
  3. Notifique os clientes para que se reconectem — por meio de seu próprio canal de notificação, notificação push ou mensagem no aplicativo.
// 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);
});

Dica: Se Migração de sessão estiver ativada, a plataforma poderá recuperar a sessão automaticamente. Nesse caso sessionReconnected é reiniciado no cliente e não é necessário reiniciar manualmente.


Interrupção no arquivo (gravação)

Quando um processo de arquivamento trava no meio da gravação, o sistema de monitoramento da plataforma detecta a falha e marca o arquivo como "failed", e envia uma resposta de status para a URL de status do seu arquivo registrada.

Carga útil da chamada 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 principais:

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

Recuperação

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);
});

Observação: Sempre verifique se a sessão ainda tem participantes ativos antes de reiniciar o arquivamento. Iniciar um arquivamento em uma sessão vazia resultará em um erro.


Interrupção na transmissão

Quando um nó de transmissão apresenta falha, o stream HLS ou RTMP é encerrado e a transmissão é marcada como "failed". Uma resposta de status é enviada para a sua URL de status de transmissão.

Carga útil da chamada 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"
}

Recuperação

  1. Receba o "failed" callback de status.
  2. Aguarde até que os clientes tenham se reconectado à sessão (verifique se há connectionCreated eventos, ou participantes de sessões de enquete).
  3. Iniciar uma nova transmissão:
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: A URL do HLS muda a cada nova transmissão. Certifique-se de atualizar todos os reprodutores ou sistemas a jusante que utilizam o stream com a nova URL.


Interrupção da chamada SIP

Quando uma falha no gateway SIP interrompe um trecho de chamada ativo, a conexão SIP é encerrada e a plataforma envia callDestroyed ao seu endpoint de monitoramento de sessão com reason_message: "Unexpected Clearing".

Carga útil da chamada 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
  }
}

Recuperação

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);
});

Interrupção nas legendas

Quando o mecanismo de legendas apresenta falha, a transcrição ao vivo é interrompida e a sessão de legendas é marcada como "failed". Uma resposta de status é enviada para a URL de status das suas legendas.

Carga útil da chamada 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"
}

Recuperação

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);
});

Melhores práticas

  • Sempre verifique o reason campo, mas não confie exclusivamente nisso. Embora as interrupções normalmente acarretem "Internal server failure", sua lógica de recuperação deve tratar qualquer situação inesperada "failed" status ou <something>Destroyed evento como uma possível ruptura na plataforma.
  • Implementar manipuladores de recuperação idempotentes. As chamadas de retorno podem ser entregues mais de uma vez. Use o ID do recurso (archive.id, captionsId, session.id) para realizar a deduplicação.
  • Utilize avisos de pré-rotação. O sessionNotification evento (com remainingTime: 3600 ou 14400) avisa com antecedência sobre as rotações planejadas. Use-o para interromper de forma controlada arquivos, transmissões e legendas antes da rotação, evitando uma interrupção brusca "forceDisconnected" rescisão.
  • Registrar todos os eventos de interrupção com toda a sua carga útil para análise pós-incidente. O timestamp Esse campo é a sua referência para calcular a duração do impacto.
  • Para sessões, opte pela Migração de Sessões. A ativação da migração de sessão reduz drasticamente o alcance das falhas do Media Router, ao transferir os clientes de forma transparente para um servidor em bom estado. Veja Rotação de servidores e migração de sessões.
  • Configure alertas em "Internal server failure" callbacks. Um aumento repentino em Internal server failure A ocorrência de eventos em várias sessões é um sinal precoce de um incidente mais abrangente na plataforma.

Veja também