|
30 | 30 | import java.util.concurrent.atomic.AtomicLong;
|
31 | 31 | import java.util.concurrent.atomic.AtomicReference;
|
32 | 32 | import java.util.function.BiConsumer;
|
33 |
| -import java.util.function.Function; |
34 | 33 | import java.util.function.Predicate;
|
35 | 34 | import java.util.function.Supplier;
|
36 |
| -import java.util.stream.Collectors; |
37 | 35 | import org.apache.qpid.protonj2.client.ConnectionOptions;
|
38 | 36 | import org.apache.qpid.protonj2.client.DisconnectionEvent;
|
39 | 37 | import org.apache.qpid.protonj2.client.Session;
|
@@ -123,19 +121,17 @@ final class AmqpConnection extends ResourceBase implements Connection {
|
123 | 121 | : null;
|
124 | 122 | this.management = createManagement();
|
125 | 123 | NativeConnectionWrapper ncw =
|
126 |
| - enforceAffinity( |
| 124 | + ConnectionUtils.enforceAffinity( |
127 | 125 | addrs -> {
|
128 | 126 | NativeConnectionWrapper wrapper =
|
129 | 127 | connect(this.connectionSettings, builder.name(), disconnectHandler, addrs);
|
130 |
| - this.nativeConnection = wrapper.connection; |
| 128 | + this.nativeConnection = wrapper.connection(); |
131 | 129 | return wrapper;
|
132 | 130 | },
|
133 | 131 | this.management,
|
134 | 132 | this.affinity,
|
135 | 133 | this.environment.affinityCache());
|
136 |
| - this.connectionAddress = ncw.address; |
137 |
| - this.connectionNodename = ncw.nodename; |
138 |
| - this.nativeConnection = ncw.connection; |
| 134 | + this.sync(ncw); |
139 | 135 | this.state(OPEN);
|
140 | 136 | this.environment.metricsCollector().openConnection();
|
141 | 137 | }
|
@@ -235,96 +231,10 @@ private NativeConnectionWrapper connect(
|
235 | 231 | }
|
236 | 232 | }
|
237 | 233 |
|
238 |
| - static NativeConnectionWrapper enforceAffinity( |
239 |
| - Function<List<Address>, NativeConnectionWrapper> connectionFactory, |
240 |
| - AmqpManagement management, |
241 |
| - ConnectionUtils.ConnectionAffinity affinity, |
242 |
| - ConnectionUtils.AffinityCache affinityCache) { |
243 |
| - // TODO add retry for sensitive operations in affinity mechanism |
244 |
| - if (affinity == null) { |
245 |
| - return connectionFactory.apply(null); |
246 |
| - } |
247 |
| - try { |
248 |
| - NativeConnectionWrapper pickedConnection = null; |
249 |
| - int attemptCount = 0; |
250 |
| - boolean queueInfoRefreshed = false; |
251 |
| - List<String> nodesWithAffinity = null; |
252 |
| - Management.QueueInfo info = affinityCache.queueInfo(affinity.queue()); |
253 |
| - while (pickedConnection == null) { |
254 |
| - attemptCount++; |
255 |
| - NativeConnectionWrapper connectionWrapper = null; |
256 |
| - if (info == null) { |
257 |
| - connectionWrapper = connectionFactory.apply(null); |
258 |
| - management.init(); |
259 |
| - info = management.queueInfo(affinity.queue()); |
260 |
| - affinityCache.queueInfo(info); |
261 |
| - queueInfoRefreshed = true; |
262 |
| - } |
263 |
| - LOGGER.debug( |
264 |
| - "Looking affinity with queue '{}' (type = {}, leader = {}, replicas = {})", |
265 |
| - info.name(), |
266 |
| - info.type(), |
267 |
| - info.leader(), |
268 |
| - info.replicas()); |
269 |
| - if (nodesWithAffinity == null) { |
270 |
| - nodesWithAffinity = ConnectionUtils.findAffinity(affinity, info); |
271 |
| - LOGGER.debug("Nodes matching affinity {}: {}", affinity, nodesWithAffinity); |
272 |
| - } |
273 |
| - if (connectionWrapper == null) { |
274 |
| - List<Address> addressHints = |
275 |
| - nodesWithAffinity.stream() |
276 |
| - .map(affinityCache::nodenameToAddress) |
277 |
| - .filter(Objects::nonNull) |
278 |
| - .collect(Collectors.toList()); |
279 |
| - connectionWrapper = connectionFactory.apply(addressHints); |
280 |
| - } |
281 |
| - LOGGER.debug("Currently connected to node {}", connectionWrapper.nodename); |
282 |
| - affinityCache.nodenameToAddress(connectionWrapper.nodename, connectionWrapper.address); |
283 |
| - if (nodesWithAffinity.contains(connectionWrapper.nodename)) { |
284 |
| - LOGGER.debug("Affinity {} found with node {}", affinity, connectionWrapper.nodename); |
285 |
| - if (!queueInfoRefreshed) { |
286 |
| - LOGGER.debug("Refreshing queue information."); |
287 |
| - management.init(); |
288 |
| - info = management.queueInfo(affinity.queue()); |
289 |
| - affinityCache.queueInfo(info); |
290 |
| - nodesWithAffinity = ConnectionUtils.findAffinity(affinity, info); |
291 |
| - LOGGER.debug("Nodes matching affinity {}: {}", affinity, nodesWithAffinity); |
292 |
| - queueInfoRefreshed = true; |
293 |
| - if (nodesWithAffinity.contains(connectionWrapper.nodename)) { |
294 |
| - pickedConnection = connectionWrapper; |
295 |
| - } else { |
296 |
| - management.releaseResources(); |
297 |
| - connectionWrapper.connection.close(); |
298 |
| - } |
299 |
| - } else { |
300 |
| - pickedConnection = connectionWrapper; |
301 |
| - } |
302 |
| - } else if (attemptCount == 5) { |
303 |
| - LOGGER.debug( |
304 |
| - "Could not find affinity {} after {} attempt(s), using last connection.", |
305 |
| - affinity, |
306 |
| - attemptCount); |
307 |
| - pickedConnection = connectionWrapper; |
308 |
| - } else { |
309 |
| - LOGGER.debug("Affinity {} not found with node {}.", affinity, connectionWrapper.nodename); |
310 |
| - if (!queueInfoRefreshed) { |
311 |
| - LOGGER.debug("Refreshing queue information."); |
312 |
| - management.init(); |
313 |
| - info = management.queueInfo(affinity.queue()); |
314 |
| - affinityCache.queueInfo(info); |
315 |
| - nodesWithAffinity = ConnectionUtils.findAffinity(affinity, info); |
316 |
| - LOGGER.debug("Nodes matching affinity {}: {}", affinity, nodesWithAffinity); |
317 |
| - queueInfoRefreshed = true; |
318 |
| - } |
319 |
| - management.releaseResources(); |
320 |
| - connectionWrapper.connection.close(); |
321 |
| - } |
322 |
| - } |
323 |
| - return pickedConnection; |
324 |
| - } catch (RuntimeException e) { |
325 |
| - LOGGER.warn("Cannot enforce affinity {} of error when looking up queue", affinity, e); |
326 |
| - throw e; |
327 |
| - } |
| 234 | + private void sync(NativeConnectionWrapper wrapper) { |
| 235 | + this.connectionAddress = wrapper.address(); |
| 236 | + this.connectionNodename = wrapper.nodename(); |
| 237 | + this.nativeConnection = wrapper.connection(); |
328 | 238 | }
|
329 | 239 |
|
330 | 240 | private static void checkBrokerVersion(org.apache.qpid.protonj2.client.Connection connection)
|
@@ -419,9 +329,7 @@ private void recoverAfterConnectionFailure(
|
419 | 329 | NativeConnectionWrapper ncw =
|
420 | 330 | recoverNativeConnection(
|
421 | 331 | recoveryConfiguration, connectionName, disconnectedHandlerReference);
|
422 |
| - this.connectionAddress = ncw.address; |
423 |
| - this.connectionNodename = ncw.nodename; |
424 |
| - this.nativeConnection = ncw.connection; |
| 332 | + this.sync(ncw); |
425 | 333 | LOGGER.debug("Reconnected to {}", this.currentConnectionLabel());
|
426 | 334 | } catch (Exception ex) {
|
427 | 335 | if (ex instanceof InterruptedException) {
|
@@ -476,15 +384,15 @@ private NativeConnectionWrapper recoverNativeConnection(
|
476 | 384 |
|
477 | 385 | try {
|
478 | 386 | NativeConnectionWrapper result =
|
479 |
| - enforceAffinity( |
| 387 | + ConnectionUtils.enforceAffinity( |
480 | 388 | addrs -> {
|
481 | 389 | NativeConnectionWrapper wrapper =
|
482 | 390 | connect(
|
483 | 391 | this.connectionSettings,
|
484 | 392 | connectionName,
|
485 | 393 | disconnectedHandlerReference.get(),
|
486 | 394 | addrs);
|
487 |
| - this.nativeConnection = wrapper.connection; |
| 395 | + this.nativeConnection = wrapper.connection(); |
488 | 396 | return wrapper;
|
489 | 397 | },
|
490 | 398 | this.management,
|
@@ -772,9 +680,13 @@ String nodename() {
|
772 | 680 | return this.nodename;
|
773 | 681 | }
|
774 | 682 |
|
775 |
| - public Address address() { |
| 683 | + Address address() { |
776 | 684 | return this.address;
|
777 | 685 | }
|
| 686 | + |
| 687 | + org.apache.qpid.protonj2.client.Connection connection() { |
| 688 | + return this.connection; |
| 689 | + } |
778 | 690 | }
|
779 | 691 |
|
780 | 692 | @Override
|
|
0 commit comments