Particular / NServiceBus.Transport.AzureServiceBus

Azure Service Bus transport
Other
22 stars 19 forks source link

Support for hierarchical entities #1013

Open danielmarbach opened 4 months ago

danielmarbach commented 4 months ago

Describe the feature.

Is your feature related to a problem? Please describe.

Azure Service Bus allows entities to be organized in hierarchies on the same namespace. This can be handy to group for example tenant related queues and topics together.

So, for example, you can have a hierarchy like this

tenanta/endpoint1 tenanta/endpoint2 tenantb/endpoint1 tenantb/endpoint2

image

To achieve that, there are a number of "quirks" required on an endpoint configuration level.

The trick is to override the local queue address to contain the hierarchy and make sure the routing table contains the hierarchy too. For separate audit and error queues, you also need to make sure the audit and error queues are configured accordingly.

        var tenantIdentifier = Environment.GetEnvironmentVariable("TenantIdentifier");

        var endpointConfiguration = new EndpointConfiguration($"Endpoint1");
        // Override the local address
        endpointConfiguration.OverrideLocalAddress($"{tenantIdentifier}/Endpoint1");
        endpointConfiguration.EnableInstallers();

        // Override the diagnostic path to have unique paths for endpoint for demo purposes
        endpointConfiguration.SetDiagnosticsPath($".diagnostics/{tenantIdentifier}");

        // configure tenant specific error queue
        endpointConfiguration.SendFailedMessagesTo($"{tenantIdentifier}/error");
        // configure tenant specific audit queue
        endpointConfiguration.AuditProcessedMessagesTo($"{tenantIdentifier}/audit");

        // switch the topology to have a bundle per tenant
        // make sure the subscription doesn't contain illegal characters in the path
        var transport = new AzureServiceBusTransport(connectionString)
        {
            Topology = TopicTopology.Single($"{tenantIdentifier}/bundle1"),
            SubscriptionNamingConvention = subscription => subscription.Replace($"{tenantIdentifier}/", string.Empty)
        };
        var routing = endpointConfiguration.UseTransport(transport);
        // Carefully override each command routing to go to the right destination
        routing.RouteToEndpoint(typeof(Command1), $"{tenantIdentifier}/Endpoint2");

There is currently one downside to this approach. You have to be careful to configure the tenant identifier on all the sends; otherwise you might send to some "central" queue.

SQS as the concept of QueueNamePrefix that is applied on a transport level, which makes "isolating" the same endpoints on the same SQS account a breeze and doesn't require changing the routing tables, error and audit queues.

Describe the requested feature

Add a possibility to leverage hierarchies to facilitate grouping of the same endpoints within a hierarchy.

Describe alternatives you've considered

None

Additional Context

Sample implementation

TenantsWithAsbUsingHierarchy.zip