6.3 Reconnect automático Evolution antes de abrir incident

Fluxo novo no heartbeat-check quando threshold vence:
1. Verifica se reconnect está habilitado (metadata.heartbeat_reconnect_
   enabled, default true) E se API respondeu (sem fetchError) E se
   passou do cooldown de 10min desde a última tentativa.
2. POST /instance/restart/{instance} na Evolution.
3. Aguarda 3s pra estabilizar + rechecka connectionState.
4. Se state voltou pra 'open': restaura connected + limpa
   first_unhealthy_at + incrementa heartbeat_reconnect_count + resolve
   qualquer incident aberto. Retorna action='auto_reconnected'.
5. Senão: atualiza heartbeat_reconnect_last_at (respeita cooldown) e
   abre incident normalmente com details.reconnect_attempted=true.

Anti-loop: 1 tentativa por ciclo (não retry), cooldown de 10min/channel
pra não martelar Evolution nem gerar restart infinito. Tentativas são
contadas em metadata.heartbeat_reconnect_count (auditoria futura).

UI em /configuracoes/whatsapp-pessoal ganha novo toggle no card de
Monitoramento: "Tentar reconectar automaticamente" (default ligado)
com explicação clara. Tenant pode desligar se preferir ser alertado
imediato sem tentativa.

Summary do endpoint agora inclui auto_reconnected count — útil pra
métricas de confiabilidade da Evolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-04-23 12:19:52 -03:00
parent 0f643817c2
commit 4e4bac622c
2 changed files with 102 additions and 7 deletions
@@ -218,7 +218,11 @@ async function checkConnectionStatus() {
// ──────────────────────────────────────────────────────────────
// Monitoramento de conexão (Heartbeat — Grupo 6.1)
// ──────────────────────────────────────────────────────────────
const heartbeatConfig = ref({ threshold_minutes: 5, alerts_enabled: true });
const heartbeatConfig = ref({
threshold_minutes: 5,
alerts_enabled: true,
reconnect_enabled: true
});
const heartbeatConfigSaving = ref(false);
const incidents = ref([]);
const incidentsLoading = ref(false);
@@ -228,7 +232,8 @@ async function loadHeartbeatConfig() {
const meta = channelRecord.value.metadata || {};
heartbeatConfig.value = {
threshold_minutes: Number(meta.heartbeat_threshold_minutes) || 5,
alerts_enabled: meta.heartbeat_alerts_enabled !== false
alerts_enabled: meta.heartbeat_alerts_enabled !== false,
reconnect_enabled: meta.heartbeat_reconnect_enabled !== false
};
}
@@ -240,7 +245,8 @@ async function saveHeartbeatConfig() {
const newMeta = {
...(channelRecord.value.metadata || {}),
heartbeat_threshold_minutes: threshold,
heartbeat_alerts_enabled: !!heartbeatConfig.value.alerts_enabled
heartbeat_alerts_enabled: !!heartbeatConfig.value.alerts_enabled,
heartbeat_reconnect_enabled: !!heartbeatConfig.value.reconnect_enabled
};
const { error } = await supabase
.from('notification_channels')
@@ -868,6 +874,15 @@ onBeforeUnmount(() => {
</div>
</div>
<!-- Reconnect automático -->
<div class="flex items-start gap-2 pt-2 border-t border-[var(--surface-border)]">
<ToggleSwitch v-model="heartbeatConfig.reconnect_enabled" inputId="hb-reconnect" />
<label for="hb-reconnect" class="text-sm cursor-pointer select-none flex-1">
<span class="font-semibold">Tentar reconectar automaticamente</span>
<span class="block text-xs text-[var(--text-color-secondary)]">Antes de abrir um alerta, o sistema pede à Evolution pra restaurar a sessão. Se funcionar, ninguém é incomodado. Máximo 1 tentativa a cada 10 minutos.</span>
</label>
</div>
<!-- Histórico de incidents -->
<div class="border-t border-[var(--surface-border)] pt-3">
<div class="text-xs font-semibold uppercase tracking-wide text-[var(--text-color-secondary)] mb-2">