]> git.ipfire.org Git - people/stevee/ddns.git/commitdiff
Introduce error type "rate-limited" status-defeated
authorStefan Schantl <stefan.schantl@ipfire.org>
Fri, 24 Feb 2017 10:53:50 +0000 (11:53 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Fri, 24 Feb 2017 12:38:13 +0000 (13:38 +0100)
This error type is used for handling HTTP 429 - Too many requests.

When using this error type, a holdoff_time of 30 minutes will be
used by default until the next update attempt will be send. The holdoff_time
can be specified in the provides class if needed.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
src/ddns/database.py
src/ddns/errors.py
src/ddns/providers.py

index 70a73635740211e356e2f68144dc4475f3390dea..adce5874e4ea656cd178fd7da08e625393abeea6 100644 (file)
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # ddns - A dynamic DNS client for IPFire                                      #
-# Copyright (C) 2014 IPFire development team                                  #
+# Copyright (C) 2014-2017 IPFire development team                             #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -111,12 +111,14 @@ class DDNSDatabase(object):
        def log_failure(self, hostname, exception):
                if exception:
                        message = "%s: %s" % (exception.__class__.__name__, exception.reason)
+                       error_type = exception.genre
                else:
                        message = None
+                       error_type = "failure"
 
                logger.debug("Logging failed update for %s: %s" % (hostname, message or ""))
 
-               return self.add_update(hostname, "failure", message=message)
+               return self.add_update(hostname, error_type, message=message)
 
        def last_update(self, hostname, status=None):
                """
index a8a201751f1111d41c2723681897e1261c467803..56ab97459942953860827d6a7b9a4140d5513bbe 100644 (file)
@@ -27,6 +27,7 @@ class DDNSError(Exception):
                raised by DDNS.
        """
        reason = N_("Error")
+       genre = "failure"
 
        def __init__(self, message=None):
                self.message = message
@@ -166,6 +167,7 @@ class DDNSTooManyRequests(DDNSError):
                Raised when too many requests occured.
        """
        reason = N_("Too many requests")
+       genre = "rate-limited"
 
 
 class DDNSUpdateError(DDNSError):
index ea723e591667e926907e3536d10a751fb7521b2a..cb6dd2d19464f20bc82911a6d0509998f4f64caa 100644 (file)
@@ -67,6 +67,10 @@ class DDNSProvider(object):
        # is tried after the last one has failed.
        holdoff_failure_days = 0.5
 
+       # holdoff time for rate-limited updates - Number of minutes no update
+       # is tried after the last one has been sent.
+       holdoff_rate-limited_minutes = 30
+
        # True if the provider is able to remove records, too.
        # Required to remove AAAA records if IPv6 is absent again.
        can_remove_records = True
@@ -223,13 +227,13 @@ class DDNSProvider(object):
        @property
        def has_failure(self):
                """
-                       Returns True when the last update has failed and no retry
-                       should be performed, yet.
+                       Returns True when the last update has not failed or rate-limited and
+                       no retry should be performed, yet.
                """
                last_status = self.db.last_update_status(self.hostname)
 
-               # Return False if the last update has not failed.
-               if not last_status == "failure":
+               # Return False if the last update has failed or has been rate-limited.
+               if not (last_status == "failure" or last_status == "rate-limited"):
                        return False
 
                # If there is no holdoff time, we won't update ever again.
@@ -242,7 +246,12 @@ class DDNSProvider(object):
 
                # Determine when the holdoff time ends
                last_update = self.db.last_update(self.hostname, status=last_status)
-               holdoff_end = last_update + datetime.timedelta(days=self.holdoff_failure_days)
+
+               # Calculate holdoff end, based on the last status (failure or rate-limited)
+               if last_status == "failure"
+                       holdoff_end = last_update + datetime.timedelta(days=self.holdoff_failure_days)
+               else:
+                       holdoff_end = last_update + datetime.timedelta(minutes=self.holdoff_rate-limited_minutes)
 
                now = datetime.datetime.utcnow()
                if now < holdoff_end: