Skip to content

Commit

Permalink
Add a retry mechanism on swagger.json
Browse files Browse the repository at this point in the history
EsiApp will now try up to 3 times to get the swagger.json spec.
  • Loading branch information
Kyria committed Jun 23, 2019
1 parent 06407a0 commit 11f55fd
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,5 @@ ENV/
.ropeproject

env3/

\.vscode/
4 changes: 2 additions & 2 deletions esipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .app import EsiApp # noqa
from pyswagger import App # noqa
except ImportError: # pragma: no cover
# Not installed or in install (not yet installed) so ignore
# Not installed or in install (not yet installed) so ignore
pass

__version__ = '1.0.0'
__version__ = '1.1.0'
31 changes: 29 additions & 2 deletions esipy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
""" App entry point. Uses Esi Meta Endpoint to work """
import time

import logging
import requests
from six.moves.urllib.error import HTTPError

from pyswagger import App

from .utils import check_cache
from .utils import get_cache_time_left
from .exceptions import APIException

LOGGER = logging.getLogger(__name__)


class EsiApp(object):
Expand Down Expand Up @@ -103,8 +108,30 @@ def __get_or_create_app(self, url, cache_key):
return cached_app

# ok, cache is not accurate, make the full stuff
app = App.create(app_url)
if self.caching:
# also retry up to 3 times if we get any errors
app = None
for _retry in range(1, 4):
try:
app = App.create(app_url)
except HTTPError as error:
LOGGER.warning(
"[failure #%d] %s %d: %r",
_retry,
app_url,
error.code,
error.msg
)
continue
break

if app is None:
raise APIException(
app_url,
500,
response="Cannot fetch '%s'." % app_url
)

if self.caching and app:
self.cache.set(cache_key, (app, res.headers, timeout))

return app
Expand Down
39 changes: 39 additions & 0 deletions test/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

from esipy import EsiApp
from esipy.cache import DictCache
from esipy.exceptions import APIException
from pyswagger import App

import httmock
import mock
import unittest
from six.moves.urllib.error import HTTPError

from .mock import _swagger_spec_mock_
from .mock import make_expire_time_str
Expand Down Expand Up @@ -182,3 +184,40 @@ def fail_if_request(url, request):
urlopen_mock.return_value = open(TestEsiApp.ESI_META_SWAGGER)
EsiApp(cache_time=None, cache=cache, cache_prefix='esipy_test')
urlopen_mock.return_value.close()

@mock.patch('six.moves.urllib.request.urlopen')
def test_app_http_error_retry_fail(self, urlopen_mock):
urlopen_mock.side_effect = HTTPError(
"http://mock.test",
500,
"HTTP 500 whatever",
None,
None
)
with httmock.HTTMock(*_swagger_spec_mock_):
with self.assertRaises(APIException):
self.app = EsiApp(cache_prefix='esipy_test')
self.assertEqual(urlopen_mock.call_count, 3)

@mock.patch('six.moves.urllib.request.urlopen')
def test_app_http_error_retry_ok(self, urlopen_mock):
http_error = HTTPError(
"http://mock.test",
500,
"HTTP 500 whatever",
None,
None
)

# this will make the function raise exception / return the value
# in this given order
side_effect_results = [
http_error,
http_error,
open(TestEsiApp.ESI_META_SWAGGER)
]

urlopen_mock.side_effect = side_effect_results
with httmock.HTTMock(*_swagger_spec_mock_):
EsiApp(cache_prefix='esipy_test')
self.assertEqual(urlopen_mock.call_count, 3)

0 comments on commit 11f55fd

Please sign in to comment.