diff --git a/README.md b/README.md index 51e6599..456e809 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,5 @@ The watcher can be configured using consul: watch: disabled: false # to disable the watcher, during test for instance + block-timeout: 10m # Sets the read timeout. Default value (10 minutes). ``` diff --git a/build.gradle.kts b/build.gradle.kts index 086e102..87a4ec1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(mn.micronaut.serde.jackson) implementation(mn.micronaut.discovery.client) implementation(mn.micronaut.reactor) + implementation(mn.micronaut.retry) implementation(mn.guava) // ----------- TESTS ----------- diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchConfiguration.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchConfiguration.java new file mode 100644 index 0000000..e1c667b --- /dev/null +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchConfiguration.java @@ -0,0 +1,68 @@ +package com.frogdevelopment.micronaut.consul.watch; + +import java.time.Duration; +import java.util.Optional; + +import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.discovery.consul.ConsulConfiguration; +import io.micronaut.discovery.consul.condition.RequiresConsul; +import io.micronaut.http.client.HttpClientConfiguration; + +@RequiresConsul +@ConfigurationProperties(WatchConfiguration.PREFIX) +public class WatchConfiguration extends HttpClientConfiguration { + + public static final String EXPR_CONSUL_WATCH_RETRY_COUNT = "${" + WatchConfiguration.PREFIX + ".retry-count:3}"; + public static final String EXPR_CONSUL_WATCH_RETRY_DELAY = "${" + WatchConfiguration.PREFIX + ".retry-delay:1s}"; + + /** + * The default block timeout in minutes. + */ + public static final long DEFAULT_BLOCK_TIMEOUT_MINUTES = 10; + + public static final long DEFAULT_WATCH_DELAY_MILLISECONDS = 500; + + /** + * The prefix to use for all Consul settings. + */ + public static final String PREFIX = "consul.watch"; + + private Duration readTimeout = Duration.ofMinutes(DEFAULT_BLOCK_TIMEOUT_MINUTES); + private Duration watchDelay = Duration.ofSeconds(DEFAULT_WATCH_DELAY_MILLISECONDS); + + private final ConsulConfiguration consulConfiguration; + + public WatchConfiguration(final ConsulConfiguration consulConfiguration) { + super(consulConfiguration); + this.consulConfiguration = consulConfiguration; + } + + @Override + public ConnectionPoolConfiguration getConnectionPoolConfiguration() { + return consulConfiguration.getConnectionPoolConfiguration(); + } + + @Override + public Optional getReadTimeout() { + return Optional.ofNullable(readTimeout); + } + + @Override + public void setReadTimeout(@Nullable Duration readTimeout) { + this.readTimeout = readTimeout; + } + + public Duration getWatchDelay() { + return watchDelay; + } + + /** + * Sets the watch delay before each call to avoid flooding. Default value ({@value #DEFAULT_WATCH_DELAY_MILLISECONDS} milliseconds). + * + * @param watchDelay The read timeout + */ + public void setWatchDelay(Duration watchDelay) { + this.watchDelay = watchDelay; + } +} diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactory.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchFactory.java similarity index 88% rename from src/main/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactory.java rename to src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchFactory.java index e7958f3..1108c55 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactory.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/WatchFactory.java @@ -7,9 +7,8 @@ import java.util.ArrayList; import java.util.List; -import jakarta.inject.Named; -import com.frogdevelopment.micronaut.consul.watch.client.IndexConsulClient; +import com.frogdevelopment.micronaut.consul.watch.client.WatchConsulClient; import com.frogdevelopment.micronaut.consul.watch.context.PropertiesChangeHandler; import com.frogdevelopment.micronaut.consul.watch.watcher.ConfigurationsWatcher; import com.frogdevelopment.micronaut.consul.watch.watcher.NativeWatcher; @@ -25,8 +24,6 @@ import io.micronaut.context.exceptions.ConfigurationException; import io.micronaut.discovery.consul.ConsulConfiguration; import io.micronaut.jackson.core.env.JsonPropertySourceLoader; -import io.micronaut.scheduling.TaskExecutors; -import io.micronaut.scheduling.TaskScheduler; /** * Create all needed {@link Watcher} based on configuration. @@ -36,14 +33,13 @@ */ @Factory @RequiredArgsConstructor -public class WatcherFactory { +public class WatchFactory { private static final String CONSUL_PATH_SEPARATOR = "/"; private final Environment environment; - @Named(TaskExecutors.SCHEDULED) - private final TaskScheduler taskScheduler; - private final IndexConsulClient consulClient; + private final WatchConsulClient consulClient; + private final WatchConfiguration watchConfiguration; private final PropertiesChangeHandler propertiesChangeHandler; @Context @@ -106,11 +102,11 @@ private static String toProfiledPath(final String resource, final String activeN private Watcher watchNative(final List keyPaths) { // adding '/' at the end of the kvPath to distinct 'kvPath/' from 'kvPath,profile/' final var kvPaths = keyPaths.stream().map(path -> path + CONSUL_PATH_SEPARATOR).toList(); - return new NativeWatcher(kvPaths, taskScheduler, consulClient, propertiesChangeHandler); + return new NativeWatcher(kvPaths, consulClient, watchConfiguration, propertiesChangeHandler); } private Watcher watchConfigurations(final List kvPaths, final PropertySourceLoader propertySourceLoader) { - return new ConfigurationsWatcher(kvPaths, taskScheduler, consulClient, propertiesChangeHandler, propertySourceLoader); + return new ConfigurationsWatcher(kvPaths, consulClient, watchConfiguration, propertiesChangeHandler, propertySourceLoader); } } diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/IndexConsulClient.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/IndexConsulClient.java deleted file mode 100644 index 7a60b99..0000000 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/IndexConsulClient.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.frogdevelopment.micronaut.consul.watch.client; - -import java.io.Closeable; -import java.util.List; - -import org.reactivestreams.Publisher; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.core.annotation.Nullable; -import io.micronaut.discovery.consul.ConsulConfiguration; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.QueryValue; -import io.micronaut.http.client.annotation.Client; - -@Client(id = io.micronaut.discovery.consul.client.v1.ConsulClient.SERVICE_ID, path = "/v1", - configuration = ConsulConfiguration.class) -@Requires(beans = ConsulConfiguration.class) -public interface IndexConsulClient extends Closeable, AutoCloseable { - - default Publisher> readValues(String key) { - return readValues(key, true); - } - - default Publisher> readValues(String key, boolean recurse) { - return readValues(key, recurse, null); - } - - @Get(uri = "/kv/{+key}?{&recurse}{&index}", single = true) - Publisher> readValues(String key, @QueryValue boolean recurse, @Nullable @QueryValue Integer index); - -} diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/WatchConsulClient.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/WatchConsulClient.java new file mode 100644 index 0000000..7cf5d5c --- /dev/null +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/client/WatchConsulClient.java @@ -0,0 +1,27 @@ +package com.frogdevelopment.micronaut.consul.watch.client; + +import java.util.List; + +import com.frogdevelopment.micronaut.consul.watch.WatchConfiguration; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.discovery.consul.client.v1.ConsulClient; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.QueryValue; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.retry.annotation.Retryable; +import reactor.core.publisher.Mono; + +@Requires(beans = WatchConfiguration.class) +@Client(id = ConsulClient.SERVICE_ID, path = "/v1", configuration = WatchConfiguration.class) +public interface WatchConsulClient { + + @Get(uri = "/kv/{+key}?{&recurse}{&index}", single = true) + @Retryable( + attempts = WatchConfiguration.EXPR_CONSUL_WATCH_RETRY_COUNT, + delay = WatchConfiguration.EXPR_CONSUL_WATCH_RETRY_DELAY + ) + Mono> watchValues(String key, @Nullable @QueryValue Boolean recurse, @Nullable @QueryValue Integer index); + +} diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/package-info.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/package-info.java index 572f65d..d58a70f 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/package-info.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/package-info.java @@ -1,6 +1,6 @@ @Configuration @RequiresConsul -@Requires(property = "consul.watch.disabled", notEquals = "true", defaultValue = "false") +@Requires(property = WatchConfiguration.PREFIX + "disabled", notEquals = "true", defaultValue = "false") package com.frogdevelopment.micronaut.consul.watch; import io.micronaut.context.annotation.Configuration; diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/AbstractWatcher.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/AbstractWatcher.java index 8c83bf8..4fb5b7b 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/AbstractWatcher.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/AbstractWatcher.java @@ -3,21 +3,19 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import java.time.Duration; import java.util.Base64; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import com.frogdevelopment.micronaut.consul.watch.client.IndexConsulClient; +import com.frogdevelopment.micronaut.consul.watch.WatchConfiguration; import com.frogdevelopment.micronaut.consul.watch.client.KeyValue; +import com.frogdevelopment.micronaut.consul.watch.client.WatchConsulClient; import com.frogdevelopment.micronaut.consul.watch.context.PropertiesChangeHandler; import io.micronaut.http.HttpStatus; import io.micronaut.http.client.exceptions.HttpClientResponseException; import io.micronaut.http.client.exceptions.ReadTimeoutException; -import io.micronaut.http.client.exceptions.ResponseClosedException; -import io.micronaut.scheduling.TaskScheduler; import reactor.core.Disposable; import reactor.core.publisher.Mono; @@ -30,11 +28,10 @@ abstract sealed class AbstractWatcher implements Watcher permits ConfigurationsWatcher, NativeWatcher { protected static final Integer NO_INDEX = null; - private static final int WATCH_DELAY = 1000; private final List kvPaths; - private final TaskScheduler taskScheduler; - protected final IndexConsulClient consulClient; + protected final WatchConsulClient consulClient; + private final WatchConfiguration watchConfiguration; private final PropertiesChangeHandler propertiesChangeHandler; protected final Map kvHolder = new ConcurrentHashMap<>(); @@ -52,7 +49,8 @@ public void start() { try { log.debug("Starting KVs watcher"); watching = true; - kvPaths.forEach(kvPath -> watchKvPath(kvPath, 0)); + kvPaths.parallelStream() + .forEach(kvPath -> watchKvPath(kvPath, 0)); } catch (final Exception e) { log.error("Error watching configurations", e); stop(); @@ -81,16 +79,16 @@ public void stop() { } private void watchKvPath(final String kvPath, final int nbFailures) { - taskScheduler.schedule(Duration.ofMillis(WATCH_DELAY), () -> { if (!watching) { log.warn("Watcher is not started"); return; } - final var disposable = watchValue(kvPath) + // delaying to avoid flood caused by multiple consecutive calls + final var disposable = Mono.delay(watchConfiguration.getWatchDelay()) + .then(watchValue(kvPath)) .subscribe(next -> onNext(kvPath, next), throwable -> onError(kvPath, throwable, nbFailures)); listeners.put(kvPath, disposable); - }); } protected abstract Mono watchValue(String kvPath); @@ -118,9 +116,9 @@ private void onNext(String kvPath, final V next) { private void onError(String kvPath, Throwable throwable, int nbFailures) { if (throwable instanceof final HttpClientResponseException e && e.getStatus() == HttpStatus.NOT_FOUND) { - log.debug("No KV found with kvPath={}", kvPath); + log.trace("No KV found with kvPath={}", kvPath); listeners.remove(kvPath); - } else if (throwable instanceof ReadTimeoutException || throwable instanceof ResponseClosedException) { + } else if (throwable instanceof ReadTimeoutException) { log.debug("Exception [{}] for kvPath={}", throwable, kvPath); watchKvPath(kvPath, 0); } else { diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/ConfigurationsWatcher.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/ConfigurationsWatcher.java index 2dd58f5..58beeec 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/ConfigurationsWatcher.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/ConfigurationsWatcher.java @@ -9,13 +9,13 @@ import java.util.Map; import java.util.Optional; -import com.frogdevelopment.micronaut.consul.watch.client.IndexConsulClient; +import com.frogdevelopment.micronaut.consul.watch.WatchConfiguration; import com.frogdevelopment.micronaut.consul.watch.client.KeyValue; +import com.frogdevelopment.micronaut.consul.watch.client.WatchConsulClient; import com.frogdevelopment.micronaut.consul.watch.context.PropertiesChangeHandler; import io.micronaut.context.env.PropertySourceReader; import io.micronaut.core.util.StringUtils; -import io.micronaut.scheduling.TaskScheduler; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -34,11 +34,11 @@ public final class ConfigurationsWatcher extends AbstractWatcher { * Default constructor */ public ConfigurationsWatcher(final List kvPaths, - final TaskScheduler taskScheduler, - final IndexConsulClient consulClient, + final WatchConsulClient consulClient, + final WatchConfiguration watchConfiguration, final PropertiesChangeHandler propertiesChangeHandler, final PropertySourceReader propertySourceReader) { - super(kvPaths, taskScheduler, consulClient, propertiesChangeHandler); + super(kvPaths, consulClient, watchConfiguration, propertiesChangeHandler); this.propertySourceReader = propertySourceReader; } @@ -48,7 +48,7 @@ protected Mono watchValue(String kvPath) { .map(KeyValue::getModifyIndex) .orElse(NO_INDEX); log.debug("Watching kvPath={} with index={}", kvPath, modifiedIndex); - return Mono.from(consulClient.readValues(kvPath, false, modifiedIndex)) + return consulClient.watchValues(kvPath, false, modifiedIndex) .flatMapMany(Flux::fromIterable) .filter(kv -> kvPath.equals(kv.getKey())) .singleOrEmpty(); diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/NativeWatcher.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/NativeWatcher.java index 2303727..f989a42 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/NativeWatcher.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/NativeWatcher.java @@ -12,12 +12,12 @@ import java.util.Optional; import java.util.stream.Collectors; -import com.frogdevelopment.micronaut.consul.watch.client.IndexConsulClient; +import com.frogdevelopment.micronaut.consul.watch.WatchConfiguration; import com.frogdevelopment.micronaut.consul.watch.client.KeyValue; +import com.frogdevelopment.micronaut.consul.watch.client.WatchConsulClient; import com.frogdevelopment.micronaut.consul.watch.context.PropertiesChangeHandler; import io.micronaut.core.util.StringUtils; -import io.micronaut.scheduling.TaskScheduler; import reactor.core.publisher.Mono; /** @@ -35,10 +35,10 @@ public final class NativeWatcher extends AbstractWatcher> { * Default constructor */ public NativeWatcher(final List kvPaths, - final TaskScheduler taskScheduler, - final IndexConsulClient consulClient, + final WatchConsulClient consulClient, + final WatchConfiguration watchConfiguration, final PropertiesChangeHandler propertiesChangeHandler) { - super(kvPaths, taskScheduler, consulClient, propertiesChangeHandler); + super(kvPaths, consulClient, watchConfiguration, propertiesChangeHandler); } @Override @@ -50,7 +50,7 @@ protected Mono> watchValue(String kvPath) { .max(Integer::compareTo) .orElse(NO_INDEX); log.debug("Watching kvPath={} with index={}", kvPath, modifiedIndex); - return Mono.from(consulClient.readValues(kvPath, true, modifiedIndex)); + return consulClient.watchValues(kvPath, true, modifiedIndex); } @Override diff --git a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatchResult.java b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatchResult.java index 4155787..d350f66 100644 --- a/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatchResult.java +++ b/src/main/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatchResult.java @@ -2,6 +2,13 @@ import java.util.Map; +/** + * @param kvPath Path of the KV + * @param previous Previous value of the KV + * @param next New value of the KV + * @author LE GALL BenoƮt + * @since 1.0.0 + */ public record WatchResult( String kvPath, Map previous, diff --git a/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactoryTest.java b/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchFactoryTest.java similarity index 93% rename from src/test/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactoryTest.java rename to src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchFactoryTest.java index 4f4f5ab..6a895c1 100644 --- a/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatcherFactoryTest.java +++ b/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchFactoryTest.java @@ -29,10 +29,10 @@ import static org.mockito.BDDMockito.given; @ExtendWith(MockitoExtension.class) -class WatcherFactoryTest { +class WatchFactoryTest { @InjectMocks - private WatcherFactory watcherFactory; + private WatchFactory watchFactory; @Mock private Environment environment; @@ -52,7 +52,7 @@ void should_create_required_watchers() { given(environment.getActiveNames()).willReturn(Set.of("cloud", "test")); // when - final var watcher = watcherFactory.createWatcher(consulConfiguration); + final var watcher = watchFactory.createWatcher(consulConfiguration); // then assertThat(watcher) @@ -79,7 +79,7 @@ void should_throwException_when_formatNotSupported(final Format format) { given(consulConfiguration.getConfiguration().getFormat()).willReturn(format); // when - final var caught = catchThrowableOfType(ConfigurationException.class, () -> watcherFactory.createWatcher(consulConfiguration)); + final var caught = catchThrowableOfType(ConfigurationException.class, () -> watchFactory.createWatcher(consulConfiguration)); // then assertThat(caught).isNotNull(); @@ -93,7 +93,7 @@ void should_watch_native() { given(consulConfiguration.getConfiguration().getFormat()).willReturn(NATIVE); // when - final var watcher = watcherFactory.createWatcher(consulConfiguration); + final var watcher = watchFactory.createWatcher(consulConfiguration); // then assertThat(watcher).isInstanceOf(NativeWatcher.class); @@ -117,7 +117,7 @@ void should_watch_configurations(final Format format) { given(consulConfiguration.getConfiguration().getFormat()).willReturn(format); // when - final var watcher = watcherFactory.createWatcher(consulConfiguration); + final var watcher = watchFactory.createWatcher(consulConfiguration); // then assertThat(watcher).isInstanceOf(ConfigurationsWatcher.class); diff --git a/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchTriggerTest.java b/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchTriggerTest.java deleted file mode 100644 index 8e54d62..0000000 --- a/src/test/java/com/frogdevelopment/micronaut/consul/watch/WatchTriggerTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.frogdevelopment.micronaut.consul.watch; - -import java.util.concurrent.ScheduledFuture; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.frogdevelopment.micronaut.consul.watch.watcher.Watcher; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.read.ListAppender; -import io.micronaut.scheduling.TaskScheduler; - -@ExtendWith(MockitoExtension.class) -class WatchTriggerTest { - - @Mock - private TaskScheduler taskScheduler; - @Mock - private Watcher watcher; - - @Mock - private ScheduledFuture scheduledFuture; - - @Captor - private ArgumentCaptor runnableCaptor; - - private ListAppender listAppender; - -// @BeforeEach() -// void beforeEach() { -// listAppender = new ListAppender<>(); -// listAppender.start(); -// watcherLogger.addAppender(listAppender); -// } -// -// @AfterEach -// void afterEach() { -// listAppender.stop(); -// watcherLogger.detachAppender(listAppender); -// listAppender = null; -// } - -// @Test -// void should_throwAnException_when_alreadyStarted() { -// // given -// given(taskScheduler.scheduleWithFixedDelay(any(), any(), any())).willAnswer(invocation -> scheduledFuture); -// -// // when -// watchTrigger.start(null); -// final var caught = Assertions.catchThrowable(() -> watchTrigger.start(null)); -// -// // then -// assertThat(caught) -// .isInstanceOf(IllegalStateException.class) -// .hasMessage("Watcher scheduler already started"); -// } -// -// @Test -// void should_start_all_watchers() { -// // given -// given(taskScheduler.scheduleWithFixedDelay(any(), any(), runnableCaptor.capture())).willAnswer(invocation -> scheduledFuture); -// watchTrigger.start(null); -// final var runnable = runnableCaptor.getValue(); -// -// // when -// runnable.run(); -// -// // then -// then(watcher).should().start(); -// } -// -// @Test -// void should_stopScheduler() { -// // given -// given(taskScheduler.scheduleWithFixedDelay(any(), any(), runnableCaptor.capture())).willAnswer(invocation -> scheduledFuture); -// watchTrigger.start(null); -// given(scheduledFuture.cancel(true)).willReturn(true); -// -// // when -// watchTrigger.stop(null); -// -// // then -// then(taskScheduler).shouldHaveNoMoreInteractions(); -// } -// -// @Test -// void should_logWarning_when_stoppingAnUnstartedWatcher() { -// // when -// watchTrigger.stop(null); -// -// // then -// then(taskScheduler).shouldHaveNoMoreInteractions(); -// then(scheduledFuture).shouldHaveNoInteractions(); -// } -// -// @Test -// void should_logWarning_when_alreadyStopped() { -// // given -// given(taskScheduler.scheduleWithFixedDelay(any(), any(), runnableCaptor.capture())).willAnswer(invocation -> scheduledFuture); -// watchTrigger.start(null); -// given(scheduledFuture.cancel(true)).willReturn(true); -// watchTrigger.stop(null); -// -// // when -// watchTrigger.stop(null); -// -// // then -// then(taskScheduler).shouldHaveNoMoreInteractions(); -// -// assertThat(listAppender.list) -// .filteredOn(iLoggingEvent -> Level.WARN.equals(iLoggingEvent.getLevel())) -// .hasSize(1) -// .first() -// .extracting(ILoggingEvent::getFormattedMessage) -// .isEqualTo("Watcher scheduler is already stopped"); -// } -// -// @Test -// void should_logWarning_when_schedulerCanNotBeStopped() { -// // given -// given(taskScheduler.scheduleWithFixedDelay(any(), any(), runnableCaptor.capture())).willAnswer(invocation -> scheduledFuture); -// watchTrigger.start(null); -// given(scheduledFuture.cancel(true)).willReturn(false); -// -// // when -// watchTrigger.stop(null); -// -// // then -// then(taskScheduler).shouldHaveNoMoreInteractions(); -// -// assertThat(listAppender.list) -// .filteredOn(iLoggingEvent -> Level.WARN.equals(iLoggingEvent.getLevel())) -// .hasSize(1) -// .first() -// .extracting(ILoggingEvent::getFormattedMessage) -// .isEqualTo("Watcher scheduler could not be stopped"); -// } -} diff --git a/src/test/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatcherTest.java b/src/test/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatcherTest.java index d991af0..ba32f1a 100644 --- a/src/test/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatcherTest.java +++ b/src/test/java/com/frogdevelopment/micronaut/consul/watch/watcher/WatcherTest.java @@ -12,7 +12,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import com.frogdevelopment.micronaut.consul.watch.client.IndexConsulClient; +import com.frogdevelopment.micronaut.consul.watch.client.WatchConsulClient; import com.frogdevelopment.micronaut.consul.watch.context.PropertiesChangeHandler; import io.micronaut.context.env.PropertySourceReader; @@ -23,7 +23,7 @@ class WatcherTest { private Watcher watcher; @Mock - private IndexConsulClient consulClient; + private WatchConsulClient consulClient; @Mock private PropertiesChangeHandler propertiesChangeHandler; private final PropertySourceReader propertySourceReader = new YamlPropertySourceLoader(); diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 9a17885..39b8e80 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -1,4 +1,5 @@ consul: - client: - read-idle-timeout: 15s - read-timeout: 30s + watch: + read-timeout: 2s + retry-count: 0 + watch-delay: 2s diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml index 2e098d4..53bad5c 100644 --- a/src/test/resources/logback.xml +++ b/src/test/resources/logback.xml @@ -11,7 +11,7 @@ - +