Skip to content

Commit 268e643

Browse files
committed
Improve Catching of Dreamhost Rate Limiting
1 parent 8772d07 commit 268e643

1 file changed

Lines changed: 60 additions & 63 deletions

File tree

src/main.rs

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -171,17 +171,25 @@ impl DreamhostClient {
171171
}
172172

173173
fn list_records(&self) -> Result<Vec<Record>> {
174-
// Check cache first
175174
let mut cache = self.record_cache.lock().unwrap();
176175
if let Some(records) = cache.as_ref() {
177176
debug!("Using cached DNS records");
178177
return Ok(records.clone());
179178
}
180179

181180
let resp = self.call(&[("cmd", "dns-list_records")])?;
182-
let records: Vec<Record> = serde_json::from_value(resp["data"].clone())?;
181+
182+
// Ensure we have a JSON array for data; else, treat as error
183+
let records: Vec<Record> = match &resp["data"] {
184+
serde_json::Value::Array(arr) => serde_json::from_value(serde_json::Value::Array(arr.clone()))?,
185+
_ => {
186+
// "data" might be a string like "slow_down_bucko"
187+
let reason = resp["reason"].as_str().unwrap_or("Unknown DreamHost API error");
188+
return Err(anyhow!("DreamHost API error: {}", reason));
189+
}
190+
};
183191

184-
*cache = Some(records.clone()); // store in cache
192+
*cache = Some(records.clone()); // cache it
185193
Ok(records)
186194
}
187195

@@ -266,68 +274,48 @@ fn check_and_update(
266274
) -> Result<()> {
267275

268276
match dh.get_dns_ip(record, record_type) {
269-
270277
Ok(current_ip) => {
271-
278+
// Existing record exists, update if necessary
272279
if let Ok(existing_ip) = current_ip.parse::<IpAddr>() {
273-
274280
if detected_ip == existing_ip {
275-
276281
info!("{} record already up-to-date", record_type);
277282
return Ok(());
278-
279283
}
280-
281284
}
282285

283286
warn!("{} record mismatch detected", record_type);
284287

285288
if dry_run {
286-
287-
info!(
288-
"DRY RUN: Would update {} record {} -> {}",
289-
record_type,
290-
current_ip,
291-
detected_ip
292-
);
293-
289+
info!("DRY RUN: Would update {} record {} -> {}", record_type, current_ip, detected_ip);
294290
return Ok(());
295291
}
296292

297-
dh.update_dns(
298-
record,
299-
&current_ip,
300-
&detected_ip.to_string(),
301-
record_type,
302-
)?;
303-
293+
dh.update_dns(record, &current_ip, &detected_ip.to_string(), record_type)?;
304294
info!("{} record updated successfully", record_type);
305-
306295
}
307296

308-
Err(_) => {
309-
310-
warn!("{} record does not exist, creating new one", record_type);
311-
312-
if dry_run {
297+
Err(e) => {
298+
// Only create record if the error indicates "not found"
299+
let msg = e.to_string();
300+
if msg.contains("not found") {
301+
warn!("{} record does not exist, creating new one", record_type);
313302

314-
info!(
315-
"DRY RUN: Would create {} record -> {}",
316-
record_type,
317-
detected_ip
318-
);
303+
if dry_run {
304+
info!("DRY RUN: Would create {} record -> {}", record_type, detected_ip);
305+
return Ok(());
306+
}
319307

320-
return Ok(());
308+
dh.call(&[
309+
("cmd", "dns-add_record"),
310+
("record", record),
311+
("type", record_type),
312+
("value", &detected_ip.to_string()),
313+
])?;
314+
info!("{} record created successfully", record_type);
315+
} else {
316+
// Propagate all other errors (API errors, rate limits, network errors)
317+
return Err(e);
321318
}
322-
323-
dh.call(&[
324-
("cmd", "dns-add_record"),
325-
("record", record),
326-
("type", record_type),
327-
("value", &detected_ip.to_string()),
328-
])?;
329-
330-
info!("{} record created successfully", record_type);
331319
}
332320
}
333321

@@ -375,36 +363,45 @@ fn main() -> Result<()> {
375363

376364
impl DetectionJob {
377365
fn run(self, dh: &Arc<DreamhostClient>) -> Result<()> {
366+
367+
// helper to safely remove a DNS record if it exists
368+
let remove_stale_record = |record_type: &str, record_name: &str| -> Result<()> {
369+
match dh.get_dns_ip(record_name, record_type) {
370+
Ok(existing_ip) => {
371+
warn!("{} record exists but no WAN IP detected: {}", record_type, existing_ip);
372+
if self.dry_run {
373+
info!("DRY RUN: Would remove stale {} record {}", record_type, existing_ip);
374+
} else {
375+
dh.call(&[
376+
("cmd", "dns-remove_record"),
377+
("record", record_name),
378+
("type", record_type),
379+
("value", &existing_ip),
380+
])?;
381+
warn!("Removed stale {} record {}", record_type, existing_ip);
382+
}
383+
}
384+
Err(_) => debug!("No {} record exists; nothing to remove", record_type),
385+
}
386+
Ok(())
387+
};
388+
378389
match detect_ip(&self.client, self.services, self.require_ipv4) {
379390
Ok(ip) => {
380-
info!("Detected {} WAN: {}", self.record_type, ip);
391+
let ipv = if self.record_type=="A" { "IPV4" } else { "IPV6" };
392+
info!("Detected {} WAN: {}", ipv, ip);
381393
check_and_update(dh, &self.record_name, ip, self.record_type, self.dry_run)?;
382394
}
383395
Err(_) => {
384396
if self.record_type == "AAAA" {
385397
info!("No IPv6 WAN detected");
386-
match dh.get_dns_ip(&self.record_name, "AAAA") {
387-
Ok(existing_ip) => {
388-
warn!("IPv6 not detected but AAAA record exists: {}", existing_ip);
389-
if self.dry_run {
390-
info!("DRY RUN: Would remove stale AAAA record {}", existing_ip);
391-
} else {
392-
dh.call(&[
393-
("cmd", "dns-remove_record"),
394-
("record", &self.record_name),
395-
("type", "AAAA"),
396-
("value", &existing_ip),
397-
])?;
398-
warn!("Removed stale AAAA record {}", existing_ip);
399-
}
400-
}
401-
Err(_) => debug!("No AAAA record exists; nothing to remove"),
402-
}
398+
remove_stale_record("AAAA", &self.record_name)?;
403399
} else {
404400
warn!("No IPv4 WAN detected");
405401
}
406402
}
407403
}
404+
408405
Ok(())
409406
}
410407
}

0 commit comments

Comments
 (0)