@@ -15,59 +15,77 @@ public async Task<IEnumerable<ProxyRegistration>> Initialize(IReadOnlyCollection
1515 {
1616 // Assume that it is the number of endpoints that is more likely to scale up in size than the number of transports (typically only 2).
1717 // Therefore in cases where it might matter, it is more efficient to iterate over the transports multiple times.
18- transportConfigurationMappings = transportConfigurations . ToDictionary ( t => t . Name , t => t ) ;
1918
2019 IList < ProxyRegistration > proxyRegistrations = [ ] ;
2120
22- foreach ( var targetTransport in transportConfigurations )
21+ await CreateAndRegisterDispatchers ( transportConfigurations , proxyRegistrations , cancellationToken )
22+ . ConfigureAwait ( false ) ;
23+
24+ var allEndpoints = transportConfigurations . SelectMany (
25+ transport => transport . Endpoints . Select ( endpoint => ( transport , endpoint ) ) ) ;
26+
27+ foreach ( var ( transport , endpoint ) in allEndpoints )
2328 {
24- // Create the dispatcher for this transport
25- var dispatchEndpoint = await EndpointProxyFactory . CreateDispatcher ( targetTransport , cancellationToken ) . ConfigureAwait ( false ) ;
29+ AddressMap . Add ( transport , endpoint ) ;
30+
31+ var dispatcher = dispatchers [ transport . Name ] ;
32+ var queueAddress = new QueueAddress ( endpoint . Name ) ;
33+ var targetTransportAddress = dispatcher . ToTransportAddress ( queueAddress ) ;
34+ endpointAddressMappings [ endpoint . Name ] = endpoint . QueueAddress ?? targetTransportAddress ;
35+ targetEndpointDispatchers [ endpoint . Name ] = new TargetEndpointDispatcher ( transport . Name , dispatcher , targetTransportAddress ) ;
36+
37+ await CreateAndRegisterProxies ( transport , endpoint , transportConfigurations , proxyRegistrations , cancellationToken )
38+ . ConfigureAwait ( false ) ;
39+ }
40+
41+ return proxyRegistrations ;
42+ }
2643
44+ async Task CreateAndRegisterDispatchers (
45+ IReadOnlyCollection < BridgeTransport > transportConfigurations ,
46+ IList < ProxyRegistration > proxyRegistrations ,
47+ CancellationToken cancellationToken )
48+ {
49+ foreach ( var transport in transportConfigurations )
50+ {
51+ var dispatcher = await EndpointProxyFactory . CreateDispatcher ( transport , cancellationToken ) . ConfigureAwait ( false ) ;
52+ dispatchers . Add ( transport . Name , dispatcher ) ;
2753 proxyRegistrations . Add ( new ProxyRegistration
2854 {
2955 Endpoint = null ,
30- TranportName = targetTransport . Name ,
31- RawEndpoint = dispatchEndpoint
56+ RawEndpoint = dispatcher
3257 } ) ;
58+ }
59+
60+ AddressMap = new AddressMap ( dispatchers ) ;
61+ }
3362
34- // create required proxy endpoints on all transports
35- foreach ( var endpointToSimulate in targetTransport . Endpoints )
63+ async Task CreateAndRegisterProxies (
64+ BridgeTransport targetTransport ,
65+ BridgeEndpoint targetEndpoint ,
66+ IReadOnlyCollection < BridgeTransport > transportConfigurations ,
67+ IList < ProxyRegistration > proxyRegistrations ,
68+ CancellationToken cancellationToken )
69+ {
70+ // Endpoint will need to be proxied on the other transports
71+ foreach ( var proxyTransport in transportConfigurations )
72+ {
73+ if ( proxyTransport . Name == targetTransport . Name )
3674 {
37- // Endpoint will need to be proxied on the other transports
38- foreach ( var proxyTransport in transportConfigurationMappings . Where ( kvp => kvp . Key != targetTransport . Name ) . Select ( kvp => kvp . Value ) )
39- {
40- var startableEndpointProxy = await endpointProxyFactory . CreateProxy ( endpointToSimulate , proxyTransport , cancellationToken )
41- . ConfigureAwait ( false ) ;
42-
43- logger . LogInformation ( "Proxy for endpoint {endpoint} created on {transport}" , endpointToSimulate . Name , proxyTransport . Name ) ;
44-
45- var queueAddress = new QueueAddress ( endpointToSimulate . Name ) ;
46- var targetTransportAddress = dispatchEndpoint . ToTransportAddress ( queueAddress ) ;
47- var sourceTransportAddress = startableEndpointProxy . ToTransportAddress ( queueAddress ) ;
48-
49- endpointAddressMappings [ endpointToSimulate . Name ] = endpointToSimulate . QueueAddress ?? targetTransportAddress ;
50- targetEndpointAddressMappings [ targetTransportAddress ] = sourceTransportAddress ;
51- if ( targetTransportAddress != sourceTransportAddress )
52- {
53- // Also add the reverse mapping so that any messages that were in-flight before a bridge configuration change
54- // can still have their address translated correctly. This also allows for the case where duplicate logical endpoints
55- // are running as a competing consumer with the bridge in canary/parallel deployment scenarios.
56- targetEndpointAddressMappings [ sourceTransportAddress ] = targetTransportAddress ;
57- }
58- targetEndpointDispatchers [ endpointToSimulate . Name ] = new TargetEndpointDispatcher ( targetTransport . Name , dispatchEndpoint , targetTransportAddress ) ;
59-
60- proxyRegistrations . Add ( new ProxyRegistration
61- {
62- Endpoint = endpointToSimulate ,
63- TranportName = proxyTransport . Name ,
64- RawEndpoint = startableEndpointProxy
65- } ) ;
66- }
75+ continue ;
6776 }
68- }
6977
70- return proxyRegistrations ;
78+ var startableEndpointProxy = await endpointProxyFactory . CreateProxy ( targetEndpoint , proxyTransport , cancellationToken )
79+ . ConfigureAwait ( false ) ;
80+
81+ logger . LogInformation ( "Proxy for endpoint {endpoint} created on {transport}" , targetTransport . Name , proxyTransport . Name ) ;
82+
83+ proxyRegistrations . Add ( new ProxyRegistration
84+ {
85+ Endpoint = targetEndpoint ,
86+ RawEndpoint = startableEndpointProxy
87+ } ) ;
88+ }
7189 }
7290
7391 public TargetEndpointDispatcher GetTargetEndpointDispatcher ( string sourceEndpointName )
@@ -77,21 +95,12 @@ public TargetEndpointDispatcher GetTargetEndpointDispatcher(string sourceEndpoin
7795 return endpointDispatcher ;
7896 }
7997
80- var nearestMatch = GetClosestMatchForExceptionMessage ( sourceEndpointName , targetEndpointDispatchers . Keys ) ;
98+ var nearestMatch = sourceEndpointName . GetClosestMatch ( targetEndpointDispatchers . Keys ) ;
8199
82100 throw new Exception ( $ "No target endpoint dispatcher could be found for endpoint: { sourceEndpointName } . Ensure names have correct casing as mappings are case-sensitive. Nearest configured match: { nearestMatch } ") ;
83101 }
84102
85- public bool TryTranslateToTargetAddress ( string sourceAddress , out string bestMatch )
86- {
87- if ( targetEndpointAddressMappings . TryGetValue ( sourceAddress , out bestMatch ) )
88- {
89- return true ;
90- }
91-
92- bestMatch = GetClosestMatchForExceptionMessage ( sourceAddress , targetEndpointAddressMappings . Keys ) ;
93- return false ;
94- }
103+ public IAddressMap AddressMap { get ; private set ; }
95104
96105 public string GetEndpointAddress ( string endpointName )
97106 {
@@ -100,30 +109,18 @@ public string GetEndpointAddress(string endpointName)
100109 return address ;
101110 }
102111
103- var nearestMatch = GetClosestMatchForExceptionMessage ( endpointName , endpointAddressMappings . Keys ) ;
112+ var nearestMatch = endpointName . GetClosestMatch ( endpointAddressMappings . Keys ) ?? "(No mappings registered)" ;
104113
105114 throw new Exception ( $ "No address mapping could be found for endpoint: { endpointName } . Ensure names have correct casing as mappings are case-sensitive. Nearest configured match: { nearestMatch } ") ;
106115 }
107116
108- static string GetClosestMatchForExceptionMessage ( string sourceEndpointName , IEnumerable < string > items )
109- {
110- var calculator = new Levenshtein ( sourceEndpointName . ToLower ( ) ) ;
111- var nearestMatch = items
112- . OrderBy ( x => calculator . DistanceFrom ( x . ToLower ( ) ) )
113- . FirstOrDefault ( ) ;
114- return nearestMatch ?? "(No mappings registered)" ;
115- }
116-
117- Dictionary < string , BridgeTransport > transportConfigurationMappings = [ ] ;
118-
117+ readonly Dictionary < string , IStartableRawEndpoint > dispatchers = [ ] ;
119118 readonly Dictionary < string , TargetEndpointDispatcher > targetEndpointDispatchers = [ ] ;
120- readonly Dictionary < string , string > targetEndpointAddressMappings = [ ] ;
121119 readonly Dictionary < string , string > endpointAddressMappings = [ ] ;
122120
123121 public class ProxyRegistration
124122 {
125123 public BridgeEndpoint Endpoint ;
126- public string TranportName ;
127124 public IStartableRawEndpoint RawEndpoint ;
128125 }
129126}
0 commit comments