Created
February 23, 2026 20:23
-
-
Save alexandrebl/f0611eb7b6a81b6aa535acbbbc9494c2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ======================================================================================================== | |
| // SISTEMA DE PROCESSAMENTO DE PEDIDOS COM AKKA.NET - PIPELINE DE ATORES ENCADEADOS | |
| // ======================================================================================================== | |
| // | |
| // Este projeto demonstra o uso de ATORES ENCADEADOS (Actor Pipeline) usando o framework Akka.NET. | |
| // O objetivo é processar pedidos através de múltiplas etapas, onde cada ator é responsável por | |
| // uma única responsabilidade (Single Responsibility Principle). | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // O QUE É AKKA.NET? | |
| // -------------------------------------------------------------------------------------------------------- | |
| // Akka.NET é um framework para construir sistemas concorrentes, distribuídos e resilientes usando | |
| // o modelo de ATORES. Cada ator é uma unidade isolada de processamento que: | |
| // - Possui seu próprio estado privado | |
| // - Processa mensagens de forma assíncrona e sequencial | |
| // - Comunica-se com outros atores apenas através de mensagens | |
| // - Não compartilha memória (evita problemas de concorrência) | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // ARQUITETURA DO PIPELINE DE PROCESSAMENTO | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // O sistema implementa um PIPELINE DE 5 ATORES ENCADEADOS que processam pedidos em etapas: | |
| // | |
| // ┌─────────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ | |
| // │ OrderReceiver │ ───> │ Validation │ ───> │ Payment │ ───> │ Shipping │ ───> │ Notification │ | |
| // │ Actor │ │ Actor │ │ Actor │ │ Actor │ │ Actor │ | |
| // └─────────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────────┘ | |
| // Etapa 1 Etapa 2 Etapa 3 Etapa 4 Etapa 5 | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // FLUXO DETALHADO DE PROCESSAMENTO | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // 1. ORDERRECEIVER ACTOR (Recepção) | |
| // - Recebe: Order (pedido original) | |
| // - Função: Ponto de entrada do sistema, recebe pedidos dos clientes | |
| // - Processa: Registra o recebimento do pedido | |
| // - Envia para: ValidationActor | |
| // | |
| // 2. VALIDATION ACTOR (Validação) | |
| // - Recebe: Order | |
| // - Função: Valida os dados do pedido (quantidade > 0 e preço > 0) | |
| // - Processa: Verifica integridade dos dados | |
| // - Envia para: PaymentActor (se válido) ou interrompe o fluxo (se inválido) | |
| // - Mensagem enviada: ValidatedOrder | |
| // | |
| // 3. PAYMENT ACTOR (Pagamento) | |
| // - Recebe: ValidatedOrder | |
| // - Função: Processa o pagamento do pedido | |
| // - Processa: Calcula o valor total, simula aprovação do pagamento, gera ID de transação | |
| // - Envia para: ShippingActor | |
| // - Mensagem enviada: PaidOrder (inclui TransactionId) | |
| // | |
| // 4. SHIPPING ACTOR (Envio) | |
| // - Recebe: PaidOrder | |
| // - Função: Prepara e despacha o pedido | |
| // - Processa: Simula preparação do envio, gera código de rastreamento | |
| // - Envia para: NotificationActor | |
| // - Mensagem enviada: ShippedOrder (inclui TrackingNumber) | |
| // | |
| // 5. NOTIFICATION ACTOR (Notificação) | |
| // - Recebe: ShippedOrder | |
| // - Função: Envia notificação final ao cliente | |
| // - Processa: Gera notificação com todos os detalhes do pedido concluído | |
| // - Final do pipeline: Não envia para outros atores | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // TIPOS DE MENSAGENS NO PIPELINE | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // As mensagens são objetos imutáveis que transportam dados entre atores: | |
| // | |
| // Order → Pedido original (Id, Product, Quantity, Price) | |
| // ValidatedOrder → Pedido validado (Order + IsValid) | |
| // PaidOrder → Pedido pago (Order + TransactionId) | |
| // ShippedOrder → Pedido enviado (Order + TrackingNumber) | |
| // CompletedOrder → Pedido concluído (Order + Status) [definida mas não usada neste exemplo] | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // VANTAGENS DESTA ARQUITETURA | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // 1. DESACOPLAMENTO: Cada ator conhece apenas o próximo ator na cadeia | |
| // 2. ESCALABILIDADE: Pode-se adicionar múltiplas instâncias de cada ator para processar em paralelo | |
| // 3. RESILIÊNCIA: Se um ator falha, o sistema pode reiniciá-lo sem afetar os outros | |
| // 4. MANUTENIBILIDADE: Cada ator tem uma responsabilidade clara e bem definida | |
| // 5. TESTABILIDADE: Cada ator pode ser testado isoladamente | |
| // 6. ASSÍNCRONO: Processamento não-bloqueante, cada ator processa em seu próprio ritmo | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // CONCEITOS IMPORTANTES DO AKKA.NET UTILIZADOS | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // - ActorSystem: Container que gerencia todos os atores | |
| // - ActorOf: Cria uma nova instância de ator | |
| // - Props.Create: Factory para criar atores com parâmetros de construtor | |
| // - IActorRef: Referência para enviar mensagens a um ator (não acessa o ator diretamente) | |
| // - Tell(): Envia mensagem assíncrona (fire-and-forget) | |
| // - Receive<T>: Define um handler SÍNCRONO para processar mensagens do tipo T | |
| // - ReceiveAsync<T>: Define um handler ASSÍNCRONO para processar mensagens do tipo T (permite await) | |
| // - ReceiveActor: Classe base para atores que usam pattern matching de mensagens | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| // ASYNC/AWAIT NO AKKA.NET - BOAS PRÁTICAS | |
| // -------------------------------------------------------------------------------------------------------- | |
| // | |
| // 1. Use ReceiveAsync<T> ao invés de Receive<T> quando precisar fazer operações assíncronas | |
| // 2. Sempre aguarde (await) operações I/O: chamadas HTTP, banco de dados, leitura de arquivos | |
| // 3. Use Task.Delay() para simular latência ou throttling de operações | |
| // 4. Evite bloqueio com .Result ou .Wait() - sempre use await | |
| // 5. Cada ator processa mensagens sequencialmente, então async/await não quebra o modelo de atores | |
| // 6. O ator continua processando outras mensagens apenas após o await completar | |
| // | |
| // -------------------------------------------------------------------------------------------------------- | |
| using Akka.Actor; | |
| // ======================================================================================================== | |
| // INICIALIZAÇÃO DO SISTEMA DE ATORES | |
| // ======================================================================================================== | |
| // Cria o ActorSystem - container raiz que gerencia todos os atores | |
| // Nome do sistema: "MyActorSystem" - identificador único do sistema | |
| var actorSystem = ActorSystem.Create("MyActorSystem"); | |
| // ======================================================================================================== | |
| // CRIAÇÃO DO PIPELINE DE ATORES | |
| // ======================================================================================================== | |
| // IMPORTANTE: Os atores são criados na ordem INVERSA do fluxo (do fim para o início) | |
| // Isso é necessário porque cada ator precisa receber a referência (IActorRef) do próximo ator | |
| // no seu construtor para poder enviar mensagens (Tell) para ele. | |
| // | |
| // Fluxo do pipeline: OrderReceiver → Validation → Payment → Shipping → Notification | |
| // Ordem de criação: Notification ← Shipping ← Payment ← Validation ← OrderReceiver | |
| // ======================================================================================================== | |
| // 5. Notification Actor - Final do pipeline (não precisa de referência para próximo ator) | |
| var notificationActor = actorSystem.ActorOf<NotificationActor>("notification"); | |
| // 4. Shipping Actor - Recebe referência do NotificationActor | |
| var shippingActor = actorSystem.ActorOf(Props.Create(() => new ShippingActor(notificationActor)), "shipping"); | |
| // 3. Payment Actor - Recebe referência do ShippingActor | |
| var paymentActor = actorSystem.ActorOf(Props.Create(() => new PaymentActor(shippingActor)), "payment"); | |
| // 2. Validation Actor - Recebe referência do PaymentActor | |
| var validationActor = actorSystem.ActorOf(Props.Create(() => new ValidationActor(paymentActor)), "validation"); | |
| // 1. Order Receiver Actor - Início do pipeline, recebe referência do ValidationActor | |
| var orderReceiver = actorSystem.ActorOf(Props.Create(() => new OrderReceiverActor(validationActor)), "orderReceiver"); | |
| // ======================================================================================================== | |
| // ENVIO DE PEDIDOS PARA PROCESSAMENTO | |
| // ======================================================================================================== | |
| // Tell() é um método "fire-and-forget" (envia e esquece) | |
| // As mensagens são processadas assincronamente pelos atores | |
| // ======================================================================================================== | |
| orderReceiver.Tell(new Order { Id = 1, Product = "Notebook", Quantity = 1, Price = 3500.00m }); | |
| orderReceiver.Tell(new Order { Id = 2, Product = "Mouse", Quantity = 2, Price = 50.00m }); | |
| orderReceiver.Tell(new Order { Id = 3, Product = "Teclado", Quantity = 1, Price = 250.00m }); | |
| Console.WriteLine("Aguardando processamento dos pedidos...\n"); | |
| // ======================================================================================================== | |
| // MONITORAMENTO DO SISTEMA | |
| // ======================================================================================================== | |
| // Usa CancellationToken para controle cooperativo do loop de monitoramento | |
| // Substitui o uso de Timer tradicional por abordagem totalmente assíncrona | |
| // ======================================================================================================== | |
| // Loop assíncrono com Task.Delay ao invés de Timer (boa prática async/await) | |
| var cancellationTokenSource = new CancellationTokenSource(); | |
| var monitoringTask = MonitorSystemAsync(cancellationTokenSource.Token); | |
| // Aguarda 10 segundos de forma assíncrona (permite que o pipeline processe os pedidos) | |
| await Task.Delay(TimeSpan.FromSeconds(10)); | |
| // Cancela o loop de monitoramento de forma cooperativa | |
| cancellationTokenSource.Cancel(); | |
| try | |
| { | |
| // Aguarda o término gracioso do loop de monitoramento | |
| await monitoringTask; | |
| } | |
| catch (OperationCanceledException) | |
| { | |
| // Exceção esperada quando cancelamos o token - comportamento normal | |
| } | |
| // ======================================================================================================== | |
| // ENCERRAMENTO DO SISTEMA DE ATORES | |
| // ======================================================================================================== | |
| // Terminate() encerra todos os atores de forma ordenada e libera recursos | |
| // É uma operação assíncrona que aguarda todos os atores finalizarem | |
| // ======================================================================================================== | |
| Console.WriteLine("\nEncerrando o sistema de atores..."); | |
| await actorSystem.Terminate(); | |
| // ======================================================================================================== | |
| // MÉTODO DE MONITORAMENTO DO SISTEMA | |
| // ======================================================================================================== | |
| // Este método executa um loop assíncrono para monitorar a saúde do sistema de atores. | |
| // Em um sistema de produção, este método poderia: | |
| // - Verificar métricas de performance dos atores | |
| // - Monitorar filas de mensagens | |
| // - Registrar estatísticas em logs | |
| // - Enviar alertas se houver problemas | |
| // | |
| // Usa CancellationToken para permitir cancelamento cooperativo e gracioso do loop. | |
| // ======================================================================================================== | |
| static async Task MonitorSystemAsync(CancellationToken cancellationToken) | |
| { | |
| int count = 0; | |
| while (!cancellationToken.IsCancellationRequested) | |
| { | |
| try | |
| { | |
| // Aguarda de forma assíncrona ao invés de usar Timer (boa prática async/await) | |
| await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken); | |
| count++; | |
| Console.WriteLine($"\n[Monitor] Tick: {count} - Sistema em execução..."); | |
| } | |
| catch (OperationCanceledException) | |
| { | |
| // Operação cancelada é esperada quando o token é cancelado | |
| // Permite saída limpa do loop | |
| break; | |
| } | |
| } | |
| } | |
| // ======================================================================================================== | |
| // DEFINIÇÃO DAS MENSAGENS DO PIPELINE | |
| // ======================================================================================================== | |
| // As mensagens são objetos IMUTÁVEIS que transportam dados entre atores. | |
| // Seguindo o padrão de Akka.NET, as mensagens devem ser: | |
| // - Imutáveis (readonly ou init-only properties quando possível) | |
| // - Serializáveis (para permitir distribuição remota) | |
| // - Pequenas e focadas (cada mensagem representa um evento ou comando específico) | |
| // ======================================================================================================== | |
| /// <summary> | |
| /// Mensagem inicial que representa um pedido recebido do cliente. | |
| /// Esta é a mensagem de entrada do pipeline. | |
| /// </summary> | |
| public class Order | |
| { | |
| public int Id { get; set; } | |
| public string Product { get; set; } = string.Empty; | |
| public int Quantity { get; set; } | |
| public decimal Price { get; set; } | |
| } | |
| /// <summary> | |
| /// Mensagem que transporta um pedido validado. | |
| /// Contém o pedido original e o resultado da validação. | |
| /// </summary> | |
| public class ValidatedOrder | |
| { | |
| public Order Order { get; set; } = null!; | |
| public bool IsValid { get; set; } | |
| } | |
| /// <summary> | |
| /// Mensagem que transporta um pedido pago. | |
| /// Inclui o ID da transação gerado pelo gateway de pagamento. | |
| /// </summary> | |
| public class PaidOrder | |
| { | |
| public Order Order { get; set; } = null!; | |
| public string TransactionId { get; set; } = string.Empty; | |
| } | |
| /// <summary> | |
| /// Mensagem que transporta um pedido enviado. | |
| /// Inclui o código de rastreamento da transportadora. | |
| /// </summary> | |
| public class ShippedOrder | |
| { | |
| public Order Order { get; set; } = null!; | |
| public string TrackingNumber { get; set; } = string.Empty; | |
| } | |
| /// <summary> | |
| /// Mensagem que representa um pedido completamente processado. | |
| /// Reservada para uso futuro em extensões do pipeline. | |
| /// </summary> | |
| public class CompletedOrder | |
| { | |
| public Order Order { get; set; } = null!; | |
| public string Status { get; set; } = string.Empty; | |
| } | |
| // ======================================================================================================== | |
| // IMPLEMENTAÇÃO DOS ATORES DO PIPELINE | |
| // ======================================================================================================== | |
| // Cada ator herda de ReceiveActor e usa ReceiveAsync<T> para processar mensagens de forma assíncrona. | |
| // Os atores são independentes e se comunicam APENAS através de mensagens (Tell). | |
| // ======================================================================================================== | |
| // ======================================================================================================== | |
| // IMPLEMENTAÇÃO DOS ATORES DO PIPELINE | |
| // ======================================================================================================== | |
| // Cada ator herda de ReceiveActor e usa ReceiveAsync<T> para processar mensagens de forma assíncrona. | |
| // Os atores são independentes e se comunicam APENAS através de mensagens (Tell). | |
| // ======================================================================================================== | |
| /// <summary> | |
| /// ATOR 1: ORDER RECEIVER ACTOR (Ponto de Entrada do Sistema) | |
| /// | |
| /// Responsabilidades: | |
| /// - Receber pedidos de clientes externos | |
| /// - Persistir pedidos no banco de dados | |
| /// - Encaminhar pedidos para validação | |
| /// | |
| /// Integrações Simuladas: | |
| /// - Banco de dados (persistência de pedidos) | |
| /// </summary> | |
| public class OrderReceiverActor : ReceiveActor | |
| { | |
| private readonly IActorRef _validationActor; | |
| public OrderReceiverActor(IActorRef validationActor) | |
| { | |
| _validationActor = validationActor; | |
| // ReceiveAsync permite usar await dentro do handler | |
| ReceiveAsync<Order>(async order => | |
| { | |
| Console.WriteLine($"[OrderReceiver] Pedido #{order.Id} recebido: {order.Product} x{order.Quantity}"); | |
| // Simula operação assíncrona: salvar pedido no banco de dados | |
| // Em produção: await dbContext.Orders.AddAsync(order); await dbContext.SaveChangesAsync(); | |
| await Task.Delay(100); // Simula latência de I/O do banco (~100ms) | |
| Console.WriteLine($"[OrderReceiver] Pedido #{order.Id} salvo no banco de dados"); | |
| // Envia para o próximo ator na cadeia (desacoplamento via mensagens) | |
| _validationActor.Tell(order); | |
| }); | |
| } | |
| } | |
| /// <summary> | |
| /// ATOR 2: VALIDATION ACTOR (Validador de Dados e Regras de Negócio) | |
| /// | |
| /// Responsabilidades: | |
| /// - Validar integridade dos dados do pedido | |
| /// - Verificar disponibilidade de estoque | |
| /// - Aplicar regras de negócio (limites, restrições) | |
| /// - Decidir se o pedido pode prosseguir no pipeline | |
| /// | |
| /// Integrações Simuladas: | |
| /// - API de validação de regras de negócio | |
| /// - Serviço de verificação de estoque | |
| /// </summary> | |
| public class ValidationActor : ReceiveActor | |
| { | |
| private readonly IActorRef _paymentActor; | |
| public ValidationActor(IActorRef paymentActor) | |
| { | |
| _paymentActor = paymentActor; | |
| // ReceiveAsync para operações assíncronas de validação | |
| ReceiveAsync<Order>(async order => | |
| { | |
| Console.WriteLine($"[Validation] Validando pedido #{order.Id}..."); | |
| // Simula validação assíncrona: verificar estoque, consultar regras de negócio via API | |
| // Em produção: await stockService.CheckAvailabilityAsync(order.Product, order.Quantity); | |
| await Task.Delay(200); // Simula latência de chamada a serviço externo (~200ms) | |
| // Aplica regras de validação | |
| bool isValid = order.Quantity > 0 && order.Price > 0; | |
| if (isValid) | |
| { | |
| Console.WriteLine($"[Validation] Pedido #{order.Id} validado com sucesso!"); | |
| // Encapsula o pedido em ValidatedOrder e envia para próximo ator | |
| _paymentActor.Tell(new ValidatedOrder { Order = order, IsValid = true }); | |
| } | |
| else | |
| { | |
| Console.WriteLine($"[Validation] Pedido #{order.Id} inválido!"); | |
| // Pipeline interrompido - pedido não avança para pagamento | |
| } | |
| }); | |
| } | |
| } | |
| /// <summary> | |
| /// ATOR 3: PAYMENT ACTOR (Processador de Pagamentos) | |
| /// | |
| /// Responsabilidades: | |
| /// - Calcular valor total do pedido | |
| /// - Processar pagamento via gateway externo | |
| /// - Gerar e armazenar ID de transação | |
| /// - Encaminhar pedidos pagos para envio | |
| /// | |
| /// Integrações Simuladas: | |
| /// - Gateway de pagamento (Stripe, PayPal, PagSeguro, etc) | |
| /// </summary> | |
| public class PaymentActor : ReceiveActor | |
| { | |
| private readonly IActorRef _shippingActor; | |
| public PaymentActor(IActorRef shippingActor) | |
| { | |
| _shippingActor = shippingActor; | |
| // ReceiveAsync para processar pagamento de forma assíncrona | |
| ReceiveAsync<ValidatedOrder>(async validatedOrder => | |
| { | |
| // Só processa pedidos que passaram pela validação | |
| if (validatedOrder.IsValid) | |
| { | |
| var order = validatedOrder.Order; | |
| decimal totalAmount = order.Price * order.Quantity; | |
| Console.WriteLine($"[Payment] Processando pagamento de R$ {totalAmount:F2} para pedido #{order.Id}..."); | |
| // Chama método auxiliar para simular integração com gateway de pagamento | |
| await ProcessPaymentAsync(order.Id, totalAmount); | |
| // Gera ID único de transação (em produção, viria do gateway) | |
| string transactionId = Guid.NewGuid().ToString()[..8]; | |
| Console.WriteLine($"[Payment] Pagamento aprovado! Transaction ID: {transactionId}"); | |
| // Encapsula pedido pago e envia para o próximo ator | |
| _shippingActor.Tell(new PaidOrder { Order = order, TransactionId = transactionId }); | |
| } | |
| }); | |
| } | |
| /// <summary> | |
| /// Simula chamada assíncrona a um gateway de pagamento externo. | |
| /// Em produção, este método faria requisição HTTP a APIs como: | |
| /// - Stripe: await stripe.Charges.CreateAsync(chargeOptions) | |
| /// - PayPal: await paypalClient.CreatePaymentAsync(payment) | |
| /// - Mercado Pago: await mercadoPagoClient.ProcessPaymentAsync(request) | |
| /// </summary> | |
| private static async Task ProcessPaymentAsync(int orderId, decimal amount) | |
| { | |
| // Simula latência de rede ao chamar API externa | |
| // 300-500ms é realista para APIs de pagamento | |
| await Task.Delay(350); | |
| // Aqui seria feita a chamada real à API do gateway de pagamento | |
| // Exemplo: var result = await httpClient.PostAsync("https://api.payment-gateway.com/charge", content); | |
| } | |
| } | |
| /// <summary> | |
| /// ATOR 4: SHIPPING ACTOR (Gerenciador de Envio e Logística) | |
| /// | |
| /// Responsabilidades: | |
| /// - Integrar com APIs de transportadoras | |
| /// - Gerar etiquetas de envio | |
| /// - Obter códigos de rastreamento | |
| /// - Encaminhar pedidos despachados para notificação | |
| /// | |
| /// Integrações Simuladas: | |
| /// - API de transportadoras (Correios, FedEx, UPS, DHL, etc) | |
| /// </summary> | |
| public class ShippingActor : ReceiveActor | |
| { | |
| private readonly IActorRef _notificationActor; | |
| public ShippingActor(IActorRef notificationActor) | |
| { | |
| _notificationActor = notificationActor; | |
| // ReceiveAsync para processar envio de forma assíncrona | |
| ReceiveAsync<PaidOrder>(async paidOrder => | |
| { | |
| var order = paidOrder.Order; | |
| Console.WriteLine($"[Shipping] Preparando envio do pedido #{order.Id}..."); | |
| // Chama método auxiliar para simular integração com API de transportadora | |
| string trackingNumber = await GenerateShippingLabelAsync(order.Id, order.Product); | |
| Console.WriteLine($"[Shipping] Pedido #{order.Id} despachado! Código de rastreio: {trackingNumber}"); | |
| // Encapsula pedido enviado e envia para o último ator (notificação) | |
| _notificationActor.Tell(new ShippedOrder | |
| { | |
| Order = order, | |
| TrackingNumber = trackingNumber | |
| }); | |
| }); | |
| } | |
| /// <summary> | |
| /// Simula geração assíncrona de etiqueta de envio via API de transportadora. | |
| /// Em produção, este método faria requisição HTTP a APIs como: | |
| /// - Correios: await correiosClient.CreateShippingLabelAsync(address, dimensions) | |
| /// - FedEx: await fedexClient.CreateShipmentAsync(shipmentRequest) | |
| /// - Melhor Envio: await melhorEnvioClient.GenerateLabelAsync(order) | |
| /// </summary> | |
| private static async Task<string> GenerateShippingLabelAsync(int orderId, string product) | |
| { | |
| // Simula chamada assíncrona à API da transportadora (~250ms) | |
| await Task.Delay(250); | |
| // Aqui seria feita a chamada real à API da transportadora | |
| // Exemplo: var response = await httpClient.PostAsync("https://api.shipping.com/create-label", content); | |
| // Retornaria: response.TrackingNumber | |
| // Gera código de rastreio simulado no formato brasileiro | |
| return $"BR{Random.Shared.Next(10000000, 99999999)}"; | |
| } | |
| } | |
| /// <summary> | |
| /// ATOR 5: NOTIFICATION ACTOR (Gerenciador de Notificações Multi-Canal) | |
| /// | |
| /// Responsabilidades: | |
| /// - Enviar notificações por email | |
| /// - Enviar notificações por SMS | |
| /// - Enviar push notifications (opcional) | |
| /// - Registrar conclusão do processamento do pedido | |
| /// | |
| /// Integrações Simuladas: | |
| /// - Serviço de email (SendGrid, AWS SES, SMTP) | |
| /// - Serviço de SMS (Twilio, AWS SNS) | |
| /// | |
| /// Este é o ÚLTIMO ator do pipeline - finaliza o processamento. | |
| /// </summary> | |
| public class NotificationActor : ReceiveActor | |
| { | |
| public NotificationActor() | |
| { | |
| // ReceiveAsync para enviar notificações de forma assíncrona | |
| ReceiveAsync<ShippedOrder>(async shippedOrder => | |
| { | |
| var order = shippedOrder.Order; | |
| Console.WriteLine($"[Notification] Enviando notificação para pedido #{order.Id}..."); | |
| // Envia notificações em paralelo para otimizar tempo | |
| // Cada canal de notificação é independente | |
| await SendEmailNotificationAsync(order.Id, order.Product, shippedOrder.TrackingNumber); | |
| await SendSmsNotificationAsync(order.Id); | |
| // Exibe resumo final do processamento | |
| Console.WriteLine($"[Notification] ✓ Pedido #{order.Id} concluído com sucesso!"); | |
| Console.WriteLine($"[Notification] Produto: {order.Product}"); | |
| Console.WriteLine($"[Notification] Rastreio: {shippedOrder.TrackingNumber}"); | |
| // Pipeline completo: Order → Validation → Payment → Shipping → Notification ✓ | |
| }); | |
| } | |
| /// <summary> | |
| /// Simula envio assíncrono de notificação por email. | |
| /// Em produção, este método integraria com serviços como: | |
| /// - SendGrid: await sendGridClient.SendEmailAsync(message) | |
| /// - AWS SES: await sesClient.SendEmailAsync(request) | |
| /// - MailKit: await smtpClient.SendAsync(mimeMessage) | |
| /// </summary> | |
| private static async Task SendEmailNotificationAsync(int orderId, string product, string trackingNumber) | |
| { | |
| // Simula chamada assíncrona a serviço de email (~150ms) | |
| await Task.Delay(150); | |
| // Aqui seria feita a chamada real ao serviço de email | |
| // Exemplo: | |
| // var message = new EmailMessage { | |
| // To = customer.Email, | |
| // Subject = $"Pedido #{orderId} enviado!", | |
| // Body = $"Seu produto {product} foi enviado. Rastreie com: {trackingNumber}" | |
| // }; | |
| // await emailService.SendAsync(message); | |
| } | |
| /// <summary> | |
| /// Simula envio assíncrono de notificação por SMS. | |
| /// Em produção, este método integraria com serviços como: | |
| /// - Twilio: await twilioClient.Messages.CreateAsync(messageOptions) | |
| /// - AWS SNS: await snsClient.PublishAsync(publishRequest) | |
| /// - Nexmo: await nexmoClient.SMS.SendAnSMSAsync(smsRequest) | |
| /// </summary> | |
| private static async Task SendSmsNotificationAsync(int orderId) | |
| { | |
| // Simula chamada assíncrona a serviço de SMS (~100ms) | |
| await Task.Delay(100); | |
| // Aqui seria feita a chamada real ao serviço de SMS | |
| // Exemplo: | |
| // await smsService.SendAsync( | |
| // phoneNumber: customer.Phone, | |
| // message: $"Pedido #{orderId} enviado! Verifique seu email para detalhes." | |
| // ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment