Commits

Sebastian Rahlf  committed f4315b4 Merge

Merged in retry functionality from jerryji/python-amazon-product-api (pull request #2)

  • Participants
  • Parent commits 758a663, b3dcdcc

Comments (0)

Files changed (5)

 
 Benoit C
 Dmitry Chaplinsky
+Jerry Ji
 Kilian Valkhof
+0.2.6 (in development)
+----------------------
+
+- Added RetryAPI to contrib package thanks to Jerry Ji.
+
+
 0.2.5 (2011-09-19) "Buttercup"
 ------------------------------
 

File amazonproduct/api.py

File contents unchanged.

File amazonproduct/contrib/retry.py

+
+import socket
+import time
+import urllib2
+
+from amazonproduct.api import API
+
+class RetryAPI (API):
+
+    """
+    API which will try up to ``TRIES`` times to fetch a result from Amazon
+    should it run into a timeout. For the time being this will remain in
+    :mod:`amazonproduct.contrib` but its functionality may be merged into the
+    main API at a later date.
+
+    Based on work by Jerry Ji
+    """
+
+    #: Max number of tries before giving up
+    TRIES = 5
+
+    #: Delay between tries in seconds
+    DELAY = 3
+
+    #: Between each try the delay will be lengthened by this backoff multiplier
+    BACKOFF = 1
+
+    def _fetch(self, url):
+        """
+        Retrieves XML response from Amazon. In case of a timeout, it will try
+        :const:`~RetryAPI.TRIES`` times before raising an error.
+        """
+        attempts = 0
+        delay = self.DELAY
+
+        while True:
+            try:
+                attempts += 1
+                return API._fetch(self, url)
+            except urllib2.URLError, e:
+
+                # if a timeout occurred
+                # wait for some time before trying again
+                reason = getattr(e, 'reason', None)
+                if isinstance(reason, socket.timeout) and attempts < self.TRIES:
+                    time.sleep(delay)
+                    delay *= self.BACKOFF
+                    continue
+
+                # otherwise reraise the original error
+                raise
+

File tests/test_contrib_retry.py

+import socket
+from urllib2 import URLError
+import pytest
+
+from amazonproduct.api import API
+from amazonproduct.contrib.retry import RetryAPI
+
+@pytest.mark.slowtest
+def test_timeout(monkeypatch):
+    """
+    Check that in case of a timeout API will not give up easily.
+    """
+
+    class mock_fetch (object):
+        def __init__(self):
+            self.calls = 0
+        def __call__(self, _, url):
+            self.calls += 1
+            print 'call %i: %s' % (self.calls, url)
+            raise URLError(socket.timeout())
+
+    fetcher = mock_fetch()
+    monkeypatch.setattr(API, '_fetch', fetcher)
+
+    api = RetryAPI(locale='de')
+
+    itworked = False
+    try:
+        api.call(operation='DummyOperation')
+        itworked = True
+    except URLError, e:
+        assert isinstance(e.reason, socket.timeout)
+
+    # timeout WAS raised and fetch was called TRIES times
+    assert not itworked
+    assert fetcher.calls == api.TRIES