Move backoff logic to Updater
This commit is contained in:
parent
da402b0da9
commit
4b0f3cefb8
5 changed files with 58 additions and 27 deletions
10
README.md
10
README.md
|
@ -22,11 +22,11 @@ The configuration can contain a list of update targets:
|
|||
|
||||
ddnssclient can also be configured using some properties or environment variables
|
||||
|
||||
| Property | Environment variable | Value | Default |
|
||||
| -------- |-----------------------|-----------------------------------|---------|
|
||||
| ddnsclient.interval | DDNSCLIENT_INTERVAL | e.g. "3600s", "60m", "1h" | "5m" |
|
||||
| ddnsclient.ip-provider | DDNSCLIENT_IP_PROVIDER | an ip lookup provider (see below) | null |
|
||||
| ddnsclient.dyndns.backup-duration | DDNSCLIENT_DYNDNS_BACKUP_DURATION | e.g. "60s", "1m" | "60s" |
|
||||
| Property | Environment variable | Value | Default |
|
||||
|-----------------------------|------------------------------|-----------------------------------|---------|
|
||||
| ddnsclient.interval | DDNSCLIENT_INTERVAL | e.g. "3600s", "60m", "1h" | "5m" |
|
||||
| ddnsclient.ip-provider | DDNSCLIENT_IP_PROVIDER | an ip lookup provider (see below) | null |
|
||||
| ddnsclient.backoff-duration | DDNS_CLIENT_BACKOFF_DURATION | e.g. "60s", "1m" | "60s" |
|
||||
|
||||
## IP lookup
|
||||
|
||||
|
|
|
@ -9,8 +9,14 @@ import de.rpr.ddnsclient.model.DyndnsAuth;
|
|||
import de.rpr.ddnsclient.model.IPs;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ApplicationScoped
|
||||
public class Updater {
|
||||
|
||||
|
@ -19,15 +25,23 @@ public class Updater {
|
|||
private final DynDnsRouter dynDnsRouter;
|
||||
private final IpProvider ipProvider;
|
||||
private final DnsResolver dnsResolver;
|
||||
private final Duration backoff;
|
||||
|
||||
private final Config config;
|
||||
|
||||
private final Map<String, LocalDateTime> updateMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
public Updater(DynDnsRouter dynDnsRouter, IpProvider ipProvider, DnsResolver dnsResolver, Config config) {
|
||||
public Updater(DynDnsRouter dynDnsRouter,
|
||||
IpProvider ipProvider,
|
||||
DnsResolver dnsResolver,
|
||||
Config config,
|
||||
@ConfigProperty(name = "ddnsclient.backoff-duration:300s") Duration backoff) {
|
||||
this.dynDnsRouter = dynDnsRouter;
|
||||
this.ipProvider = ipProvider;
|
||||
this.dnsResolver = dnsResolver;
|
||||
this.config = config;
|
||||
this.backoff = backoff;
|
||||
}
|
||||
|
||||
void run() {
|
||||
|
@ -42,6 +56,12 @@ public class Updater {
|
|||
|
||||
config.forEach(cfg -> {
|
||||
|
||||
if (updateMap.containsKey(cfg.hostname())
|
||||
&& Duration.between(updateMap.get(cfg.hostname()), LocalDateTime.now()).toSeconds() < backoff.toSeconds()) {
|
||||
log.debug("Back-off period, skipping update.");
|
||||
return;
|
||||
}
|
||||
|
||||
log.infof("Handling %s.", cfg.hostname());
|
||||
|
||||
IPs registeredIps = dnsResolver.resolve(cfg.hostname());
|
||||
|
@ -51,6 +71,7 @@ public class Updater {
|
|||
log.tracef("IPs changed, updating...");
|
||||
DynDns dynDns = dynDnsRouter.get(cfg.provider());
|
||||
dynDns.update(cfg.hostname(), publicIps, new DyndnsAuth(null, null, cfg.token()));
|
||||
updateMap.put(cfg.hostname(), LocalDateTime.now());
|
||||
} else {
|
||||
log.infof("Hostname is up-to-date.", cfg.hostname());
|
||||
}
|
||||
|
|
|
@ -22,11 +22,6 @@ public class Ddnss implements DynDns {
|
|||
|
||||
private static final Logger log = Logger.getLogger(Ddnss.class);
|
||||
|
||||
@ConfigProperty(name = "ddnsclient.dyndns.backoff-duration")
|
||||
Duration backoff;
|
||||
|
||||
private final Map<String, LocalDateTime> updateMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "ddnss";
|
||||
|
@ -34,12 +29,6 @@ public class Ddnss implements DynDns {
|
|||
|
||||
public void update(String hostname, IPs currentIps, DyndnsAuth auth) {
|
||||
|
||||
if (updateMap.containsKey(hostname)
|
||||
&& Duration.between(updateMap.get(hostname), LocalDateTime.now()).toSeconds() < backoff.toSeconds()) {
|
||||
log.debug("Back-off period, skipping update.");
|
||||
return;
|
||||
}
|
||||
|
||||
String updateUrl = MessageFormat.format("https://ddnss.de/upd.php?key={0}&host={1}&ip={2}&ip6={3}",
|
||||
auth.token(), hostname, currentIps.v4(), currentIps.v6());
|
||||
|
||||
|
@ -55,7 +44,6 @@ public class Ddnss implements DynDns {
|
|||
if (response.statusCode() != 200) {
|
||||
log.errorf("Couldn't update hostname %s." + hostname);
|
||||
}
|
||||
updateMap.put(hostname, LocalDateTime.now());
|
||||
log.info("Hostname updated.");
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
|
@ -2,7 +2,3 @@ quarkus.naming.enable-jndi=true
|
|||
quarkus.log.level=INFO
|
||||
quarkus.log.category."de.rpr.ddnsclient".min-level=TRACE
|
||||
quarkus.log.category."de.rpr.ddnsclient".level=INFO
|
||||
|
||||
ddnsclient.interval=15s
|
||||
#ddnsclient.ip-provider=
|
||||
ddnsclient.dyndns.backoff-duration=60s
|
|
@ -15,6 +15,7 @@ import org.mockito.ArgumentCaptor;
|
|||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -34,10 +35,12 @@ class UpdaterTest {
|
|||
add(new Value("ddnss", "example.org", null, null, "token"));
|
||||
}};
|
||||
|
||||
Duration backoff = Duration.ofMinutes(5);
|
||||
|
||||
@Test
|
||||
void should_throw_exception_if_config_is_empty() {
|
||||
Config config = new Config();
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, config);
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, config, backoff);
|
||||
Assertions.assertThrows(IllegalStateException.class, updater::run);
|
||||
}
|
||||
|
||||
|
@ -53,7 +56,7 @@ class UpdaterTest {
|
|||
add(new Value("ddnss", "host2.example.org", null, null, "token"));
|
||||
}};
|
||||
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, multipleConfigEntries);
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, multipleConfigEntries, backoff);
|
||||
updater.run();
|
||||
|
||||
ArgumentCaptor<String> hostnameCaptor = ArgumentCaptor.forClass(String.class);
|
||||
|
@ -71,7 +74,7 @@ class UpdaterTest {
|
|||
when(ipProvider.getPublicIps()).thenReturn(ips);
|
||||
when(dnsResolver.resolve("example.org")).thenReturn(ips);
|
||||
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig);
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig, backoff);
|
||||
updater.run();
|
||||
|
||||
verify(dynDnsRouter, never()).get(any());
|
||||
|
@ -89,7 +92,7 @@ class UpdaterTest {
|
|||
when(ipProvider.getPublicIps()).thenReturn(publicIps);
|
||||
when(dnsResolver.resolve("example.org")).thenReturn(new IPs("registered_ipv4", "registered_ipv6"));
|
||||
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig);
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig, backoff);
|
||||
updater.run();
|
||||
|
||||
verify(ddnss).update(
|
||||
|
@ -99,4 +102,27 @@ class UpdaterTest {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_not_try_to_update_hostname_within_configured_backoff_duration() {
|
||||
|
||||
DynDns ddnss = mock(Ddnss.class);
|
||||
|
||||
when(dynDnsRouter.get("ddnss")).thenReturn(ddnss);
|
||||
|
||||
IPs publicIps = new IPs("ipv4", "ipv6");
|
||||
when(ipProvider.getPublicIps()).thenReturn(publicIps);
|
||||
when(dnsResolver.resolve("example.org")).thenReturn(new IPs("registered_ipv4", "registered_ipv6"));
|
||||
|
||||
Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig, backoff);
|
||||
updater.run();
|
||||
|
||||
updater.run();
|
||||
|
||||
verify(ddnss, times(1)).update(
|
||||
"example.org",
|
||||
publicIps,
|
||||
new DyndnsAuth(null, null, "token")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue