|
14 | 14 |
|
15 | 15 | package com.rabbitmq.stream.impl;
|
16 | 16 |
|
17 |
| -import static com.rabbitmq.stream.impl.Utils.convertCodeToException; |
18 |
| -import static com.rabbitmq.stream.impl.Utils.formatConstant; |
19 |
| -import static com.rabbitmq.stream.impl.Utils.isSac; |
20 |
| -import static com.rabbitmq.stream.impl.Utils.jsonField; |
21 |
| -import static com.rabbitmq.stream.impl.Utils.namedFunction; |
22 |
| -import static com.rabbitmq.stream.impl.Utils.namedRunnable; |
23 |
| -import static com.rabbitmq.stream.impl.Utils.quote; |
| 17 | +import static com.rabbitmq.stream.impl.Utils.*; |
24 | 18 | import static java.lang.String.format;
|
25 | 19 |
|
26 | 20 | import com.rabbitmq.stream.*;
|
|
51 | 45 | import java.util.concurrent.atomic.AtomicInteger;
|
52 | 46 | import java.util.concurrent.atomic.AtomicLong;
|
53 | 47 | import java.util.concurrent.atomic.AtomicReference;
|
| 48 | +import java.util.concurrent.locks.Lock; |
| 49 | +import java.util.concurrent.locks.ReentrantLock; |
54 | 50 | import java.util.function.*;
|
55 | 51 | import java.util.stream.Collectors;
|
56 | 52 | import java.util.stream.IntStream;
|
@@ -80,6 +76,7 @@ class ConsumersCoordinator {
|
80 | 76 | new DefaultExecutorServiceFactory(
|
81 | 77 | Runtime.getRuntime().availableProcessors(), 10, "rabbitmq-stream-consumer-connection-");
|
82 | 78 | private final boolean forceReplica;
|
| 79 | + private final Lock coordinatorLock = new ReentrantLock(); |
83 | 80 |
|
84 | 81 | ConsumersCoordinator(
|
85 | 82 | StreamEnvironment environment,
|
@@ -116,47 +113,51 @@ Runnable subscribe(
|
116 | 113 | MessageHandler messageHandler,
|
117 | 114 | Map<String, String> subscriptionProperties,
|
118 | 115 | ConsumerFlowStrategy flowStrategy) {
|
119 |
| - List<Client.Broker> candidates = findBrokersForStream(stream, forceReplica); |
120 |
| - Client.Broker newNode = pickBroker(candidates); |
121 |
| - if (newNode == null) { |
122 |
| - throw new IllegalStateException("No available node to subscribe to"); |
123 |
| - } |
124 |
| - |
125 |
| - // create stream subscription to track final and changing state of this very subscription |
126 |
| - // we keep this instance when we move the subscription from a client to another one |
127 |
| - SubscriptionTracker subscriptionTracker = |
128 |
| - new SubscriptionTracker( |
129 |
| - this.trackerIdSequence.getAndIncrement(), |
130 |
| - consumer, |
131 |
| - stream, |
132 |
| - offsetSpecification, |
133 |
| - trackingReference, |
134 |
| - subscriptionListener, |
135 |
| - trackingClosingCallback, |
136 |
| - messageHandler, |
137 |
| - subscriptionProperties, |
138 |
| - flowStrategy); |
| 116 | + return lock( |
| 117 | + this.coordinatorLock, |
| 118 | + () -> { |
| 119 | + List<Client.Broker> candidates = findBrokersForStream(stream, forceReplica); |
| 120 | + Client.Broker newNode = pickBroker(candidates); |
| 121 | + if (newNode == null) { |
| 122 | + throw new IllegalStateException("No available node to subscribe to"); |
| 123 | + } |
139 | 124 |
|
140 |
| - try { |
141 |
| - addToManager(newNode, subscriptionTracker, offsetSpecification, true); |
142 |
| - } catch (ConnectionStreamException e) { |
143 |
| - // these exceptions are not public |
144 |
| - throw new StreamException(e.getMessage()); |
145 |
| - } |
| 125 | + // create stream subscription to track final and changing state of this very subscription |
| 126 | + // we keep this instance when we move the subscription from a client to another one |
| 127 | + SubscriptionTracker subscriptionTracker = |
| 128 | + new SubscriptionTracker( |
| 129 | + this.trackerIdSequence.getAndIncrement(), |
| 130 | + consumer, |
| 131 | + stream, |
| 132 | + offsetSpecification, |
| 133 | + trackingReference, |
| 134 | + subscriptionListener, |
| 135 | + trackingClosingCallback, |
| 136 | + messageHandler, |
| 137 | + subscriptionProperties, |
| 138 | + flowStrategy); |
| 139 | + |
| 140 | + try { |
| 141 | + addToManager(newNode, subscriptionTracker, offsetSpecification, true); |
| 142 | + } catch (ConnectionStreamException e) { |
| 143 | + // these exceptions are not public |
| 144 | + throw new StreamException(e.getMessage()); |
| 145 | + } |
146 | 146 |
|
147 |
| - if (debug) { |
148 |
| - this.trackers.add(subscriptionTracker); |
149 |
| - return () -> { |
150 |
| - try { |
151 |
| - this.trackers.remove(subscriptionTracker); |
152 |
| - } catch (Exception e) { |
153 |
| - LOGGER.debug("Error while removing subscription tracker from list"); |
154 |
| - } |
155 |
| - subscriptionTracker.cancel(); |
156 |
| - }; |
157 |
| - } else { |
158 |
| - return subscriptionTracker::cancel; |
159 |
| - } |
| 147 | + if (debug) { |
| 148 | + this.trackers.add(subscriptionTracker); |
| 149 | + return () -> { |
| 150 | + try { |
| 151 | + this.trackers.remove(subscriptionTracker); |
| 152 | + } catch (Exception e) { |
| 153 | + LOGGER.debug("Error while removing subscription tracker from list"); |
| 154 | + } |
| 155 | + subscriptionTracker.cancel(); |
| 156 | + }; |
| 157 | + } else { |
| 158 | + return subscriptionTracker::cancel; |
| 159 | + } |
| 160 | + }); |
160 | 161 | }
|
161 | 162 |
|
162 | 163 | private void addToManager(
|
|
0 commit comments