/*
* Copyright (c) 2015 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.spotify.dns;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* Provides builders for configuring and instantiating {@link DnsSrvWatcher}s.
*/
public final class DnsSrvWatchers {
/**
* Creates a {@link DnsSrvWatcherBuilder} using the given {@link DnsSrvResolver}. The builder
* can be configured to have the desired behavior.
*
*
Exactly one of {@link DnsSrvWatcherBuilder#polling(long, TimeUnit)} or
* {@link DnsSrvWatcherBuilder#customTrigger(DnsSrvWatcherFactory)} must be used.
*
* @param resolver The resolver to use for lookups
* @return a builder for further configuring the watcher
*/
public static DnsSrvWatcherBuilder newBuilder(DnsSrvResolver resolver) {
requireNonNull(resolver, "resolver");
return new DnsSrvWatcherBuilder<>(resolver, Function.identity());
}
/**
* Creates a {@link DnsSrvWatcherBuilder} using the given {@link DnsSrvResolver}. The builder
* can be configured to have the desired behavior.
*
* This watcher will use a function that transforms the {@link LookupResult}s into an
* arbitrary type that will be used throughout the {@link DnsSrvWatcher} api.
*
*
Exactly one of {@link DnsSrvWatcherBuilder#polling(long, TimeUnit)} or
* {@link DnsSrvWatcherBuilder#customTrigger(DnsSrvWatcherFactory)} must be used.
*
* @param resolver The resolver to use for lookups
* @param resultTransformer The transformer function
* @return a builder for further configuring the watcher
*/
public static DnsSrvWatcherBuilder newBuilder(
DnsSrvResolver resolver,
Function resultTransformer) {
requireNonNull(resolver, "resolver");
requireNonNull(resultTransformer, "resultTransformer");
return new DnsSrvWatcherBuilder<>(resolver, resultTransformer);
}
/**
* @deprecated Use {@link #newBuilder(DnsSrvResolver, java.util.function.Function)}
* deprecated since version 3.2.0
*/
public static DnsSrvWatcherBuilder newBuilder(
DnsSrvResolver resolver,
com.google.common.base.Function resultTransformer) {
requireNonNull(resolver, "resolver");
requireNonNull(resultTransformer, "resultTransformer");
return new DnsSrvWatcherBuilder<>(resolver, resultTransformer);
}
public static final class DnsSrvWatcherBuilder {
private final DnsSrvResolver resolver;
private final Function resultTransformer;
private final boolean polling;
private final long pollingInterval;
private final TimeUnit pollingIntervalUnit;
private final ErrorHandler errorHandler;
private final DnsSrvWatcherFactory dnsSrvWatcherFactory;
private final ScheduledExecutorService scheduledExecutorService;
private DnsSrvWatcherBuilder(
DnsSrvResolver resolver,
Function resultTransformer) {
this(resolver, resultTransformer, false, 0, null, null, null, null);
}
private DnsSrvWatcherBuilder(
DnsSrvResolver resolver,
Function resultTransformer,
boolean polling,
long pollingInterval,
TimeUnit pollingIntervalUnit,
ErrorHandler errorHandler,
DnsSrvWatcherFactory dnsSrvWatcherFactory,
ScheduledExecutorService scheduledExecutorService) {
this.resolver = resolver;
this.resultTransformer = resultTransformer;
this.polling = polling;
this.pollingInterval = pollingInterval;
this.pollingIntervalUnit = pollingIntervalUnit;
this.errorHandler = errorHandler;
this.dnsSrvWatcherFactory = dnsSrvWatcherFactory;
this.scheduledExecutorService = scheduledExecutorService;
}
public DnsSrvWatcher build() {
checkState(polling ^ dnsSrvWatcherFactory != null, "specify either polling or custom trigger");
DnsSrvWatcherFactory watcherFactory;
if (polling) {
final ScheduledExecutorService executor =
scheduledExecutorService != null
? scheduledExecutorService
: MoreExecutors.getExitingScheduledExecutorService(
new ScheduledThreadPoolExecutor(
1, new ThreadFactoryBuilder().setNameFormat("dns-lookup-%d").build()),
0, SECONDS);
watcherFactory =
cnf -> new PollingDnsSrvWatcher<>(cnf, executor, pollingInterval, pollingIntervalUnit);
} else {
watcherFactory = requireNonNull(dnsSrvWatcherFactory, "dnsSrvWatcherFactory");
}
final ChangeNotifierFactory changeNotifierFactory =
fqdn -> new ServiceResolvingChangeNotifier<>(
resolver, fqdn, resultTransformer, errorHandler);
return watcherFactory.create(changeNotifierFactory);
}
public DnsSrvWatcherBuilder polling(long pollingInterval, TimeUnit pollingIntervalUnit) {
checkArgument(pollingInterval > 0);
requireNonNull(pollingIntervalUnit, "pollingIntervalUnit");
return new DnsSrvWatcherBuilder(resolver, resultTransformer, true, pollingInterval,
pollingIntervalUnit, errorHandler, dnsSrvWatcherFactory,
scheduledExecutorService);
}
public DnsSrvWatcherBuilder usingExecutor(ScheduledExecutorService scheduledExecutorService) {
return new DnsSrvWatcherBuilder(resolver, resultTransformer, polling, pollingInterval,
pollingIntervalUnit, errorHandler, dnsSrvWatcherFactory,
scheduledExecutorService);
}
public DnsSrvWatcherBuilder customTrigger(DnsSrvWatcherFactory watcherFactory) {
requireNonNull(watcherFactory, "watcherFactory");
return new DnsSrvWatcherBuilder(resolver, resultTransformer, true, pollingInterval,
pollingIntervalUnit, errorHandler, watcherFactory,
scheduledExecutorService);
}
public DnsSrvWatcherBuilder withErrorHandler(ErrorHandler errorHandler) {
requireNonNull(errorHandler, "errorHandler");
return new DnsSrvWatcherBuilder(resolver, resultTransformer, true, pollingInterval,
pollingIntervalUnit, errorHandler, dnsSrvWatcherFactory,
scheduledExecutorService);
}
}
private DnsSrvWatchers() {
// prevent instantiation
}
}