Closed shahabganji closed 5 years ago
Hi @shahabganji
I ran your sample without Grace and I get the following error
HelloMicroServices>
HelloMicroServices> 05:16:42 [Information] () Unable to connect to broker
HelloMicroServices>
HelloMicroServices> 05:16:42 [Fatal] () Host terminated unexpectedly
HelloMicroServices> RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable ---> RabbitMQ.Client.Exceptions.ConnectFailureException: Connection failed ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.99.100:5672
HelloMicroServices> at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
HelloMicroServices> at System.Net.Sockets.Socket.<>c.<ConnectAsync>b__272_0(IAsyncResult iar)
HelloMicroServices> --- End of stack trace from previous location where exception was thrown ---
HelloMicroServices> at RabbitMQ.Client.TcpClientAdapter.ConnectAsync(String host, Int32 port)
HelloMicroServices> at RabbitMQ.Client.Impl.TaskExtensions.TimeoutAfter(Task task, Int32 millisecondsTimeout)
HelloMicroServices> at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail(ITcpClient socket, AmqpTcpEndpoint endpoint, Int32 timeout)
HelloMicroServices> --- End of inner exception stack trace ---
I'm not familiar with RawRabbit so I'm not really sure what I'm looking at. My guess is that the problem has to do with Grace picking a different constructor or activating a type that wasn't expected (it automatically resolves concrete types).
Do you know the specific type that's being constructed incorrectly?
@ipjohnson
Your error is due totally to the absence of RabbitMQ, you need to either have it on your machine or docker, if the latter, bear in mind to change the Hostnames and port to what docker exposes.
Do you know the specific type that's being constructed incorrectly?
AFAIK it uses RawRabbit.Instantiation.RawRabbitFactory
to instantiate IBusClient
instances and the return value is of Type RawRabbit.Instantiation.Disposable.BusClient
.
RawRabbitFactory and BusClient
this.Client = RawRabbitFactory.CreateSingleton(new RawRabbitOptions() {
ClientConfiguration = new RawRabbitConfiguration() {
Hostnames = new System.Collections.Generic.List<string>() { "localhost" },
Password = "guest",
VirtualHost = "/",
Port = 5672,
Username = "guest"
}
});
A code like that :point_up: works with Grace, as mentioned here
I am wondering( not sure ) how docs for v2 can be fruitful.
@shahabganji I installed RabbitMQ last night but I'm still having connection issues. Is there something more I need to do?
@ipjohnson Have you changed these parts in the appsettings.json
file to match your machine?
Port
and Virtual Host
are set to the default values, I think you only need to change the Hostnames
to localhost
or the IP
address of your machine, on which you installed RbbitMQ.
Hi @ipjohnson,
Any success? Have you installed it on your local machine or on docker?
@shahabganji so I'm able to run the example app and call the product api with and without Grace. What error should I be looking for?
Hi @ipjohnson
Firstly, I should mention that there is no error, there is a misbehavior of the library( at least I guess so :see_no_evil: )
When using default IOC and posting to the api, e.g. /api/shopping-cart/1?products=1&products=2
you should have some logs like
08:38:46 [Information] () Message received from rabbitmq : ShoppingCartItemAdded {UserId=1, ProductId=1}
08:38:46 [Information] () Recieived ack for 1
08:38:46 [Information] () Message received from rabbitmq : ShoppingCartItemAdded {UserId=1, ProductId=2}
08:38:46 [Information] (707ddb7a-0d5a-4a70-84df-9a2a4713fff5) Data ShoppingCartItemAdded {UserId=1, ProductId=1} published
however, when using Grace as IOC and posting to the same API, this will be found in the logs
08:45:55 [Warning] (dfd989cd-51f4-4aa5-b520-4ce8115eeeac) No body found in the Pipe context.
the latter indicates that the messages published with 0 payload which means the RawRabbit's IBusClient
did not perform as it should be, and there is no subscriber in the Pipe, the former shows that everything works seamlessly.
At first I thought that may be my configuratuions here is wrong so I added:
this.Client = RawRabbitFactory.CreateSingleton(new RawRabbitOptions() {
ClientConfiguration = new RawRabbitConfiguration() {
Hostnames = new System.Collections.Generic.List<string>() { "localhost" },
Password = "guest",
VirtualHost = "/",
Port = 5672,
Username = "guest"
}
});
where I create the IBusClient
in the constructor of subscriber and publisher, surprisingly it worked, that was the reason I got suspicious to DI system and tried to change from grace to the built-in one.
@shahabganji when I run the solution and hit that url I actually don't get the logging output you mention there isn't anything about raw rabbit mq. The output below is just running it with out grace
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Incoming Request: "GET", PathString {Value="/api/shopping-cart/1", HasValue=True}, [KeyValuePair`2 {Key="Connection", Value=["keep-alive"]}, KeyValuePair`2 {Key="Accept", Value=["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"]}, KeyValuePair`2 {Key="Accept-Encoding", Value=["gzip, deflate, br"]}, KeyValuePair`2 {Key="Accept-Language", Value=["en-US,en;q=0.9"]}, KeyValuePair`2 {Key="Host", Value=["localhost:5001"]}, KeyValuePair`2 {Key="User-Agent", Value=["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"]}, KeyValuePair`2 {Key="Upgrade-Insecure-Requests", Value=["1"]}]
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Route matched with "{action = \"Get\", controller = \"ShoppingCart\"}". Executing action "HelloMicroServices.Controllers.ShoppingCartController.Get (HelloMicroServices)"
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Executing action method "HelloMicroServices.Controllers.ShoppingCartController.Get (HelloMicroServices)" with arguments (["1"]) - Validation state: Valid
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Executed action method "HelloMicroServices.Controllers.ShoppingCartController.Get (HelloMicroServices)", returned result "Microsoft.AspNetCore.Mvc.OkObjectResult" in 2.4329ms.
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Executing ObjectResult, writing value of type '"HelloMicroServices.Datastores.Models.ShoppingCart"'.
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Executed action "HelloMicroServices.Controllers.ShoppingCartController.Get (HelloMicroServices)" in 198.242ms
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Request: "GET", PathString {Value="/api/shopping-cart/1", HasValue=True} executed in 295 ms
06:29:18 [Information] (509590d2-2844-4010-ab30-72dc61c6a5e1) Outgoing Response: 200, [KeyValuePair`2 {Key="Date", Value=["Wed, 15 Aug 2018 12:29:18 GMT"]}, KeyValuePair`2 {Key="Transfer-Encoding", Value=["chunked"]}, KeyValuePair`2 {Key="Content-Type", Value=["application/json; charset=utf-8"]}, KeyValuePair`2 {Key="Server", Value=["Kestrel"]}]
Sorry my bad, the url I mentioned above is an HTTP POST.
@shahabganji ok I was able to get messages published by turning off the auto registration of unknown types.
Program.cs
.UseGrace(new InjectionScopeConfiguration{ AutoRegisterUnknown = false })
Startup.cs
public void ConfigureContainer(IInjectionScope scope)
{
// empty as everything is already registered in the service collection
}
@ipjohnson, thanks for your response and solution. Is it kinda a mixed mode between Grace
and Microsoft.Extensions.DependencyInjection
; using the built-in DI to register and Grace to instantiate.
May I ask what was the problem? and what if I move the registration of services to ConfigureContainer
method? When I do, MVC pipeline fails at runtime.
and one thing more is it possible to have access to IServiceCollection
in ConfigureContainer
, since it would be a clearer code if we had all related stuff at one place.
@shahabganji correct the way Microsoft designed DI for asp.net core is that all of the framework dependencies are registered in the IServiceCollection (and 3rd party dependencies). Then all of those definitions are loaded into the external container (this case it's Grace). Then finally the ConfigureContainer method is called to do any registration for the 3rd party container using the specific registration interface for the container.
The problem you were having related to the fact that Grace will auto register concrete types by default so I think one of the optional configuration classes was being instantiated when it wasn't supposed to.
You have to keep the ConfigureContainer
method but you can leave it empty and do all of your registration against the IServiceCollection in the ConfigureServices
method.
That's what I expected from external containers, however, I expect that by turning off the AutoRegisterUnknown
property and moving the registration of services to ConfigureContainer
, the application still work. but to my surprise it doesn't !!!
One more thing, how could we find out that which dependency causes the problem? Is there any flag or log that reveals such information?
@shahabganji you'd have to ask the raw rabbit folks what specifically didn't work in raw rabbit, from my perspective Grace functioned properly as it resolved all dependencies without exceptions.
I look at a container as something you use to construct your application. Not all containers function the same. I've made Grace a container that can be configured for many different scenarios. In this case it had to be configured to turn off auto registration because of the way RawRabbit is written not because it's an issue with Grace. Not saying that what they did was wrong in any way just that Grace had to be configured for the specific use case.
As for the ConfigureContainer
method having to be there, that's part of the Microsoft DI conventions and is true of all 3rd party container not just Grace. I believe the method signature is used by the framework to figure out what container to use. The UseGrace
method just adds a dependency to the service collection which is then resolved by the framework.
@ipjohnson Thanks for your time.
@shahabganji glad it worked it out. To answer your question of is there a log for Grace. There isn't a regular log but there is a Trace function that you can attach to and it will call during construction of the activation delegate.
var container = new DependencyInjectionContainer(c => c.Trace = s => Console.WriteLine(s));
@ipjohnson Good to know about that :+1:
I was creatng a sample using RawRabbit and as always I used Grace to handle DI. however, I faced an issue in which the publisher and subscriber do not work as expected. After investigating through we got suspicious to how the objects are created so I commented the Grace parts and used the default IOC, surprisingly everything worked just fine,
I have a sample repository here
this commit uses Grace and this one with default IOC
I would be grateful if you could take a look.
Regards, -Shahab