Pular para conteúdo

SQS SEND - Enviar Mensagem para Fila

O que é este Node?

O SQS SEND é o node responsável por enviar mensagens para filas do AWS SQS (Simple Queue Service) de forma assíncrona e confiável.

Por que este Node existe?

Processar tarefas de forma assíncrona é essencial em sistemas escaláveis. O SQS SEND existe para:

  1. Desacoplamento: Separar produtores de consumidores de mensagens
  2. Processamento assíncrono: Enviar tarefas para serem processadas posteriormente
  3. Escalabilidade: Distribuir carga entre múltiplos consumidores
  4. Resiliência: Garantir que mensagens não sejam perdidas mesmo em falhas
  5. Controle de taxa: Processar mensagens no ritmo adequado
  6. Persistência: Armazenar mensagens até serem processadas

Como funciona internamente?

Quando o SQS SEND é executado, o sistema:

  1. Recebe os parâmetros: URL da fila, corpo da mensagem, atributos
  2. Autentica na AWS: Usa accessKeyId, secretAccessKey e region
  3. Serializa mensagem: Converte messageBody para JSON
  4. Envia para fila: Publica mensagem no SQS via SDK AWS
  5. Aplica delay: Se definido, atrasa entrega da mensagem
  6. Retorna MessageId: ID único da mensagem enviada
  7. Se erro: Lança exceção com detalhes do erro

Código interno (aws-executors.service.ts:104-115):

case 'sendMessage':
  const sendResult = await sqs.sendMessage({
    QueueUrl: data.queueUrl,
    MessageBody: JSON.stringify(data.messageBody),
    MessageAttributes: data.messageAttributes,
    DelaySeconds: data.delaySeconds,
  }).promise();
  return {
    success: true,
    messageId: sendResult.MessageId,
  };

Quando você DEVE usar este Node?

Use SQS SEND sempre que precisar de processamento assíncrono e desacoplado:

Casos de uso:

  1. Processamento de imagens: Enviar imagens para resize assíncrono
  2. Envio de emails: Encaminhar emails para processamento em lote
  3. Integração de sistemas: Comunicar entre microserviços
  4. Processamento de pedidos: Enviar pedidos para fulfillment
  5. Logs e auditoria: Enviar eventos para processamento posterior
  6. Tarefas agendadas: Agendar execução de jobs
  7. Importação de dados: Processar grandes volumes em background

Quando NÃO usar SQS SEND:

  • Respostas síncronas: Use Lambda direto se precisa resposta imediata
  • Pub/Sub multi-destino: Use SNS para broadcast para múltiplos assinantes
  • Processamento em tempo real: Use Kinesis para streaming

Diferença: SQS vs SNS

SQS (Queue - Fila)

  • Modelo: Ponto a ponto (1 produtor → 1 consumidor)
  • Uso: Processar mensagens sequencialmente
  • Garantia: Cada mensagem processada uma vez
  • Exemplo: Fila de processamento de pedidos

SNS (Topic - Pub/Sub)

  • Modelo: Broadcast (1 produtor → N assinantes)
  • Uso: Notificar múltiplos sistemas
  • Garantia: Todos assinantes recebem a mensagem
  • Exemplo: Notificar webhook + email + SMS

Tipos de Filas SQS

Standard Queue (Padrão)

  • Throughput: Ilimitado
  • Ordem: Melhor esforço (pode desordenar)
  • Duplicatas: Pode entregar mais de uma vez
  • Latência: Milissegundos
  • Uso: Máxima performance

FIFO Queue

  • Throughput: 300 msgs/seg (3000 com batching)
  • Ordem: Garantida (First In, First Out)
  • Duplicatas: Exatamente uma entrega
  • Latência: Ligeiramente maior
  • Uso: Ordem crítica (ex: transações bancárias)

Parâmetros Detalhados

queueUrl (string, obrigatório)

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

Formato: https://sqs.{region}.amazonaws.com/{account-id}/{queue-name}

Flow completo para testar:

{
  "name": "Teste SQS Send - Queue URL",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Preparar Dados",
        "parameters": {
          "variable": "pedido",
          "value": {
            "id": "PED-001",
            "cliente": "José Roberto",
            "total": 250.00
          }
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar para Fila",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "https://sqs.us-east-1.amazonaws.com/123456789012/pedidos-queue",
          "messageBody": "{{pedido}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Pedido enviado para processamento!\nID Mensagem: {{messageId}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Substitua credenciais e URL reais. Sistema retorna messageId único.

messageBody (object/string, obrigatório)

O que é: Conteúdo da mensagem que será enviado para a fila. Pode ser objeto JSON ou string.

Limite: Até 256 KB por mensagem

Flow completo para testar:

{
  "name": "Teste SQS Send - Message Body",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Email Cliente",
        "parameters": {
          "message": "Digite o email do cliente:",
          "variable": "email"
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar Email Job",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{sqs_queue_url}}",
          "messageBody": {
            "type": "welcome_email",
            "to": "{{email}}",
            "subject": "Bem-vindo!",
            "template": "welcome-template",
            "data": {
              "name": "Cliente",
              "date": "2025-01-15"
            }
          }
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "📧 Email agendado para envio!\nDestinatário: {{email}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Digite email. Mensagem é enviada com estrutura JSON completa.

delaySeconds (number, opcional)

O que é: Tempo de atraso (em segundos) antes da mensagem ficar disponível para consumo.

Padrão: 0 (disponível imediatamente)

Limite: 0 a 900 segundos (15 minutos)

Flow completo para testar:

{
  "name": "Teste SQS Send - Delay",
  "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": "Informar",
        "parameters": {
          "message": "⏰ Agendando lembrete para daqui 5 minutos..."
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar com Delay",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{sqs_queue_url}}",
          "messageBody": {
            "type": "reminder",
            "message": "Lembrete: Revisar documento",
            "user": "jose.roberto"
          },
          "delaySeconds": 300
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Lembrete agendado para 5 minutos!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Teste: Mensagem só fica disponível após 5 minutos (300 segundos).

messageAttributes (object, opcional)

O que é: Metadados estruturados da mensagem (filtros, headers customizados).

Formato: { "NomeAtributo": { DataType: "String", StringValue: "valor" } }

Flow completo para testar:

{
  "name": "Teste SQS Send - Attributes",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Enviar com Atributos",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{sqs_queue_url}}",
          "messageBody": {
            "orderId": "ORD-123",
            "status": "pending"
          },
          "messageAttributes": {
            "Priority": {
              "DataType": "String",
              "StringValue": "high"
            },
            "Source": {
              "DataType": "String",
              "StringValue": "whatsapp-flow"
            },
            "Version": {
              "DataType": "Number",
              "StringValue": "1"
            }
          }
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Mensagem enviada com metadados!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Atributos são usados para filtrar/rotear mensagens no consumidor.

accessKeyId (string, obrigatório)

O que é: Chave de acesso da conta AWS (credencial de autenticação).

Formato: Alfanumérico, 20 caracteres

secretAccessKey (string, obrigatório)

O que é: Chave secreta da conta AWS (credencial de autenticação).

Formato: Alfanumérico, 40 caracteres

region (string, obrigatório)

O que é: Região AWS onde a fila está hospedada.

Exemplos: us-east-1, us-west-2, eu-west-1, sa-east-1 (São Paulo)

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim Deve ser "sendMessage"
accessKeyId string Sim AWS Access Key ID
secretAccessKey string Sim AWS Secret Access Key
region string Sim Região AWS (ex: us-east-1)
queueUrl string Sim URL completa da fila SQS
messageBody object/string Sim Conteúdo da mensagem (JSON)
delaySeconds number Não Delay de 0-900s (padrão: 0)
messageAttributes object Não Metadados da mensagem

Exemplo 1: Processar Pedido Assíncrono

Objetivo: Enviar pedido para processamento em background

JSON para Importar

{
  "name": "Processar Pedido Assíncrono",
  "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": "Boas-vindas",
        "parameters": {
          "message": "🛒 Confirmação de Pedido"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Criar Pedido",
        "parameters": {
          "variable": "order",
          "value": {
            "orderId": "ORD-2025-001",
            "customer": {
              "name": "José Roberto",
              "phone": "+5511999999999"
            },
            "items": [
              { "sku": "PROD-001", "qty": 2, "price": 50.00 },
              { "sku": "PROD-002", "qty": 1, "price": 150.00 }
            ],
            "total": 250.00,
            "timestamp": "2025-01-15T10:30:00Z"
          }
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Enviar para Fila",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "sa-east-1",
          "queueUrl": "https://sqs.sa-east-1.amazonaws.com/123456789012/orders-processing",
          "messageBody": "{{order}}",
          "messageAttributes": {
            "OrderType": {
              "DataType": "String",
              "StringValue": "standard"
            },
            "Priority": {
              "DataType": "String",
              "StringValue": "normal"
            }
          }
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Pedido ORD-2025-001 recebido!\n\n💰 Total: R$ 250,00\n⏳ Processando em background..."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "variable_1" },
    { "source": "variable_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 🛒 Confirmação de Pedido
Sistema: ✅ Pedido ORD-2025-001 recebido!

💰 Total: R$ 250,00
⏳ Processando em background...

Exemplo 2: Enviar Email Assíncrono

Objetivo: Agendar envio de email sem bloquear o flow

JSON para Importar

{
  "name": "Agendar Email Assíncrono",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Nome",
        "parameters": {
          "message": "Qual é o seu nome?",
          "variable": "nome"
        }
      }
    },
    {
      "id": "email_1",
      "type": "email",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Email",
        "parameters": {
          "message": "Qual é o seu email?",
          "variable": "email"
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Agendar Email",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{email_queue_url}}",
          "messageBody": {
            "type": "welcome_email",
            "to": "{{email}}",
            "subject": "Bem-vindo, {{nome}}!",
            "template": "welcome",
            "data": {
              "customerName": "{{nome}}",
              "signupDate": "2025-01-15"
            }
          },
          "delaySeconds": 60
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Obrigado, {{nome}}!\n\n📧 Você receberá um email de boas-vindas em {{email}} nos próximos minutos."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "email_1" },
    { "source": "email_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Qual é o seu nome?
Usuário: José Roberto
Sistema: Qual é o seu email?
Usuário: jose@example.com
Sistema: ✅ Obrigado, José Roberto!

📧 Você receberá um email de boas-vindas em jose@example.com nos próximos minutos.

Exemplo 3: Processamento de Imagem

Objetivo: Enviar imagem para processamento assíncrono (resize, compressão)

JSON para Importar

{
  "name": "Processar Imagem Assíncrona",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "media_1",
      "type": "media",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Receber Imagem",
        "parameters": {
          "message": "📸 Envie a foto do produto:",
          "variable": "foto_produto",
          "mediaType": "image"
        }
      }
    },
    {
      "id": "sqs_1",
      "type": "aws_sqs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar para Processamento",
        "parameters": {
          "operation": "sendMessage",
          "accessKeyId": "{{aws_access_key}}",
          "secretAccessKey": "{{aws_secret_key}}",
          "region": "us-east-1",
          "queueUrl": "{{image_processing_queue}}",
          "messageBody": {
            "imageUrl": "{{foto_produto}}",
            "operations": [
              { "type": "resize", "width": 800, "height": 600 },
              { "type": "compress", "quality": 85 },
              { "type": "watermark", "text": "Minha Loja" }
            ],
            "outputBucket": "processed-images",
            "callbackUrl": "https://api.lumina.app.br/webhooks/image-processed"
          },
          "messageAttributes": {
            "ImageType": {
              "DataType": "String",
              "StringValue": "product"
            }
          }
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Foto recebida!\n\n⚙️ Processando imagem...\n📦 Você será notificado quando estiver pronta."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "media_1" },
    { "source": "media_1", "target": "sqs_1" },
    { "source": "sqs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 📸 Envie a foto do produto:
Usuário: [envia imagem]
Sistema: ✅ Foto recebida!

⚙️ Processando imagem...
📦 Você será notificado quando estiver pronta.

Resposta do Node

{
  "success": true,
  "messageId": "f8a7d2e1-c5b4-4d6a-9e8c-1f2a3b4c5d6e"
}

Dead Letter Queue (DLQ)

O que é: Fila para mensagens que falharam no processamento após X tentativas.

Configuração (no AWS Console):

{
  "RedrivePolicy": {
    "deadLetterTargetArn": "arn:aws:sqs:us-east-1:123456789012:orders-dlq",
    "maxReceiveCount": 3
  }
}

Uso: - Mensagem falha 3 vezes → movida para DLQ - Analise erros na DLQ - Reprocesse ou descarte

Boas Práticas

SIM:

  • Use DLQ para capturar falhas
  • Configure visibility timeout adequado
  • Use messageAttributes para filtros
  • Implemente idempotência no consumidor
  • Monitore tamanho da fila no CloudWatch
  • Use FIFO queues quando ordem importa
  • Valide messageBody antes de enviar
  • Configure retry policy

NÃO:

  • Não envie dados sensíveis sem criptografia
  • Não exceda 256 KB por mensagem
  • Não use para respostas síncronas
  • Não ignore erros de envio
  • Não esqueça de deletar mensagens processadas
  • Não use Standard queue se ordem é crítica

Limites AWS SQS

Item Limite
Tamanho mensagem 256 KB
Retenção 1 min - 14 dias (padrão: 4 dias)
Throughput Standard Ilimitado
Throughput FIFO 3000 msgs/seg (com batching)
Delay máximo 15 minutos
Visibility timeout 0s - 12 horas
Long polling 0-20 segundos

Dicas

💡 Batching: Envie múltiplas mensagens com sendMessageBatch() para melhor performance

💡 Long Polling: Configure WaitTimeSeconds > 0 para reduzir custos

💡 Visibilidade: Ajuste VisibilityTimeout baseado no tempo de processamento

💡 Monitoramento: Use CloudWatch para alertas de fila cheia

💡 Custo: SQS cobra por requisição (1 milhão = ~$0.40)

Próximo Node

SQS RECEIVE - Receber mensagens da fila → SQS DELETE - Deletar mensagem processada → SNS PUBLISH - Publicar em tópico SNS (broadcast)