Em artigos anteriores, abordei integração do Brighter com RabbitMQ e Brighter V10 RC1. Este guia foca na migração para o Brighter V10, destacando mudanças na configuração do RabbitMQ e atualizações que quebram a compatibilidade.
Requisitos
- .NET 8 ou superior
- Um projeto .NET com os seguintes pacotes NuGet:
- Paramore.Brighter.MessagingGateway.RMQ.Sync: Habilita integração com RabbitMQ usando RabbitMQ.Client V6 (API síncrona).
- Paramore.Brighter.MessagingGateway.RMQ.Async: Habilita integração com RabbitMQ usando RabbitMQ.Client V7 (API assíncrona).
- Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection: Permite registrar o Brighter com DI do Microsoft.
- Paramore.Brighter.ServiceActivator.Extensions.Hosting: Hospeda o Brighter como serviço de background.
- Serilog.AspNetCore: Para logging estruturado (opcional, mas recomendado).
Recapitulação do Brighter
Antes de continuar com a configuração do RabbitMQ, vamos revisar conceitos básicos do Brighter.
Requisição (Comando/Evento)
Defina mensagens usando IRequest
:
public class Greeting() : Event(Guid.NewGuid())
{
public string Name { get; set; } = string.Empty;
}
-
Comandos: Operações para único destinatário (ex:
SendEmail
) -
Eventos: Notificações broadcast (ex:
OrderShipped
)
Mapeador de Mensagem (Opcional)
Traduz entre mensagens do Brighter e objetos do app:
public class GreetingMapper : IAmAMessageMapper<Greeting>
{
public Message MapToMessage(Greeting request, Publication publication)
{
var header = new MessageHeader
{
MessageId = request.Id,
TimeStamp = DateTimeOffset.UtcNow,
Topic = publication.Topic!,
MessageType = MessageType.MT_EVENT
};
var body = new MessageBody(JsonSerializer.Serialize(request));
return new Message(header, body);
}
public Greeting MapToRequest(Message message)
{
return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
}
public IRequestContext? Context { get; set; }
}
Mudança no V10: Mapeadores assíncronos agora exigem IAmAMessageMapperAsync
Manipulador de Requisição
Processa mensagens recebidas:
public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
public override Greeting Handle(Greeting command)
{
logger.LogInformation("Olá {Name}", command.Name);
return base.Handle(command);
}
}
Configurando Brighter com RabbitMQ
1. Escolha entre Sync vs Async
- Sync (RMQ.Sync): Usa RabbitMQ.Client V6 (API bloqueante). Adequado para migrações graduais.
- Async (RMQ.Async): Usa RabbitMQ.Client V7 (API totalmente assíncrona). Recomendado para novos projetos.
Dica: Migre primeiro para o Brighter V10 usando RMQ.Sync
antes de adotar o RMQ.Async
.
2. Configuração da Conexão
Defina detalhes da conexão com RabbitMQ:
var connection = new RmqMessagingGatewayConnection
{
AmpqUri = new AmqpUriSpecification(new Uri("amqp://guest:guest@localhost:5672")),
Exchange = new Exchange("paramore.brighter.exchange"),
};
3. Assinatura no RabbitMQ
Assine uma fila/tópico:
.AddServiceActivator(opt =>
{
opt.Subscriptions = [
new RmqSubscription<Greeting>(
new SubscriptionName("kafka.greeting.subscription"),
new ChannelName("greeting.queue"),
new RoutingKey("greeting.topic"),
makeChannels: OnMissingChannel.Create,
messagePumpType: MessagePumpType.Reactor
),
];
opt.DefaultChannelFactory = new ChannelFactory(new RmqMessageConsumerFactory(connection));
})
4. Configuração do Produtor RabbitMQ
Publique eventos em um tópico:
.UseExternalBus(opt =>
{
opt.ProducerRegistry = new RmqProducerRegistryFactory(connection, [
new RmqPublication<Greeting>
{
MakeChannels = OnMissingChannel.Create,
Topic = new RoutingKey("greeting.topic"),
},
]).Create();
});
Mudanças que quebram a compatibilidade no Brighter V10
O Brighter V10 introduz atualizações significativas na integração com RabbitMQ, principalmente devido à adoção do RabbitMQ.Client
V6/V7 e melhor separação entre async/sync. Abaixo estão as principais mudanças:
Renomeação de Pacotes
Para alinhar com a versão do RabbitMQ.Client
e clarificar uso async/sync:
- Antigo:
Paramore.Brighter.MessagingGateway.RMQ
- Novo:
-
Paramore.Brighter.MessagingGateway.RMQ.Sync
(API sync V6) -
Paramore.Brighter.MessagingGateway.RMQ.Async
(API async V7)
-
Por quê? O RabbitMQ.Client
V7 introduziu mudanças que exigem ajustes no código. A divisão garante compatibilidade explícita e evita surpresas em runtime.
Reestruturação dos Mapeadores de Mensagem
Serialização JSON Padrão:
No V9, mapeadores eram obrigatórios. No V10, a serialização JSON é nativa, exceto quando lógica personalizada é necessária.
Separação de Interfaces
-
IAmAMessageMapper
(sync/reactor): Para fluxos síncronos -
IAmAMessageMapperAsync
(async/proactor): Para fluxos assíncronos
Mudanças em IAmAMessageMapper
// V10
IRequestContext? Context { get; set; }
Message MapToMessage(Greeting request, Publication publication);
// V9
Message MapToMessage(Greeting request);
Assinaturas
Tiveram 2 principais mudanças:
Tipos de Message Pump Explícitos
Antes tinhamos runAsync
ou isAsync
como booleanos. Agora temos messagePumpType
do tipo MessagePumpType
(Reactor
, Proactor
, Unknown
).
Renomeação de Propriedades
Na AddServiceActivator
renomeamos a propriedade ChannelFactory
para DefaultChannelFactory
Publicações
Também tiveram 2 principais mudanças:
Reestruturação da Configuração
Removemos IAmAProducerRegistry
. Use ExternalBusConfiguration
para configurar produtores e padrões de outbox:
// V10
.UseExternalBus(opt => { ... })
// V9
.UseExternalBus(new RmqProducerRegistryFactory(...))
Especificação do Tipo de Requisição
Na Publication
, você deve especificar o tipo da requisição ou alterar o IAmAPublicationFinder
padrão com UsePublicationFinder
:
new RmqPublication<Greeting>
{
MakeChannels = OnMissingChannel.Create,
Topic = new RoutingKey("greeting.topic"),
}
// ou
new RmqPublication
{
MakeChannels = OnMissingChannel.Create,
Topic = new RoutingKey("greeting.topic"),
RequestType = typeof(Greeting)
}
Dicas para Migração
- Comece com
RMQ.Sync
: Migre primeiro para o Brighter V10 usandoRabbitMQ.Client
V6 antes de adotar o pacote async V7 - Revise Mapeadores: Substitua
IAmAMessageMapper
porIAmAMessageMapperAsync
para fluxos assíncronos - Valide Assinaturas: Garanta que
messagePumpType
corresponda aos requisitos async/sync - Atualize Publicações: Adicione
RequestType
em instâncias não genéricas deRmqPublication
ou defina umIAmAPublicationFinder
Conclusão
O Brighter V10 simplifica a integração com RabbitMQ com uma separação mais clara entre async/sync e menos boilerplate. Principais etapas incluem:
- Atualizar pacotes NuGet
- Refatorar mapeadores para padrões assíncronos