|
18 | 18 | import static com.rabbitmq.stream.impl.Utils.isSac; |
19 | 19 | import static com.rabbitmq.stream.impl.Utils.namedFunction; |
20 | 20 | import static com.rabbitmq.stream.impl.Utils.namedRunnable; |
21 | | -import static java.lang.String.format; |
22 | 21 |
|
23 | 22 | import com.rabbitmq.stream.BackOffDelayPolicy; |
24 | 23 | import com.rabbitmq.stream.Constants; |
|
43 | 42 | import com.rabbitmq.stream.impl.Utils.ClientConnectionType; |
44 | 43 | import com.rabbitmq.stream.impl.Utils.ClientFactory; |
45 | 44 | import com.rabbitmq.stream.impl.Utils.ClientFactoryContext; |
46 | | -import java.time.Duration; |
47 | 45 | import java.util.ArrayList; |
48 | 46 | import java.util.Collection; |
49 | 47 | import java.util.Collections; |
|
63 | 61 | import java.util.concurrent.atomic.AtomicReference; |
64 | 62 | import java.util.function.Function; |
65 | 63 | import java.util.function.Predicate; |
66 | | -import java.util.function.Supplier; |
67 | 64 | import java.util.stream.Collectors; |
68 | 65 | import java.util.stream.IntStream; |
69 | 66 | import org.slf4j.Logger; |
@@ -171,11 +168,14 @@ private void addToManager( |
171 | 168 | pickedManager = iterator.next(); |
172 | 169 | if (pickedManager.isClosed()) { |
173 | 170 | iterator.remove(); |
174 | | - } |
175 | | - if (node.equals(pickedManager.node) && !pickedManager.isFull()) { |
176 | | - break; |
177 | | - } else { |
178 | 171 | pickedManager = null; |
| 172 | + } else { |
| 173 | + if (node.equals(pickedManager.node) && !pickedManager.isFull()) { |
| 174 | + // let's try this one |
| 175 | + break; |
| 176 | + } else { |
| 177 | + pickedManager = null; |
| 178 | + } |
179 | 179 | } |
180 | 180 | } |
181 | 181 | if (pickedManager == null) { |
@@ -744,7 +744,7 @@ private void assignConsumersToStream( |
744 | 744 | for (SubscriptionTracker affectedSubscription : subscriptions) { |
745 | 745 | if (affectedSubscription.compareAndSet( |
746 | 746 | SubscriptionState.ACTIVE, SubscriptionState.RECOVERING)) { |
747 | | - recoverSubscription(stream, candidates, affectedSubscription); |
| 747 | + recoverSubscription(candidates, affectedSubscription); |
748 | 748 | } else { |
749 | 749 | LOGGER.debug( |
750 | 750 | "Not recovering consumer {} from stream {}, state is {}, expected is {}", |
@@ -774,51 +774,46 @@ private void assignConsumersToStream( |
774 | 774 | }); |
775 | 775 | } |
776 | 776 |
|
777 | | - private void recoverSubscription( |
778 | | - String stream, List<Broker> candidates, SubscriptionTracker affectedSubscription) { |
| 777 | + private void recoverSubscription(List<Broker> candidates, SubscriptionTracker tracker) { |
779 | 778 | boolean reassignmentCompleted = false; |
780 | 779 | while (!reassignmentCompleted) { |
781 | 780 | try { |
782 | | - if (affectedSubscription.consumer.isOpen()) { |
| 781 | + if (tracker.consumer.isOpen()) { |
783 | 782 | Broker broker = pickBroker(candidates); |
784 | | - LOGGER.debug("Using {} to resume consuming from {}", broker, stream); |
785 | | - synchronized (affectedSubscription.consumer) { |
786 | | - if (affectedSubscription.consumer.isOpen()) { |
| 783 | + LOGGER.debug("Using {} to resume consuming from {}", broker, tracker.stream); |
| 784 | + synchronized (tracker.consumer) { |
| 785 | + if (tracker.consumer.isOpen()) { |
787 | 786 | OffsetSpecification offsetSpecification; |
788 | | - if (affectedSubscription.hasReceivedSomething) { |
789 | | - offsetSpecification = OffsetSpecification.offset(affectedSubscription.offset); |
| 787 | + if (tracker.hasReceivedSomething) { |
| 788 | + offsetSpecification = OffsetSpecification.offset(tracker.offset); |
790 | 789 | } else { |
791 | | - offsetSpecification = affectedSubscription.initialOffsetSpecification; |
| 790 | + offsetSpecification = tracker.initialOffsetSpecification; |
792 | 791 | } |
793 | | - addToManager(broker, affectedSubscription, offsetSpecification, false); |
794 | | - reassignmentCompleted = true; |
795 | | - } else { |
796 | | - reassignmentCompleted = true; |
| 792 | + addToManager(broker, tracker, offsetSpecification, false); |
797 | 793 | } |
798 | 794 | } |
799 | 795 | } else { |
800 | 796 | LOGGER.debug("Not re-assigning consumer because it has been closed"); |
801 | | - reassignmentCompleted = true; |
802 | 797 | } |
| 798 | + reassignmentCompleted = true; |
803 | 799 | } catch (ConnectionStreamException |
804 | 800 | | ClientClosedException |
805 | 801 | | StreamNotAvailableException e) { |
806 | 802 | LOGGER.debug( |
807 | 803 | "Consumer {} re-assignment on stream {} timed out or connection closed or stream not available, " |
808 | 804 | + "refreshing candidates and retrying", |
809 | | - affectedSubscription.consumer.id(), |
810 | | - affectedSubscription.stream); |
| 805 | + tracker.consumer.id(), |
| 806 | + tracker.stream); |
811 | 807 | // maybe not a good candidate, let's refresh and retry for this one |
812 | 808 | candidates = |
813 | | - callAndMaybeRetry( |
814 | | - () -> findBrokersForStream(stream), |
| 809 | + Utils.callAndMaybeRetry( |
| 810 | + () -> findBrokersForStream(tracker.stream), |
815 | 811 | ex -> !(ex instanceof StreamDoesNotExistException), |
816 | 812 | environment.recoveryBackOffDelayPolicy(), |
817 | 813 | "Candidate lookup to consume from '%s'", |
818 | | - stream); |
819 | | - |
| 814 | + tracker.stream); |
820 | 815 | } catch (Exception e) { |
821 | | - LOGGER.warn("Error while re-assigning subscription from stream {}", stream, e); |
| 816 | + LOGGER.warn("Error while re-assigning subscription from stream {}", tracker.stream, e); |
822 | 817 | reassignmentCompleted = true; |
823 | 818 | } |
824 | 819 | } |
@@ -873,7 +868,7 @@ synchronized void add( |
873 | 868 | if (offsetTrackingReference != null) { |
874 | 869 | checkNotClosed(); |
875 | 870 | QueryOffsetResponse queryOffsetResponse = |
876 | | - callAndMaybeRetry( |
| 871 | + Utils.callAndMaybeRetry( |
877 | 872 | () -> client.queryOffset(offsetTrackingReference, subscriptionTracker.stream), |
878 | 873 | RETRY_ON_TIMEOUT, |
879 | 874 | "Offset query for consumer %s on stream '%s' (reference %s)", |
@@ -917,7 +912,7 @@ synchronized void add( |
917 | 912 | // FIXME consider using fewer initial credits |
918 | 913 | byte subId = subscriptionId; |
919 | 914 | Client.Response subscribeResponse = |
920 | | - callAndMaybeRetry( |
| 915 | + Utils.callAndMaybeRetry( |
921 | 916 | () -> |
922 | 917 | client.subscribe( |
923 | 918 | subId, |
@@ -968,7 +963,7 @@ synchronized void remove(SubscriptionTracker subscriptionTracker) { |
968 | 963 | byte subscriptionIdInClient = subscriptionTracker.subscriptionIdInClient; |
969 | 964 | try { |
970 | 965 | Client.Response unsubscribeResponse = |
971 | | - callAndMaybeRetry( |
| 966 | + Utils.callAndMaybeRetry( |
972 | 967 | () -> client.unsubscribe(subscriptionIdInClient), |
973 | 968 | RETRY_ON_TIMEOUT, |
974 | 969 | "Unsubscribe request for consumer %d on stream '%s'", |
@@ -1129,54 +1124,6 @@ private static void maybeExchangeCommandVersions(Client client) { |
1129 | 1124 | } |
1130 | 1125 | } |
1131 | 1126 |
|
1132 | | - static <T> T callAndMaybeRetry( |
1133 | | - Supplier<T> operation, Predicate<Exception> retryCondition, String format, Object... args) { |
1134 | | - return callAndMaybeRetry(operation, retryCondition, i -> Duration.ZERO, format, args); |
1135 | | - } |
1136 | | - |
1137 | | - static <T> T callAndMaybeRetry( |
1138 | | - Supplier<T> operation, |
1139 | | - Predicate<Exception> retryCondition, |
1140 | | - BackOffDelayPolicy delayPolicy, |
1141 | | - String format, |
1142 | | - Object... args) { |
1143 | | - String description = format(format, args); |
1144 | | - int attempt = 0; |
1145 | | - Exception lastException = null; |
1146 | | - while (attempt++ < 3) { |
1147 | | - try { |
1148 | | - return operation.get(); |
1149 | | - } catch (Exception e) { |
1150 | | - lastException = e; |
1151 | | - if (retryCondition.test(e)) { |
1152 | | - LOGGER.debug("Operation '{}' failed, retrying...", description); |
1153 | | - Duration delay = delayPolicy.delay(attempt - 1); |
1154 | | - if (!delay.isZero()) { |
1155 | | - try { |
1156 | | - Thread.sleep(delay.toMillis()); |
1157 | | - } catch (InterruptedException ex) { |
1158 | | - Thread.interrupted(); |
1159 | | - lastException = ex; |
1160 | | - break; |
1161 | | - } |
1162 | | - } |
1163 | | - } else { |
1164 | | - break; |
1165 | | - } |
1166 | | - } |
1167 | | - } |
1168 | | - String message = |
1169 | | - format("Could not complete task '%s' after %d attempt(s)", description, --attempt); |
1170 | | - LOGGER.debug(message); |
1171 | | - if (lastException == null) { |
1172 | | - throw new StreamException(message); |
1173 | | - } else if (lastException instanceof RuntimeException) { |
1174 | | - throw (RuntimeException) lastException; |
1175 | | - } else { |
1176 | | - throw new StreamException(message, lastException); |
1177 | | - } |
1178 | | - } |
1179 | | - |
1180 | 1127 | private static final Predicate<Exception> RETRY_ON_TIMEOUT = |
1181 | 1128 | e -> e instanceof TimeoutStreamException; |
1182 | 1129 |
|
|
0 commit comments