Retry DNS updates when they fail
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Alex 2023-01-11 22:35:56 +01:00
parent 7c8dcd7aa7
commit 5f946d485c
Signed by: lx
GPG key ID: 0E496D15096376BE
2 changed files with 25 additions and 6 deletions

View file

@ -24,7 +24,7 @@ pub struct DnsConfig {
pub entries: HashMap<DnsEntryKey, DnsEntryValue>, pub entries: HashMap<DnsEntryKey, DnsEntryValue>,
} }
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct DnsEntryKey { pub struct DnsEntryKey {
pub dns_path: String, pub dns_path: String,
pub record_type: DnsRecordType, pub record_type: DnsRecordType,
@ -35,7 +35,7 @@ pub struct DnsEntryValue {
pub targets: HashSet<String>, pub targets: HashSet<String>,
} }
#[derive(Debug, Hash, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
pub enum DnsRecordType { pub enum DnsRecordType {
A, A,

View file

@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -10,6 +11,8 @@ use tracing::*;
use crate::dns_config::*; use crate::dns_config::*;
use crate::DomainProvider; use crate::DomainProvider;
const RETRY_DELAY: Duration = Duration::from_secs(600); // 10 minutes
pub async fn dns_updater_task( pub async fn dns_updater_task(
mut rx_dns_config: watch::Receiver<Arc<DnsConfig>>, mut rx_dns_config: watch::Receiver<Arc<DnsConfig>>,
providers: Vec<DomainProvider>, providers: Vec<DomainProvider>,
@ -30,6 +33,8 @@ pub async fn dns_updater_task(
info!("DNS updater starting"); info!("DNS updater starting");
let mut config = Arc::new(DnsConfig::new()); let mut config = Arc::new(DnsConfig::new());
let mut failures = HashSet::new();
while !*must_exit.borrow() { while !*must_exit.borrow() {
select!( select!(
c = rx_dns_config.changed() => { c = rx_dns_config.changed() => {
@ -37,19 +42,31 @@ pub async fn dns_updater_task(
break; break;
} }
} }
_ = tokio::time::sleep(RETRY_DELAY) => {
if failures.is_empty() {
continue;
}
}
_ = must_exit.changed() => continue, _ = must_exit.changed() => continue,
); );
// Always lag 15 seconds behind actual updates, // Always lag 15 seconds behind actual updates,
// to avoid sending too many at once and hitting rate limits // to avoid sending too many at once and hitting rate limits
// TODO: retry regularly rate limits are hit
tokio::time::sleep(Duration::from_secs(15)).await; tokio::time::sleep(Duration::from_secs(15)).await;
let new_config: Arc<DnsConfig> = rx_dns_config.borrow_and_update().clone(); let new_config: Arc<DnsConfig> = rx_dns_config.borrow_and_update().clone();
let mut new_failures = HashSet::new();
for (key, value) in new_config.entries.iter() { for (key, value) in new_config.entries.iter() {
// Skip entries that haven't changed if failures.contains(key) {
if config.entries.get(key) == Some(value) { info!(
record = key.to_string(),
target = value.to_string(),
"retrying after failure"
);
} else if config.entries.get(key) == Some(value) {
// Skip entries that haven't changed, and that were
// successfully updated on the previous iteration
continue; continue;
} }
@ -75,8 +92,9 @@ pub async fn dns_updater_task(
record = key.to_string(), record = key.to_string(),
target = value.to_string(), target = value.to_string(),
error = e.to_string(), error = e.to_string(),
"unable to update record" "unable to update record, will retry later"
); );
new_failures.insert(key.clone());
} }
} else { } else {
error!( error!(
@ -87,6 +105,7 @@ pub async fn dns_updater_task(
} }
config = new_config; config = new_config;
failures = new_failures;
} }
} }