Pular para conteúdo

SQS DELETE - Deletar Mensagem da Fila

O que é este Node?

O SQS DELETE é o node responsável por remover permanentemente mensagens processadas de filas do AWS SQS.

Por que este Node existe?

Deletar mensagens após processamento é crucial para evitar duplicatas. O SQS DELETE existe para:

  1. Confirmar processamento: Sinalizar que mensagem foi processada com sucesso
  2. Evitar duplicatas: Impedir que mensagem seja processada novamente
  3. Limpar fila: Manter fila apenas com mensagens pendentes
  4. Controle de custo: Evitar armazenamento desnecessário
  5. Gestão de recursos: Liberar espaço na fila
  6. Auditoria: Confirmar conclusão do processamento

Como funciona internamente?

Quando o SQS DELETE é executado, o sistema:

  1. Autentica na AWS: Usa accessKeyId, secretAccessKey e region
  2. Valida receiptHandle: Verifica se é válido (obtido no receive)
  3. Remove mensagem: Deleta permanentemente da fila
  4. Libera visibilidade: Mensagem não volta mais
  5. Retorna sucesso: Confirma deleção
  6. Se inválido: Lança erro (handle expirado ou inválido)
  7. Se erro: Lança exceção

Código interno (aws-executors.service.ts:129-137):

case 'deleteMessage':
  await sqs.deleteMessage({
    QueueUrl: data.queueUrl,
    ReceiptHandle: data.receiptHandle,
  }).promise();
  return {
    success: true,
    message: 'Message deleted successfully',
  };

Quando você DEVE usar este Node?

Use SQS DELETE sempre que processar mensagem com sucesso:

Casos de uso:

  1. Após processamento: Deletar job executado com sucesso
  2. Confirmação de entrega: Remover após enviar email/notificação
  3. Pipeline concluído: Remover após etapa finalizar
  4. Validação bem-sucedida: Deletar após validar dados
  5. Integração completa: Remover após sincronizar sistemas
  6. Limpeza de fila: Remover mensagens obsoletas
  7. Workflow finalizado: Deletar após completar todas etapas

Quando NÃO usar SQS DELETE:

  • Processamento falhou: Deixe mensagem para retry (ou DLQ)
  • Validação falhou: Não delete se dados inválidos
  • Processamento parcial: Não delete se não completou
  • Auditoria necessária: Mova para fila de auditoria antes

ReceiptHandle: O Identificador Único

O que é: Token único retornado no receiveMessage() que identifica a mensagem.

Características: - Único para cada receive (mesmo MessageId gera handles diferentes) - Expira após visibility timeout - Necessário para deletar - Não pode ser reutilizado

Importante:

// ❌ ERRADO - usar MessageId
deleteMessage({ MessageId: "abc123" })

// ✅ CORRETO - usar ReceiptHandle
deleteMessage({ ReceiptHandle: "AQEBzW...xyz==" })

Parâmetros Detalhados

receiptHandle (string, obrigatório)

O que é: Token único obtido ao receber a mensagem, usado para identificá-la na deleção.

Onde obter: Campo ReceiptHandle da resposta de receiveMessages

Flow completo para testar:

{
  "name": "Teste SQS Delete - Receipt Handle",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "sqs_receive_1",
      "type": "aws_sqs",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Receber Mensagem",
        "parameters": {
          "operation": "receiveMessages",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{sqs_queue_url}}",
          "maxMessages": 1
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Extrair Handle",
        "parameters": {
          "variable": "receiptHandle",
          "value": "{{messages[0].ReceiptHandle}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Processar",
        "parameters": {
          "message": "⚙️ Processando mensagem...\nID: {{messages[0].MessageId}}"
        }
      }
    },
    {
      "id": "delay_1",
      "type": "delay",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Simular Processamento",
        "parameters": {
          "seconds": 5
        }
      }
    },
    {
      "id": "sqs_delete_1",
      "type": "aws_sqs",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Deletar Mensagem",
        "parameters": {
          "operation": "deleteMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{sqs_queue_url}}",
          "receiptHandle": "{{receiptHandle}}"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Mensagem processada e deletada com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "sqs_receive_1" },
    { "source": "sqs_receive_1", "target": "variable_1" },
    { "source": "variable_1", "target": "message_1" },
    { "source": "message_1", "target": "delay_1" },
    { "source": "delay_1", "target": "sqs_delete_1" },
    { "source": "sqs_delete_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Teste: Mensagem é recebida, processada e deletada. Não volta para fila.

queueUrl (string, obrigatório)

O que é: URL completa da fila SQS de onde a mensagem será deletada.

Deve ser a mesma URL usada no receiveMessages

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim Deve ser "deleteMessage"
accessKeyId string Sim AWS Access Key ID
secretAccessKey string Sim AWS Secret Access Key
region string Sim Região AWS
queueUrl string Sim URL da fila SQS
receiptHandle string Sim Token da mensagem (do receive)

Exemplo 1: Processar e Deletar Pedido

Objetivo: Receber pedido, processar e confirmar deleção

JSON para Importar

{
  "name": "Processar e Deletar Pedido",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Iniciar Worker",
        "parameters": {
          "message": "🔄 Worker de pedidos iniciado..."
        }
      }
    },
    {
      "id": "sqs_receive_1",
      "type": "aws_sqs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Buscar Pedido",
        "parameters": {
          "operation": "receiveMessages",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "sa-east-1",
          "queueUrl": "https://sqs.sa-east-1.amazonaws.com/123456789012/orders-queue",
          "maxMessages": 1,
          "waitTimeSeconds": 20,
          "visibilityTimeout": 300
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Tem Pedido?",
        "parameters": {
          "variable": "messages.length",
          "operator": ">",
          "value": "0"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "Extrair Dados",
        "parameters": {
          "variable": "order",
          "value": "{{messages[0].Body}}"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1100, "y": 50 },
      "data": {
        "label": "Processar Pedido",
        "parameters": {
          "message": "📦 Processando pedido {{order.orderId}}\n💰 Valor: R$ {{order.total}}\n👤 Cliente: {{order.customer.name}}"
        }
      }
    },
    {
      "id": "delay_1",
      "type": "delay",
      "position": { "x": 1300, "y": 50 },
      "data": {
        "label": "Simular Processamento",
        "parameters": {
          "seconds": 3
        }
      }
    },
    {
      "id": "sqs_delete_1",
      "type": "aws_sqs",
      "position": { "x": 1500, "y": 50 },
      "data": {
        "label": "Confirmar Processamento",
        "parameters": {
          "operation": "deleteMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "sa-east-1",
          "queueUrl": "https://sqs.sa-east-1.amazonaws.com/123456789012/orders-queue",
          "receiptHandle": "{{messages[0].ReceiptHandle}}"
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 1700, "y": 50 },
      "data": {
        "label": "Sucesso",
        "parameters": {
          "message": "✅ Pedido {{order.orderId}} processado e removido da fila!"
        }
      }
    },
    {
      "id": "message_4",
      "type": "message",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "Fila Vazia",
        "parameters": {
          "message": "📭 Nenhum pedido pendente no momento"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "sqs_receive_1" },
    { "source": "sqs_receive_1", "target": "condition_1" },
    { "source": "condition_1", "target": "variable_1", "label": "true" },
    { "source": "condition_1", "target": "message_4", "label": "false" },
    { "source": "variable_1", "target": "message_2" },
    { "source": "message_2", "target": "delay_1" },
    { "source": "delay_1", "target": "sqs_delete_1" },
    { "source": "sqs_delete_1", "target": "message_3" },
    { "source": "message_3", "target": "end_1" },
    { "source": "message_4", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 🔄 Worker de pedidos iniciado...
Sistema: 📦 Processando pedido ORD-2025-001
💰 Valor: R$ 250.00
👤 Cliente: José Roberto
Sistema: ✅ Pedido ORD-2025-001 processado e removido da fila!

Exemplo 2: Worker com Tratamento de Erro

Objetivo: Deletar apenas se processamento for bem-sucedido

JSON para Importar

{
  "name": "Worker com Tratamento de Erro",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "sqs_receive_1",
      "type": "aws_sqs",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Receber Mensagem",
        "parameters": {
          "operation": "receiveMessages",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{worker_queue_url}}",
          "maxMessages": 1,
          "visibilityTimeout": 120
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Parse Body",
        "parameters": {
          "variable": "messageBody",
          "value": "{{messages[0].Body}}"
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Validar Dados",
        "parameters": {
          "variable": "messageBody.orderId",
          "operator": "exists",
          "value": "true"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "Processar",
        "parameters": {
          "message": "✅ Dados válidos - processando..."
        }
      }
    },
    {
      "id": "sqs_delete_1",
      "type": "aws_sqs",
      "position": { "x": 1100, "y": 50 },
      "data": {
        "label": "Deletar (Sucesso)",
        "parameters": {
          "operation": "deleteMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{worker_queue_url}}",
          "receiptHandle": "{{messages[0].ReceiptHandle}}"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 50 },
      "data": {
        "label": "Confirmar Sucesso",
        "parameters": {
          "message": "✅ Processado e removido da fila!"
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "Erro Validação",
        "parameters": {
          "message": "❌ Dados inválidos - mensagem volta para fila após timeout"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "sqs_receive_1" },
    { "source": "sqs_receive_1", "target": "variable_1" },
    { "source": "variable_1", "target": "condition_1" },
    { "source": "condition_1", "target": "message_1", "label": "true" },
    { "source": "condition_1", "target": "message_3", "label": "false" },
    { "source": "message_1", "target": "sqs_delete_1" },
    { "source": "sqs_delete_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" },
    { "source": "message_3", "target": "end_1" }
  ]
}

Saída esperada (sucesso):

Sistema: ✅ Dados válidos - processando...
Sistema: ✅ Processado e removido da fila!

Saída esperada (erro):

Sistema: ❌ Dados inválidos - mensagem volta para fila após timeout

Resposta do Node

{
  "success": true,
  "message": "Message deleted successfully"
}

Fluxo: Receive → Process → Delete

┌─────────────────────────────────────────────┐
│ 1. receiveMessage()                         │
│    → Mensagem fica invisível                │
│    → Retorna ReceiptHandle                  │
└─────────────────┬───────────────────────────┘
                  ↓
┌─────────────────────────────────────────────┐
│ 2. Processar mensagem                       │
│    → Validar dados                          │
│    → Executar lógica de negócio             │
│    → Salvar resultados                      │
└─────────────────┬───────────────────────────┘
                  ↓
          ┌───────┴────────┐
          │  Sucesso?      │
          └───────┬────────┘
         Sim ↓        ↓ Não
┌────────────────┐  ┌──────────────────────┐
│ 3. deleteMessage│  │ Não deletar          │
│    (ReceiptHandle)│  │ → Volta após timeout │
└────────────────┘  └──────────────────────┘
         ↓
┌─────────────────────────────────────────────┐
│ Mensagem REMOVIDA permanentemente           │
└─────────────────────────────────────────────┘

Erros Comuns

ReceiptHandle Inválido

Erro: ReceiptHandleIsInvalid
Causa: Handle expirou após visibility timeout
Solução: Aumente visibilityTimeout ou processe mais rápido

Mensagem Não Existe

Erro: Message does not exist
Causa: Mensagem já foi deletada ou expirou
Solução: Verifique se não está deletando duplicado

Fila Não Encontrada

Erro: AWS.SimpleQueueService.NonExistentQueue
Causa: queueUrl incorreta
Solução: Verifique URL da fila

Boas Práticas

SIM:

  • Delete APENAS após processamento bem-sucedido
  • Salve ReceiptHandle ao receber mensagem
  • Configure visibilityTimeout > tempo processamento
  • Implemente DLQ para mensagens problemáticas
  • Use try-catch ao redor do delete
  • Valide dados ANTES de deletar
  • Log antes de deletar (auditoria)
  • Configure maxReceiveCount apropriado

NÃO:

  • Não delete antes de processar completamente
  • Não delete se validação falhou
  • Não use MessageId (use ReceiptHandle)
  • Não delete sem try-catch
  • Não ignore erros de deleção
  • Não reutilize ReceiptHandle expirado
  • Não delete sem confirmar sucesso

Padrão Recomendado

try {
  // 1. Receive
  const result = await receiveMessages();
  const message = result.messages[0];
  const receiptHandle = message.ReceiptHandle;

  // 2. Process
  const data = JSON.parse(message.Body);
  await processOrder(data);

  // 3. Delete (apenas se sucesso)
  await deleteMessage({ receiptHandle });

} catch (error) {
  // Não delete - mensagem volta para fila
  console.error('Processing failed:', error);
  // Após maxReceiveCount tentativas → DLQ
}

Dicas

💡 Idempotência: Prepare-se para processar a mesma mensagem múltiplas vezes

💡 Auditoria: Log messageId antes de deletar para rastreamento

💡 Timeout: visibility > tempo de processamento + margem de segurança

💡 DLQ: Configure para capturar mensagens que falham repetidamente

💡 Batch Delete: Use deleteMessageBatch() para deletar múltiplas (até 10)

Próximo Node

SQS SEND - Enviar mensagem para fila → SQS RECEIVE - Receber mensagens da fila → SNS PUBLISH - Publicar em tópico SNS