diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 810352c..1536c1a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Release Notes ============= +Version 1.2.0 +------------- + +Released 2018-08-29 + +* Discards clients from the pool on ConnectionError + Version 1.1.0 ------------- diff --git a/nameko_salesforce/api/client.py b/nameko_salesforce/api/client.py index 8e3bc0f..8d647a0 100644 --- a/nameko_salesforce/api/client.py +++ b/nameko_salesforce/api/client.py @@ -32,6 +32,8 @@ class MethodProxy(object): Fetches and then invokes a method from a client that is checked out of a pool. If the method raises a `SalesforceExpiredSession` the client is discarded from the pool and the method is retried on a new client. + If `ConnectionError` is raised, the client will be discarded, but the + method not automatically retried. `Salesforce` clients support querying directly with the client and via a "resource" attribute, so the method may be on the client @@ -53,7 +55,10 @@ def __call__(self, *args, **kwargs): try: method = self.get_method_ref(client) return method(*args, **kwargs) - except simple_salesforce.SalesforceExpiredSession: + except ( + simple_salesforce.SalesforceExpiredSession, + requests.exceptions.ConnectionError + ): self.pool.discard(client) raise diff --git a/setup.py b/setup.py index 5c1a951..a539b71 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='nameko-salesforce', - version='1.1.0', + version='1.2.0', description=( 'Nameko extension for easy communication with Salesforce ' '(Including Streaming API)' diff --git a/tests/api/test_client.py b/tests/api/test_client.py index 67eb151..215e4c4 100644 --- a/tests/api/test_client.py +++ b/tests/api/test_client.py @@ -2,6 +2,7 @@ from eventlet.event import Event from mock import patch import pytest +import requests import requests_mock from simple_salesforce import SalesforceResourceNotFound @@ -156,6 +157,39 @@ def test_bad_clients_are_discarded(client, mock_salesforce_server): assert len(client.pool.free) == 1 +@pytest.mark.usefixtures('fast_retry') +def test_bad_connections_are_discarded(client, mock_salesforce_server): + + # first call is successful; second is ConnectionError + requests_data = {'LastName': 'Smith', 'Email': 'example@example.com'} + response_data = { + 'errors': [], + 'id': '003e0000003GuNXAA0', + 'success': True + } + mock_salesforce_server.post( + requests_mock.ANY, + [ + {'json': response_data}, + {'exc': requests.exceptions.ConnectionError} + ] + ) + + assert client.Contact.create(requests_data) == response_data + + assert len(client.pool.busy) == 0 + assert len(client.pool.free) == 1 + _first_client = list(client.pool.free)[0] + + with pytest.raises(requests.exceptions.ConnectionError): + client.Contact.create(requests_data) + + # first client is discarded from the pool + assert _first_client not in client.pool.free + assert len(client.pool.busy) == 0 + assert len(client.pool.free) == 0 + + @pytest.mark.usefixtures('fast_retry') def test_proxy_retries_on_session_expired(client, mock_salesforce_server):