Why when publish message to RabbitMQ with MassTransit, sends to another endpoint with skipped? - asp.net-core

Here comes my code on my publisher app (a netcore API).
services.AddMassTransit(masstransit =>
{
masstransit.UsingRabbitMq((context, cfg) =>
{
cfg.Host(new Uri("rabbitmq://srv-docker-dev-01"), "/", h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ReceiveEndpoint("implantacao", e =>
{
e.ConfigureConsumeTopology = false;
e.Bind<ClienteAlteradoEvento>();
});
});
});
Even before I create a consumer, my RabbitMQ shows a skipped queue.
And the message is delivered on this __skipped.
Can someone tell me what I'm doing wrong?
Just a few points:
My consumer will not have access to the event class of my producer.
I will have 2 queues which have to consume my API. I'll probably configure another receive endpoint.
I thought I should have only 1 exchange for each microservice. Like, all the events published by comercial microservice, should use the same exchange, but MassTransit is creating one exchange each type. Is that correct?
Any thoughs and ideas, will be welcome. I'm just learning about RabbitMQ.
EDIT
Microservice A: Have endpoints to receive user input data of customers. Users send data like names, contracts, and anything else (many different types of data can be changed on different endpoints). Every time a customer is updated, this API should publish messages to update other microservices too. Lets say we have at least 3 different events: CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent.
Microservice B: Want to consume the updates from costumer published by Microservice A. We don't have access to CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent classes. We should build our class type on its side.
Microservice C: Want to consume the updates from costumer published by Microservice A. We don't have access to CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent classes. We should build our class type on its side.
Neither B or C have access to class type on microservice A.
Is that possible? Does it makes sense?
Thanks

You are configuring a receive endpoint without any consumers on it. So any message produced that arrives on the queue will just be copied to the _skipped queue.
I'd suggest reading some documentation to get the feel for how messages, consumers, and endpoints are configured.
I wouldn't suggest using a single exchange (or even a single queue) for all the messages in a service, but since you're just learning I don't really know what else to suggest without details.

It is not recommended by Chris Patterson here, you could use RabbitMQ.Client. but it is not impossible.
In this documentation there are two ways to better understand:
Using ISendEndpoint Send<T>(...)
var endpoint = await busControl.GetSendEndpoint(new Uri("exchange:my-exchange"));
await endpoint.Send(new {});
Using IBus Publish<T>(...)
var bus = Bus.Factory.CreateUsingRabbitMq((cfgBus) =>
{
cfgBus.Host(host: eventbusoptions.Host);
// Remove default wrapper message
cfgBus.ClearSerialization();
cfgBus.UseRawJsonSerializer();
// Set exchange name
cfgBus.Message<SubmitOrder>(top =>
{
top.SetEntityName(eventbusoptions.ExchangeName);
});
// Configurations per Publish
cfgBus.Publish<SubmitOrder>(top =>
{
top.ExchangeType = eventbusoptions.ExchangeType;
top.Durable = false;
top.BindQueue(eventbusoptions.ExchangeName, eventbusoptions.QueueName, bind =>
{
bind.RoutingKey = eventbusoptions.RoutingKey;
bind.ExchangeType = eventbusoptions.ExchangeType;
bind.Durable = false;
});
});
});
await _bus.Publish<SubmitOrder>(order, context => context.SetRoutingKey(_eventBusOptions.RoutingKey));

I just realize MassTransit isn't what I'm looking for right now.
I read about RabbitMQ and people told me MassTransit should be a nice approach but I disagree. Maybe for some scenarios it would be perfect, but when you can't have the same type on both projects, it's a pain.
The "exchanges must be type" isn't flexible enough.
The problem of my question is the answer gave by Chris. But Mass will not do what I want. His answer is right, btw.

Related

Using NServiceBus in a synchronous API

I'm exposing an API to a vendor where that vendor requires the API to be synchronous. I however would like to use NServiceBus on the backend of it to make good use of our other architecture.
Is there a product/framework that can be used to do support this flow?
Are there any thoughts/considerations in choosing this approach?
The API is as said synchronous where we will transform the request a bit and then put it on an NServiceBus queue for further processing by other systems.
After the message has been sent to a queue we should wait for the other system to complete its actions and be woken up again when the reply message is received.
Pseudo code:
void APICall(String someMessage) {
var msgBusMessage = new { json = someMessage, ID = Guid.NewID() };
NServiceBus.EnqueueMessage(msgBusMessage);
var returnMessage = NServiceBus.WaitForReplyMessageWithID(msgBusMessage.ID);
return returnMessage;
}
NServiceBus has a feature called Callbacks which is designed to handle this type of interaction. It works almost exactly like the snippet you have provided. You send a request via NServiceBus and then get a Task that will eventually contain the response. You can await that task and return the result to the synchronous API.
To set it up:
Add a reference to the NServiceBus.Callbacks package (in both the sender and the receiver endpoints)
Enable callbacks by calling endpointConfiguration.EnableCallbacks(). If an endpoint returns replies but does not request request synchronous callbacks then you should use endpointConfiguration.EnableCallbacks(makesRequests: false)
Any endpoint that makes callback requests should be made Uniquely Addressable endpointConfiguration.MakeInstanceUniquelyAddressable(someUniqueIdThatSurvivesRestarts). This allows the response message to be routed to the specific endpoint instance that is waiting for it.
In the caller, use the following var response = await endpoint.Request<ResponseMessage>(new RequestMessage { ... })
In the receiver create a handler for RequestMessage and return context.Reply(new ResponseMessage {...})
You can read more about this feature (including some caveats around when you should and shouldn't use it) in the documentation. There is also a sample showing the feature in use.

SignalR WCF service to MVC5 Client. Is it possible?

So I am familiar with SignalR in respect to Client/Server communication from a hub within an MVC Site project pushing to a javascript Client. Its a very simplistic approach to Server to Client communication.
My issue is, I have a more complex architecture. MVC5 UI that makes calls to WCF services where all the computing and business logic is occurring.
My question is, I have an MVC view that is a table of information. One column contains the # items within a box. I want to update the view every time something is removed or added from the box. However, adding and removing items are not done via the UI, they are done from an outside process calling into our WCF service. We do some computation within the service and then update the count of items in the box and save it to the DB. We would like, at the time of saving to the DB to also be able to Call the SignalR hub and have it notify all the clients that the count has increased which in turn will update the table on the view. Can this be done? Can you make a call to a hub within a MVC application from a WCF service?
Can you make a call to a hub within a MVC application from a WCF
service?
Yes you can create a Duplex Service. In the callback operation (Duplex Service), the service can also call some function in the client. This function on the client is where you will make a call to your SignalR Hub method to notify your clients.
Have a look at the following samples:
http://www.c-sharpcorner.com/uploadfile/dhananjaycoder/a-simple-duplex-service-in-wcf/
https://msdn.microsoft.com/en-us/library/ms752216(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/ms731184(v=vs.110).aspx
You can,
when you have some change, call for hub, the hub broach to client and then client callback to refresh:
client
$(function () {
var notifications = $.connection.pubsHub;
notifications.client.alertms = function () {
//if (ms === "pubs")
getAllMessages()
};
// Start the connection.
$.connection.hub.start().done(function () {
//alert("connection started")
getAllMessages();
}).fail(function (e) {
alert(e);
});
});
function getAllMessages() {
$.post('#(Url.Action("GetMessages", "Home", null, Request.Url.Scheme))')
.done(function (response) {
$("#messagesTable").html(response)
});
};
</script>

How to get the source address in Rebus?

How do I get the source address in a message received?
The context is that I'm designing a monitor for a service bus implemented with Rebus. I use the publish - subscribe pattern thus a message is always published on a topic. The monitor subscribes to all topics in order to supervise that a service has send something and so is alive and healthy. Though in a message handler the received message don't contain any source address or information identifying the service publishing. This means it's not possible to supervise which services are alive and healthy. Of course I can create an attribute "Service" identifying the service publishing in all messages. This implies that each service have to set the attribute before publishing a message, which I find a bit cumbersome. The source address is there and can identify the service publishing.
When you're in a Rebus message handler, you can access the IMessageContext - either by having it injected by your IoC container (which is the preferrent way, because of the improved testability), or by accessing the static MessageContext.Current property.
The message context gives you access to a couple of things, where the headers of the incoming transport message can be used to get the return address of the message (which, by default, is set to the sender's input queue).
Something like this should do the trick:
public class SomeHandler : IHandleMessages<SomeMessage>
{
readonly IMessageContext _messageContext;
public class SomeHandler(IMessageContext messageContext)
{
_messageContext = messageContext;
}
public async Task Handle(SomeMessage message)
{
var headers = _messageContext.TransportMessage.Headers;
var returnAddress = headers[Headers.ReturnAddress];
// .. have fun with return address here
}
}

RabbitMQ Routing Keys

Good Day.
Is there a way to retrieve routing keys for an existing exchange (fanout or topic) via the browser based UI?
I don't have access to the client source code (producer) to see which routing keys are being sent to the model.
Thank you.
Edit:
The idea is to try and latch on to an existing fanout exchange (which I cannot reconfigure). I want to create a new exchange, bind it to this one and only filter out certain messages.
Use the HTTP API:
http://localhost:15672/api/exchanges/vhost/name/bindings/source
A list of all bindings in which a given exchange is the source.
for example:
http://localhost:15672/api/exchanges/%2F/my_exchange/bindings/source
[
{
"source":"my_exchange",
"vhost":"/",
"destination":"my_queue",
"destination_type":"queue",
"routing_key":"my_routkey",
"arguments":{
},
"properties_key":"my_routkey"
}
]

Slow MSMQ within a WCF service

this is a weird thing.
I created a simple SOAP based web service with WCF. When the 'SubmitTransaction' method is called, the transaction is being passed on to an application service. But if the application service is not available, it is being written to a MSMQ.
Like this:
public void SubmitTransaction(someTransaction)
{
try
{
// pass transaction data to application
}
catch(SomeError)
{
// write to MSMQ
}
}
So when an error occures the transaction is written to the queue. Now, when using the MSMQ API directly in my WCF service, everything is fine. Each call takes a few milliseconds.
E.g.:
...
catch(SomeError)
{
// write to MSMQ
var messageQueue = new MessageQueue(queuePath);
try
{
messageQueue.Send(accountingTransaction, MessageQueueTransactionType.Single);
}
finally
{
messageQueue.Close();
}
}
But since I want to use the message queue functionality at some other points of the system as well, I created a new assembly that takes care of the message queue writing.
Like:
...
catch(SomeError)
{
// write to MSMQ
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
}
Now when using this setup, the web service is suddenly very slow. From the above-mentioned milliseconds, each call now takes up to 4 seconds. Only because the message queue stuff is encapsulated in a new assembly. The logic is exactly the same. Anyone knows what the problem could be...?
Thanks!
Ok, now I know. It has something to do with my logging setup (log4net). I'll have to check that first. Sorry for stealing your time..
You have two new lines of code here:
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
Do you know which of the two is causing the problem? Perhaps add some logging, or profiling, or step through in a debugger to see which one seems slow.