Skip to content

Commit

Permalink
Automatically retry ConnectionErrors
Browse files Browse the repository at this point in the history
  • Loading branch information
bboe committed Mar 26, 2017
1 parent 2f0e701 commit 81f9cc0
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 4 deletions.
9 changes: 9 additions & 0 deletions CHANGES.rst
Expand Up @@ -4,6 +4,15 @@ Change Log
prawcore follows `semantic versioning <http://semver.org/>`_ with the exception
that deprecations will not be announced by a minor release.

Unreleased
----------

**Added**

* ``ConnectionErrors`` exceptios are automatically retried. This handles
``Connection Reset by Peer`` issues that appear to occur somewhat frequently
when running on Amazon EC2.

0.9.0 (2017-03-11)
------------------

Expand Down
2 changes: 1 addition & 1 deletion prawcore/const.py
@@ -1,7 +1,7 @@
"""Constants for the prawcore package."""
import os

__version__ = '0.9.0'
__version__ = '0.10.0rc1'

ACCESS_TOKEN_PATH = '/api/v1/access_token'
AUTHORIZATION_PATH = '/api/v1/authorize'
Expand Down
4 changes: 2 additions & 2 deletions prawcore/sessions.py
Expand Up @@ -5,7 +5,7 @@
import time

from requests.compat import urljoin
from requests.exceptions import ChunkedEncodingError
from requests.exceptions import ChunkedEncodingError, ConnectionError
from requests.status_codes import codes

from .auth import BaseAuthorizer
Expand All @@ -20,7 +20,7 @@
class Session(object):
"""The low-level connection interface to reddit's API."""

RETRY_EXCEPTIONS = (ChunkedEncodingError,)
RETRY_EXCEPTIONS = (ChunkedEncodingError, ConnectionError)
RETRY_STATUSES = {520, 522, codes['bad_gateway'], codes['gateway_timeout'],
codes['internal_server_error'],
codes['service_unavailable']}
Expand Down
30 changes: 29 additions & 1 deletion tests/test_sessions.py
Expand Up @@ -7,7 +7,7 @@
from betamax import Betamax
from mock import Mock, patch
from prawcore.exceptions import RequestException
from requests.exceptions import ChunkedEncodingError
from requests.exceptions import ChunkedEncodingError, ConnectionError
from testfixtures import LogCapture

from .config import (CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN, REQUESTOR,
Expand Down Expand Up @@ -97,6 +97,34 @@ def test_request__chunked_encoding_retry(self, mock_session):
self.assertIs(exception, context_manager.exception.original_exception)
self.assertEqual(3, session_instance.request.call_count)

@patch('requests.Session')
def test_request__connection_error_retry(self, mock_session):
session_instance = mock_session.return_value

# Handle Auth
response_dict = {'access_token': '', 'expires_in': 99, 'scope': ''}
session_instance.request.return_value = Mock(
headers={}, json=lambda: response_dict, status_code=200)
requestor = prawcore.Requestor('prawcore:test (by /u/bboe)')
authorizer = readonly_authorizer(requestor=requestor)
session_instance.request.reset_mock()

# Fail on subsequent request
exception = ConnectionError()
session_instance.request.side_effect = exception

expected = ('prawcore', 'WARNING',
'Retrying due to ConnectionError() status: GET '
'https://oauth.reddit.com/')

with LogCapture(level=logging.WARNING) as log_capture:
with self.assertRaises(RequestException) as context_manager:
prawcore.Session(authorizer).request('GET', '/')
log_capture.check(expected, expected)
self.assertIsInstance(context_manager.exception, RequestException)
self.assertIs(exception, context_manager.exception.original_exception)
self.assertEqual(3, session_instance.request.call_count)

def test_request__get(self):
with Betamax(REQUESTOR).use_cassette('Session_request__get'):
session = prawcore.Session(readonly_authorizer())
Expand Down

0 comments on commit 81f9cc0

Please sign in to comment.