Mediator.Net icon indicating copy to clipboard operation
Mediator.Net copied to clipboard

calling an async method in Request handler crashes the bus

Open SuheylZ opened this issue 5 years ago • 13 comments

Consider the following code:

 public async Task<TResponse> Handle(ReceiveContext<TRequest> context, CancellationToken token)
        {
            var request = context.Message as TRequest;
            var response = Activator.CreateInstance<TResponse>();

            Raise<NullReferenceException>.If(response == null, $"Could not create an instance of {typeof(TResponse).Name}");

            if (request.IsQueryValid(token, out var errors))
            {
                if (_cnn.State != ConnectionState.Open)
                    _cnn.Open();

                Builder.ApplyLimitingAndSorting(request);
                await Inquire(request, response, token);
                
                if (_cnn?.State == ConnectionState.Open)
                {
                    _cnn.Close();
                    _cnn.Dispose();
                }
            }
            else
                Raise<ApplicationException>.If(true, string.Join(", ", errors.Select(x => x.ErrorMessage)));

            return response;
        }

It crashes the mediator with the following error: 14-Mar-2019 16:21:23.35||ERROR|System.NullReferenceException: Object reference not set to an instance of an object. at Mediator.Net.Pipeline.EmptyPipeSpecification1.OnException(Exception ex, TContext context) at Mediator.Net.Pipeline.GlobalReceivePipe1.Connect(TContext context, CancellationToken cancellationToken) at Mediator.Net.Mediator.SendMessage[TMessage](TMessage msg, CancellationToken cancellationToken) at Mediator.Net.Mediator.RequestAsync[TRequest,TResponse](TRequest request, CancellationToken cancellationToken)

However when I make changes like this:

public Task<TResponse> Handle(ReceiveContext<TRequest> context, CancellationToken token)
        {
            var request = context.Message as TRequest;
            var response = Activator.CreateInstance<TResponse>();

            Raise<NullReferenceException>.If(response == null, $"Could not create an instance of {typeof(TResponse).Name}");

            if (request.IsQueryValid(token, out var errors))
            {
                if (_cnn.State != ConnectionState.Open)
                    _cnn.Open();

                Builder.ApplyLimitingAndSorting(request);
                Inquire(request, response, token).GetAwaiter();
                
                if (_cnn?.State == ConnectionState.Open)
                {
                    _cnn.Close();
                    _cnn.Dispose();
                }
            }
            else
                Raise<ApplicationException>.If(true, string.Join(", ", errors.Select(x => x.ErrorMessage)));

            return Task.FromResult(response);
        }

it runs perfectly fine. Aren't we supposed to call async methods ?

SuheylZ avatar Mar 14 '19 11:03 SuheylZ

Hi! Thanks for getting in touch, i am working on this issue now and will keep you updated Regards Eddy

mayuanyang avatar Mar 15 '19 00:03 mayuanyang

Hi

Just wrote a test case and did not manage to reproduce the problem, can you please advice which instance is actually null?

Here is my test case https://github.com/mayuanyang/Mediator.Net/blob/7c348efae6019b2bb9ccf9c1e222d31ec7a6920b/src/Mediator.Net.Test/TestRequestHandlers/TestAsyncRequestHandler.cs#L21

The handler https://github.com/mayuanyang/Mediator.Net/blob/7c348efae6019b2bb9ccf9c1e222d31ec7a6920b/src/Mediator.Net.TestUtil/Handlers/RequestHandlers/AsyncRequestHandler.cs#L14

and the result is in here https://ci.appveyor.com/project/mayuanyang/mediator-net

mayuanyang avatar Mar 15 '19 02:03 mayuanyang

sorry for a delayed response. Let me have a look at the test case you mentioned.

SuheylZ avatar Mar 19 '19 06:03 SuheylZ

I need to share some private code with you for the same. Queries if made async it just errors out that Response is null.

SuheylZ avatar Jun 28 '19 10:06 SuheylZ

Sure thing , how would you like to send?

mayuanyang avatar Jun 30 '19 16:06 mayuanyang

can't do it on github? how about skype? i don't know if it's okay to share it here. or any other way that you think would work

SuheylZ avatar Jun 30 '19 16:06 SuheylZ

Email would work for me [email protected]

mayuanyang avatar Jul 01 '19 04:07 mayuanyang

Same problem for me.

I share a solution (net Core 3.0) to reproduce the problem Mediator.zip

The problem seems to be in the RequestPipe.cs, ConnectToHandler(), line 64 task.GetType().GetTypeInfo().GetDeclaredProperty("Result")

it returns null

basbros avatar Oct 15 '19 20:10 basbros

Sorry, it seems already fixed with 3.0.0 dev20

basbros avatar Oct 15 '19 20:10 basbros

Is there any update for the async handlers for queries?

SuheylZ avatar Oct 29 '19 14:10 SuheylZ

Hi @MercedeX Sorry for being late, was extremely busy, however i managed to get some time and write some tests, the tests seems working fine for me, you might interest on the following files

  • The test https://github.com/mayuanyang/Mediator.Net/blob/inheritanceTest/src/Mediator.Net.Test/TestInheritance/TestInheritanceSpec.cs

  • The handlers being used for the tests https://github.com/mayuanyang/Mediator.Net/blob/inheritanceTest/src/Mediator.Net.TestUtil/Handlers/CommandHandlers/InheritanceBaseCommandHandler.cs https://github.com/mayuanyang/Mediator.Net/blob/inheritanceTest/src/Mediator.Net.TestUtil/Handlers/RequestHandlers/InheritanceBaseRequestHandler.cs

Can you please have a look and check if i missed anything, also please note that the tests were written against the 3.0.0-dev in case if you are using 2.x.x

Regards Eddy

mayuanyang avatar Nov 30 '19 09:11 mayuanyang

Sure, I would do that.

Busy working on another large scale system and planning on using your implementation for that also.

Is it possible that I can have submit fixes, if any to you and you can add them after verifying?

SuheylZ avatar Dec 04 '19 06:12 SuheylZ

For sure, you are very welcome to do so :)

mayuanyang avatar Dec 04 '19 09:12 mayuanyang