rebus-org / Rebus

:bus: Simple and lean service bus implementation for .NET
https://mookid.dk/category/rebus
Other
2.32k stars 363 forks source link

Pub/Sub and typerouting - Azure Service Bus #1097

Closed NWessel closed 1 year ago

NWessel commented 1 year ago

P.S, kommer gerne forbi med en øl :D

I have what might be a weird bug? Maybe it is my configuration..

I have a .net 7 api where I'm doing some testing with Rebus and Azure Service Bus. It took some time, but I figured out the general workings. That if you want to listen to messages it HAS to be from queues, but you can publish messages to topics. You can also subscribe to a topic, which will setup a subscription that forwards messages to said queue.

https://github.com/NWessel/SimpleRebus I have this code, and by comment you can see what works and what doesn't. I thought that when I had setup typebased routing that I would be able to just call _bus.Publish and _pub.Subscribe - But it only works when i go into _bus.Advanced.Topics. ETC I put it all in the same place for readability

public class TestingController : ControllerBase
{
    private readonly IBus _bus;

    public TestingController(IBus bus)
    {
        _bus = bus;
    }

    [HttpPost(Name = "SendMessage")]
    public async System.Threading.Tasks.Task SendMessage([FromBody] Project project)
    {
        try
        {
            //Doesn't work
            await _bus.Publish(project);

            //works
            await _bus.Advanced.Topics.Publish("project", project);

            //Doesn't work
            await _bus.Subscribe<Project>();

            //works
            await _bus.Advanced.Topics.Subscribe("project");
        }
        catch (Exception e)
        {
        }

    }
}

I get the following message in my exception from those marked as not working

**The specified HTTP verb (GET) is not valid. To know more visit https://aka.ms/sbResourceMgrExceptions. . TrackingId:8007a571-1b5e-4a32-8bae-9b8210e310de_G2, SystemTracker:ndwtest:Queue:simplerebus, Timestamp:2023-06-29T18:57:50 Status: 400 (Bad Request)

Content:

400The specified HTTP verb (GET) is not valid. To know more visit https://aka.ms/sbResourceMgrExceptions. . TrackingId:8007a571-1b5e-4a32-8bae-9b8210e310de_G2, SystemTracker:ndwtest:Queue:simplerebus, Timestamp:2023-06-29T18:57:50** This is my program.cs file with the typebased routing ```csharp using Rebus.Config; using Rebus.Routing.TypeBased; using SimpleRebus.Incoming; using SimpleRebus.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddRebusHandler(); builder.Services.AddRebus(configure => configure .Transport(t => t.UseAzureServiceBus(builder.Configuration["AzureServiceBusConnectionString"], "teamplanner")) .Logging(l => l.ColoredConsole(Rebus.Logging.LogLevel.Debug)) .Routing(r => r.TypeBased() .Map("project") .Map("resource") .Map("task")) ); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); ```
mookid8000 commented 1 year ago

Hi @NWessel , sounds pretty weird!

Initially, I though that that endpoint mappings (r.TypeBased().Map<...>(...) etc) could somehow interfere with the transport's mapping of .NET types to topic names, but that does not seem to be the case.

I coded this in my attempt to reproduce the odd behavior: https://github.com/rebus-org/Rebus.AzureServiceBus/blob/master/Rebus.AzureServiceBus.Tests/Bugs/EndpointMappingsDoNotInterfereWithPubSub.cs

Could you maybe take a look at it and see in what ways your code differs from the example?

mookid8000 commented 1 year ago

P.S, kommer gerne forbi med en øl :D

Det er sgu pænt af dig! 🙂 men jeg har øl nok 🤠

IMG_5395

(har en ølbutik med 168 forskellige øl på hylden...)

NWessel commented 1 year ago

Going to look at your code now - And for good measures, just adding the stacktrace of the error I got

at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.d7.MoveNext() at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.d14.MoveNext() at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.d11.MoveNext() at Azure.Messaging.ServiceBus.Administration.ServiceBusAdministrationClient.d48.MoveNext() at Rebus.AzureServiceBus.AzureServiceBusTransport.d28.MoveNext() at Rebus.AzureServiceBus.AzureServiceBusTransport.<>cDisplayClass86_0.<b1>d.MoveNext() at Rebus.AzureServiceBus.AzureServiceBusTransport.d86.MoveNext() at Rebus.AzureServiceBus.AzureServiceBusTransport.<>cDisplayClass35_0.<gSendOutgoingMessagesToDestination|3>d.MoveNext() at Rebus.AzureServiceBus.AzureServiceBusTransport.<>cDisplayClass35_1.<gSendOutgoingMessages|1>d.MoveNext() at Rebus.Transport.TransactionContext.d32.MoveNext() at Rebus.Transport.TransactionContext.d27.MoveNext() at Rebus.Bus.RebusBus.d43.MoveNext() at Rebus.Bus.RebusBus.d34.MoveNext() at SimpleRebus.Controllers.TestingController.d__5.MoveNext()

NWessel commented 1 year ago

I deleted all topics and queues and started the solution and now it is working - I also removed the routing with typebased().map and everything also runs smoothly. I thought I knew what that route mapping did, but now I'm unsure :D Could you give a few words on what the routing solves then? I thought it would use that mapping when publishing a message, and use that as topic name. But that doesn't seem to be the case

I would have expected to see a topic here called "myeventthing" image image

Am I misunderstanding something?

mookid8000 commented 1 year ago

When you

await bus.Send(new SomeKindOfMessage());

Rebus will look up the destination queue in its endpoint mappings. So if you have

.Routing(r => r.TypeBased().Map<SomeKindOfMessage>("some-queue")

it will send the message to the queue "some-queue".

Since Azure Service Bus has native support for topic-based routing (i.e. "pub/sub messaging"), the endpoint mappings don't have any effect or relevance for pub/sub messaging.

If you want to customize the topic names, one way to do that is to register a custom ITopicNameConvention, which is what Rebus uses to get topic names for different message types.

NWessel commented 1 year ago

Seems like I'm not allowed to register a new one image

mookid8000 commented 1 year ago

Oh yes you are, but there can be only one primary IBus in the container (which will be the bus instance injected into MVC controller, etc).

As the error message says 😁 : You'll need to register additional bus instances with isDefaultBus: false.