perf(whatsapp): índices em FKs + delete de instância em lotes

- Adiciona @@index nas FKs que sofrem cascade/SET NULL ao deletar instância:
  messages.replyToId (self-ref, evitava O(n²) no SET NULL), chats.instanceId,
  chats.contactId, contacts.instanceId, broadcasts.instanceId.
- InstanceRepository.delete agora apaga 'messages' em lotes (5k) antes do
  cascade, evitando transação/locks gigantes em instâncias com dezenas de
  milhares de mensagens. O restante (chats/contacts/...) sai pelo cascade,
  agora rápido com os índices.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Deploy Agent
2026-06-27 18:58:06 +02:00
parent e4a7e79ab1
commit 7124ec790e
2 changed files with 25 additions and 0 deletions
@@ -175,6 +175,8 @@ model Contact {
@@unique([tenantId, instanceId, jid])
@@index([tenantId, instanceId, lidJid])
// FK dedicada — acelera o cascade ao deletar a instância
@@index([instanceId])
@@map("contacts")
}
@@ -207,6 +209,9 @@ model Chat {
// WHERE tenantId + instanceId + isArchived (filtro)
// ORDER BY isPinned DESC, lastMessageAt DESC (ordenação)
@@index([tenantId, instanceId, isArchived, isPinned(sort: Desc), lastMessageAt(sort: Desc)])
// FKs dedicadas — sem elas o cascade/SET NULL ao deletar instância/contato faz full-scan
@@index([instanceId])
@@index([contactId])
@@map("chats")
}
@@ -251,6 +256,8 @@ model Message {
@@index([instanceId, fromMe, remoteJid, timestamp(sort: Desc)])
// Índice para obter a última mensagem da instância — usado na verificação de gap de sincronização
@@index([instanceId, timestamp(sort: Desc)])
// FK self-referente — sem índice o cascade roda UPDATE replyToId=NULL com full-scan (O(n²))
@@index([replyToId])
@@map("messages")
}
@@ -385,6 +392,8 @@ model Broadcast {
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
recipients BroadcastRecipient[]
// FK dedicada — acelera o cascade ao deletar a instância
@@index([instanceId])
@@map("broadcasts")
}