rebus-org / Rebus.AzureServiceBus

:bus: Azure Service Bus transport for Rebus
https://mookid.dk/category/rebus
Other
33 stars 20 forks source link

Unable to mix old and new never versions of Rebus using ASB transport #66

Closed mclausen closed 3 years ago

mclausen commented 3 years ago

Hi Rebus team, We do have a little challenge that I need some help solving. Currently we are running a lot of different Rebus workers, with different versions of Rebus.

A previous update to Rebus and Azure Service Bus transport, had quite a big breaking change, that lower cases all input queue to the service. For topics this was mainly mitigated using the .UseLegacyNaming() on the Azure Service Bus Transport configuration. Our challenge now is that are unable to .Send(msg) to an older version Rebus.

The input queue name for the older service is called hosting-management-input. We do have a lot of systems that utilizes this queue, and as such updating the queue name would require significant changes to all services, across our platform, and would require a pretty nasty maintenance window, to ensure that everything is updated and routed correctly. That said mass upgrading rebus workers is unfortunately not an option at this moment.

Our newer service are running a newer version of rebus that expect input queues to be lowercased even though we explicitly mapped the name with a dash based name.

Screenshot 2021-01-29 at 13 10 33

But when sending the message It tries to send it to the lower cased input queue name, which obviously do not exist.

Screenshot 2021-01-29 at 13 12 13

How can we move forward from here?

mookid8000 commented 3 years ago

Without completely understanding the details of how you got this issue, here's something you might be interested in looking at.... Rebus' ASB transport uses an INameFormatter to modify the names of the entities: https://github.com/rebus-org/Rebus.AzureServiceBus/blob/master/Rebus.AzureServiceBus/AzureServiceBus/NameFormat/INameFormatter.cs

Maybe you can decorate/replace its name formatter and come up with some rules that fit your conventions?

Something like

Configure.With(...)
    .(...)
    .Options(o => o.Decorate<INameFormatter>(c => new CustomNameFormatter(c.Get<INameFormatter>())))
    .Start();

where the decorator could (un)mangle the names however you feel like:

class CustomNameFormatter : INameFormatter
{
    // ...
}
mclausen commented 3 years ago

Thank you @mookid8000, it will definitly be looking into on the short term, but I really really really hoped that we could figure something out long term instead of having to do custom name formatter for every rebus worker that we use 🙈.

The old project is running the following versions of the service bus, which by it self is not an issue.

<PackageReference Include="Rebus" Version="5.3.1" />
<PackageReference Include="Rebus.AzureServiceBus" Version="6.0.7" />

The challenge that arises is using a later version of Rebus together with a newer version of Rebus.AzureServiceBus.

<PackageReference Include="Rebus" Version="6.4.1" />
<PackageReference Include="Rebus.AzureServiceBus" Version="8.0.1" />

In between those version there is a huge breaking change in the naming schemes that cannot be mitigated by using the .UseLegacyNaming() extension method. Effectively it means that we are unable to route messages to queues that does contain -.

Would you like me to scaffold a breaking test?

mookid8000 commented 3 years ago

You could also simply manually create a queue by that name, and then configure its ForwardTo property to point to the real destination queue name. And then, when all the stars align and you have updated all of your Rebus endpoints to the newest version, then the old queues could be deleted.

mclausen commented 3 years ago

It's definitely option. I'll properly need to reconsider this, and perhaps rolling back the version for now. I must amid its quite a challenge, because we love the simplicity of Rebus, and its operationally hazzle, when too much manual configuration is needed. Out of curiosity, looking at the current INameFormatter.FormatQueueName, what is holding us back submitting a pr, that doesn't swap the - or meddle with the router mapping of queue names? Is it something that you'd be interested in? 🙂

mookid8000 commented 3 years ago

(...) what is holding us back submitting a pr, that doesn't swap the - or meddle with the router mapping of queue names?

The fact that it could potentially break a lot of stuff running out there right now.

Is it something that you'd be interested in? 🙂

Not really at this point, sorry. I really need to leave the name mangling alone, because trying to satisfy too many requirements at the same time has led to the current, slightly confusing situation. No need for more confusion at this time.

If I were you, I would set up a bunch of (integration) test cases with a dedicated Azure Service Bus namespace, where you can replicate your current topology. You can then experiment with modifying/replacing the INameFormatter implementation until it meets your needs.

mclausen commented 3 years ago

The challenge with a custom name formatter is that it needs to be distributed to 20 input queues, and that carries a high risk of failure, doing too much custom juggling 🥴.

Its a bit unfortunate with the rebus version compatibility breaks on the update, but we managed to do some hoops jumping and used the ForwardTo property for the queue in question There is still a handful of queues that needs to be handheld for updates for system wide rebus compatibility. But we'll take that one step at a time.

For input, it's the input queue mapping on the router that messes the compatibility up. Out of curiosity what would the side-effects be, to not do any fancy naming formatter on the routing slip? 🕵️