Skip to content

Instantly share code, notes, and snippets.

@alexandrebl
Created February 23, 2026 20:16
Show Gist options
  • Select an option

  • Save alexandrebl/86332033e91984d68bdeaeccea2725fa to your computer and use it in GitHub Desktop.

Select an option

Save alexandrebl/86332033e91984d68bdeaeccea2725fa to your computer and use it in GitHub Desktop.
AkkaPipelineAndManualResetEvent.cs
// ========================================================================================================
// 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 para processar mensagens do tipo T
// - ReceiveActor: Classe base para atores que usam pattern matching de mensagens
//
// --------------------------------------------------------------------------------------------------------
using Akka.Actor;
var mre = new ManualResetEvent(false);
var actorSystem = ActorSystem.Create("MyActorSystem");
// Criar atores encadeados para processar pedidos
var notificationActor = actorSystem.ActorOf<NotificationActor>("notification");
var shippingActor = actorSystem.ActorOf(Props.Create(() => new ShippingActor(notificationActor)), "shipping");
var paymentActor = actorSystem.ActorOf(Props.Create(() => new PaymentActor(shippingActor)), "payment");
var validationActor = actorSystem.ActorOf(Props.Create(() => new ValidationActor(paymentActor)), "validation");
var orderReceiver = actorSystem.ActorOf(Props.Create(() => new OrderReceiverActor(validationActor)), "orderReceiver");
// Enviar pedidos para processar
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");
int count = 0;
Timer timer = new(callback =>
{
count++;
Console.WriteLine($"\nTimer tick: {count}");
if (count == 5)
{
mre.Set();
Console.WriteLine($"Timer alcançou {count} ticks, encerrando...");
}
});
timer.Change(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));
mre.WaitOne();
Console.WriteLine("\nEncerrando o sistema de atores...");
await actorSystem.Terminate();
// Mensagens
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; }
}
public class ValidatedOrder
{
public Order Order { get; set; } = null!;
public bool IsValid { get; set; }
}
public class PaidOrder
{
public Order Order { get; set; } = null!;
public string TransactionId { get; set; } = string.Empty;
}
public class ShippedOrder
{
public Order Order { get; set; } = null!;
public string TrackingNumber { get; set; } = string.Empty;
}
public class CompletedOrder
{
public Order Order { get; set; } = null!;
public string Status { get; set; } = string.Empty;
}
// Ator 1: Recebe o pedido inicial
public class OrderReceiverActor : ReceiveActor
{
private readonly IActorRef _validationActor;
public OrderReceiverActor(IActorRef validationActor)
{
_validationActor = validationActor;
Receive<Order>(order =>
{
Console.WriteLine($"[OrderReceiver] Pedido #{order.Id} recebido: {order.Product} x{order.Quantity}");
_validationActor.Tell(order);
});
}
}
// Ator 2: Valida o pedido
public class ValidationActor : ReceiveActor
{
private readonly IActorRef _paymentActor;
public ValidationActor(IActorRef paymentActor)
{
_paymentActor = paymentActor;
Receive<Order>(order =>
{
Console.WriteLine($"[Validation] Validando pedido #{order.Id}...");
bool isValid = order.Quantity > 0 && order.Price > 0;
if (isValid)
{
Console.WriteLine($"[Validation] Pedido #{order.Id} validado com sucesso!");
_paymentActor.Tell(new ValidatedOrder { Order = order, IsValid = true });
}
else
{
Console.WriteLine($"[Validation] Pedido #{order.Id} inválido!");
}
});
}
}
// Ator 3: Processa o pagamento
public class PaymentActor : ReceiveActor
{
private readonly IActorRef _shippingActor;
public PaymentActor(IActorRef shippingActor)
{
_shippingActor = shippingActor;
Receive<ValidatedOrder>(validatedOrder =>
{
if (validatedOrder.IsValid)
{
var order = validatedOrder.Order;
Console.WriteLine($"[Payment] Processando pagamento de R$ {order.Price * order.Quantity:F2} para pedido #{order.Id}...");
string transactionId = Guid.NewGuid().ToString()[..8];
Console.WriteLine($"[Payment] Pagamento aprovado! Transaction ID: {transactionId}");
_shippingActor.Tell(new PaidOrder { Order = order, TransactionId = transactionId });
}
});
}
}
// Ator 4: Processa o envio
public class ShippingActor : ReceiveActor
{
private readonly IActorRef _notificationActor;
public ShippingActor(IActorRef notificationActor)
{
_notificationActor = notificationActor;
Receive<PaidOrder>(paidOrder =>
{
var order = paidOrder.Order;
Console.WriteLine($"[Shipping] Preparando envio do pedido #{order.Id}...");
string trackingNumber = $"BR{Random.Shared.Next(10000000, 99999999)}";
Console.WriteLine($"[Shipping] Pedido #{order.Id} despachado! Código de rastreio: {trackingNumber}");
_notificationActor.Tell(new ShippedOrder
{
Order = order,
TrackingNumber = trackingNumber
});
});
}
}
// Ator 5: Envia notificação final
public class NotificationActor : ReceiveActor
{
public NotificationActor()
{
Receive<ShippedOrder>(shippedOrder =>
{
var order = shippedOrder.Order;
Console.WriteLine($"[Notification] Enviando notificação para pedido #{order.Id}...");
Console.WriteLine($"[Notification] ✓ Pedido #{order.Id} concluído com sucesso!");
Console.WriteLine($"[Notification] Produto: {order.Product}");
Console.WriteLine($"[Notification] Rastreio: {shippedOrder.TrackingNumber}");
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment