|
90 | 90 | import java.util.concurrent.CountDownLatch;
|
91 | 91 | import java.util.concurrent.TimeUnit;
|
92 | 92 | import java.util.concurrent.atomic.AtomicBoolean;
|
| 93 | +import java.util.concurrent.atomic.AtomicInteger; |
93 | 94 | import java.util.concurrent.atomic.AtomicReference;
|
94 | 95 | import java.util.logging.Logger;
|
95 | 96 | import java.util.stream.Collectors;
|
@@ -941,6 +942,117 @@ public void shouldReturnNodesThatWereDownToPoolOfNodesOnceTheyMarkTheirHealthChe
|
941 | 942 | assertThatEither(result).isRight();
|
942 | 943 | }
|
943 | 944 |
|
| 945 | + @Test |
| 946 | + public void shouldRemoveNodeWhoseHealthCheckFailsConsistently() { |
| 947 | + CombinedHandler handler = new CombinedHandler(); |
| 948 | + |
| 949 | + AtomicReference<Availability> availability = new AtomicReference<>(UP); |
| 950 | + |
| 951 | + SessionMap sessions = new LocalSessionMap(tracer, bus); |
| 952 | + handler.addHandler(sessions); |
| 953 | + NewSessionQueue queue = new LocalNewSessionQueue( |
| 954 | + tracer, |
| 955 | + bus, |
| 956 | + new DefaultSlotMatcher(), |
| 957 | + Duration.ofSeconds(2), |
| 958 | + Duration.ofSeconds(2), |
| 959 | + registrationSecret); |
| 960 | + |
| 961 | + URI uri = createUri(); |
| 962 | + Node node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret) |
| 963 | + .add( |
| 964 | + caps, |
| 965 | + new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now()))) |
| 966 | + .advanced() |
| 967 | + .healthCheck(() -> new HealthCheck.Result(availability.get(), "TL;DR")) |
| 968 | + .build(); |
| 969 | + handler.addHandler(node); |
| 970 | + |
| 971 | + LocalDistributor distributor = new LocalDistributor( |
| 972 | + tracer, |
| 973 | + bus, |
| 974 | + new PassthroughHttpClient.Factory(handler), |
| 975 | + sessions, |
| 976 | + queue, |
| 977 | + new DefaultSlotSelector(), |
| 978 | + registrationSecret, |
| 979 | + Duration.ofSeconds(1), |
| 980 | + false); |
| 981 | + handler.addHandler(distributor); |
| 982 | + distributor.add(node); |
| 983 | + |
| 984 | + waitToHaveCapacity(distributor); |
| 985 | + |
| 986 | + Either<SessionNotCreatedException, CreateSessionResponse> result = |
| 987 | + distributor.newSession(createRequest(caps)); |
| 988 | + assertThatEither(result).isRight(); |
| 989 | + |
| 990 | + availability.set(DOWN); |
| 991 | + |
| 992 | + waitTillNodesAreRemoved(distributor); |
| 993 | + |
| 994 | + result = |
| 995 | + distributor.newSession(createRequest(caps)); |
| 996 | + assertThatEither(result).isLeft(); |
| 997 | + } |
| 998 | + |
| 999 | + @Test |
| 1000 | + public void shouldNotRemoveNodeWhoseHealthCheckPassesBeforeThreshold() |
| 1001 | + throws InterruptedException { |
| 1002 | + CombinedHandler handler = new CombinedHandler(); |
| 1003 | + |
| 1004 | + AtomicInteger count = new AtomicInteger(0); |
| 1005 | + CountDownLatch latch = new CountDownLatch(1); |
| 1006 | + |
| 1007 | + SessionMap sessions = new LocalSessionMap(tracer, bus); |
| 1008 | + handler.addHandler(sessions); |
| 1009 | + NewSessionQueue queue = new LocalNewSessionQueue( |
| 1010 | + tracer, |
| 1011 | + bus, |
| 1012 | + new DefaultSlotMatcher(), |
| 1013 | + Duration.ofSeconds(2), |
| 1014 | + Duration.ofSeconds(2), |
| 1015 | + registrationSecret); |
| 1016 | + |
| 1017 | + URI uri = createUri(); |
| 1018 | + Node node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret) |
| 1019 | + .add( |
| 1020 | + caps, |
| 1021 | + new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now()))) |
| 1022 | + .advanced() |
| 1023 | + .healthCheck(() -> { |
| 1024 | + if (count.get() <= 4) { |
| 1025 | + count.incrementAndGet(); |
| 1026 | + return new HealthCheck.Result(DOWN, "Down"); |
| 1027 | + } |
| 1028 | + latch.countDown(); |
| 1029 | + return new HealthCheck.Result(UP, "Up"); |
| 1030 | + }) |
| 1031 | + .build(); |
| 1032 | + handler.addHandler(node); |
| 1033 | + |
| 1034 | + LocalDistributor distributor = new LocalDistributor( |
| 1035 | + tracer, |
| 1036 | + bus, |
| 1037 | + new PassthroughHttpClient.Factory(handler), |
| 1038 | + sessions, |
| 1039 | + queue, |
| 1040 | + new DefaultSlotSelector(), |
| 1041 | + registrationSecret, |
| 1042 | + Duration.ofSeconds(1), |
| 1043 | + false); |
| 1044 | + handler.addHandler(distributor); |
| 1045 | + distributor.add(node); |
| 1046 | + |
| 1047 | + latch.await(60, TimeUnit.SECONDS); |
| 1048 | + |
| 1049 | + waitToHaveCapacity(distributor); |
| 1050 | + |
| 1051 | + Either<SessionNotCreatedException, CreateSessionResponse> result = |
| 1052 | + distributor.newSession(createRequest(caps)); |
| 1053 | + assertThatEither(result).isRight(); |
| 1054 | + } |
| 1055 | + |
944 | 1056 | private Set<Node> createNodeSet(CombinedHandler handler, Distributor distributor, int count, Capabilities...capabilities) {
|
945 | 1057 | Set<Node> nodeSet = new HashSet<>();
|
946 | 1058 | for (int i=0; i<count; i++) {
|
@@ -1253,7 +1365,7 @@ private void waitToHaveCapacity(Distributor distributor) {
|
1253 | 1365 |
|
1254 | 1366 | private void waitTillNodesAreRemoved(Distributor distributor) {
|
1255 | 1367 | new FluentWait<>(distributor)
|
1256 |
| - .withTimeout(Duration.ofSeconds(5)) |
| 1368 | + .withTimeout(Duration.ofSeconds(60)) |
1257 | 1369 | .pollingEvery(Duration.ofMillis(100))
|
1258 | 1370 | .until(d -> {
|
1259 | 1371 | Set<NodeStatus> nodes = d.getStatus().getNodes();
|
|
0 commit comments