ivanpaulovich / FluentMediator

:twisted_rightwards_arrows: FluentMediator is an unobtrusive library that allows developers to build custom pipelines for Commands, Queries and Events.
http://paulovich.net/FluentMediator/
Apache License 2.0
192 stars 17 forks source link

Tratamento para eventos (Apenas para rastreamento) #48

Closed alesimoes closed 4 years ago

alesimoes commented 4 years ago

Ivan, blz?

Conforme conversamos. Estou usando o FluentMediator para publicar os eventos de domínio. No meu BUS eu uso o fluentMediator e ele publica o evento no mediator para o mediator executar a function associada. Até ai ok. Porém se o tratamento do evento não for registrado no FluentMediator ele levanta null Exception.

ivanpaulovich commented 4 years ago

Olá @alesimoes,

Gostaria de confirmar o bug e a sugestão sugerida:

Eu entendi que ao não configurar um Handler para um evento o mediator lança uma exception. Essa exception seria NullReferenceException ou PipelineNotFoundException?

A sugestão seria:

  1. Silenciar a exceção.
  2. Criar um handler para OnException no mediator e chamar esse handler para essas mensagens mal configuradas.

Seria isso?

alesimoes commented 4 years ago

Olá @ivanpaulovich , Desculpe a exception correta é PipelineNotFoundException;

Acredito que as duas formas que você apresentou são válidas. Ou talvez uma forma de validar no mediator se o pipeline está configurado. Sendo assim o Bus (que no caso estou usando como infraestrutura) ele poderia validar se tem alguém que quer receber o evento antes de publicar. (Apenas uma outra ideia)

ivanpaulovich commented 4 years ago

Hey @alesimoes,

O que voce acha dessa implementação?

https://github.com/ivanpaulovich/FluentMediator/commit/c3c58aa98028322db25fd77f8a17a90399558920#diff-14cb423500372d924cabf8d8f8cc87abR159-R182

mediator.Publish(ping); não ira mais lançar PipelineNotFoundException e para o desenvolvedor não perder essa mensagem, ele precisa adicionar o seu delegate no no mediator.PipelineNotFound.

Essa abordagem resolveria a sua implementação?

alesimoes commented 4 years ago

@ivanpaulovich , Excelente solução Ivan. Resolveria sim.

ivanpaulovich commented 4 years ago

Olá @alesimoes,

Estou chegando num design final, implementei duas formas de identificar que uma mensagem não chegou em uma pipeline:

Opção 01:

[Fact]
public void Publish_CallsPipelineNotFound_WhenHandlerIsNotSetup()
{
    var services = new ServiceCollection();
    // Mediator Without the Handler for PingRequest.
    services.AddFluentMediator(builder => { });

    var provider = services.BuildServiceProvider();
    var mediator = provider.GetRequiredService<IMediator>();

    bool myCustomPipelineNotFoundHandlerWasCalled = false;

    // This is handler is called for every message without a destination pipeline.
    mediator.PipelineNotFound += (object sender, PipelineNotFoundEventArgs e) => {
        myCustomPipelineNotFoundHandlerWasCalled = true;
    };

    var cts = new CancellationTokenSource();
    var ping = new PingRequest("Cancellable Async Ping");

    // Should run without throwing exceptions
    mediator.Publish(ping);

    // The method was called :)
    Assert.True(myCustomPipelineNotFoundHandlerWasCalled);
}

Opção 02:


// Add a Mediator derivative class

public class MyCustomMediator : Mediator
{
    public bool MyCustomPipelineNotFoundHandlerWasCalled = false;

    public MyCustomMediator(GetService getService, IPipelineProvider pipelines) : base(getService, pipelines)
    {
    }

    protected override void OnPipelineNotFound(PipelineNotFoundEventArgs e)
    {
        MyCustomPipelineNotFoundHandlerWasCalled = true;

        //Do something before raising the event
        base.OnPipelineNotFound(e);
        //Do something after raising the event 
    }
}

// Then you can run this:

[Fact]
public void Publish_CallsCustomPipelineNotFound_WhenHandlerIsNotSetup()
{
    var services = new ServiceCollection();

    // Mediator Without the Handler for PingRequest.
    services.AddFluentMediator<MyCustomMediator>(builder => { });

    var provider = services.BuildServiceProvider();
    var mediator = (MyCustomMediator)provider.GetRequiredService<IMediator>();

    var cts = new CancellationTokenSource();
    var ping = new PingRequest("Cancellable Async Ping");

    // Should run without throwing exceptions
    mediator.Publish(ping);

    // The method was called :)
    Assert.True(mediator.MyCustomPipelineNotFoundHandlerWasCalled);
}

Essas mudanças vão para a versão 0.4.7.

ivanpaulovich commented 4 years ago

Em primeira mão, publicado aqui:

https://www.nuget.org/packages/FluentMediator/0.4.7

alesimoes commented 4 years ago

Opa, valeu @ivanpaulovich !