Merge "Stop retrying every deletes in container-sync"
This commit is contained in:
commit
758329b1f4
|
@ -28,7 +28,7 @@ from zlib import compressobj
|
||||||
from swift.common.constraints import AUTO_CREATE_ACCOUNT_PREFIX
|
from swift.common.constraints import AUTO_CREATE_ACCOUNT_PREFIX
|
||||||
from swift.common.exceptions import ClientException
|
from swift.common.exceptions import ClientException
|
||||||
from swift.common.http import (HTTP_NOT_FOUND, HTTP_MULTIPLE_CHOICES,
|
from swift.common.http import (HTTP_NOT_FOUND, HTTP_MULTIPLE_CHOICES,
|
||||||
is_server_error)
|
is_client_error, is_server_error)
|
||||||
from swift.common.swob import Request, bytes_to_wsgi
|
from swift.common.swob import Request, bytes_to_wsgi
|
||||||
from swift.common.utils import quote, closing_if_possible
|
from swift.common.utils import quote, closing_if_possible
|
||||||
from swift.common.wsgi import loadapp, pipeline_property
|
from swift.common.wsgi import loadapp, pipeline_property
|
||||||
|
@ -930,14 +930,17 @@ class SimpleClient(object):
|
||||||
self.attempts += 1
|
self.attempts += 1
|
||||||
try:
|
try:
|
||||||
return self.base_request(method, **kwargs)
|
return self.base_request(method, **kwargs)
|
||||||
|
except urllib2.HTTPError as err:
|
||||||
|
if is_client_error(err.getcode() or 500):
|
||||||
|
raise ClientException('Client error',
|
||||||
|
http_status=err.getcode())
|
||||||
|
elif self.attempts > retries:
|
||||||
|
raise ClientException('Raise too many retries',
|
||||||
|
http_status=err.getcode())
|
||||||
except (socket.error, httplib.HTTPException, urllib2.URLError) \
|
except (socket.error, httplib.HTTPException, urllib2.URLError) \
|
||||||
as err:
|
as err:
|
||||||
if self.attempts > retries:
|
if self.attempts > retries:
|
||||||
if isinstance(err, urllib2.HTTPError):
|
raise
|
||||||
raise ClientException('Raise too many retries',
|
|
||||||
http_status=err.getcode())
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
sleep(backoff)
|
sleep(backoff)
|
||||||
backoff = min(backoff * 2, self.max_backoff)
|
backoff = min(backoff * 2, self.max_backoff)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ from swift.common.utils import (
|
||||||
FileLikeIter, get_logger, hash_path, quote, validate_sync_to,
|
FileLikeIter, get_logger, hash_path, quote, validate_sync_to,
|
||||||
whataremyips, Timestamp, decode_timestamps)
|
whataremyips, Timestamp, decode_timestamps)
|
||||||
from swift.common.daemon import Daemon
|
from swift.common.daemon import Daemon
|
||||||
from swift.common.http import HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
|
from swift.common.http import HTTP_UNAUTHORIZED, HTTP_NOT_FOUND, HTTP_CONFLICT
|
||||||
from swift.common.wsgi import ConfigString
|
from swift.common.wsgi import ConfigString
|
||||||
from swift.common.middleware.versioned_writes.object_versioning import (
|
from swift.common.middleware.versioned_writes.object_versioning import (
|
||||||
SYSMETA_VERSIONS_CONT, SYSMETA_VERSIONS_SYMLINK)
|
SYSMETA_VERSIONS_CONT, SYSMETA_VERSIONS_SYMLINK)
|
||||||
|
@ -570,7 +570,8 @@ class ContainerSync(Daemon):
|
||||||
logger=self.logger,
|
logger=self.logger,
|
||||||
timeout=self.conn_timeout)
|
timeout=self.conn_timeout)
|
||||||
except ClientException as err:
|
except ClientException as err:
|
||||||
if err.http_status != HTTP_NOT_FOUND:
|
if err.http_status not in (
|
||||||
|
HTTP_NOT_FOUND, HTTP_CONFLICT):
|
||||||
raise
|
raise
|
||||||
self.container_deletes += 1
|
self.container_deletes += 1
|
||||||
self.container_stats['deletes'] += 1
|
self.container_stats['deletes'] += 1
|
||||||
|
|
|
@ -1600,6 +1600,36 @@ class TestSimpleClient(unittest.TestCase):
|
||||||
self.assertEqual(mock_sleep.call_count, 1)
|
self.assertEqual(mock_sleep.call_count, 1)
|
||||||
self.assertEqual(mock_urlopen.call_count, 2)
|
self.assertEqual(mock_urlopen.call_count, 2)
|
||||||
|
|
||||||
|
@mock.patch.object(urllib2, 'urlopen')
|
||||||
|
def test_delete_object_with_404_no_retry(self, mock_urlopen):
|
||||||
|
mock_response = mock.MagicMock()
|
||||||
|
mock_response.read.return_value = b''
|
||||||
|
err_args = [None, 404, None, None, None]
|
||||||
|
mock_urlopen.side_effect = urllib2.HTTPError(*err_args)
|
||||||
|
|
||||||
|
with mock.patch('swift.common.internal_client.sleep') as mock_sleep, \
|
||||||
|
self.assertRaises(exceptions.ClientException) as caught:
|
||||||
|
internal_client.delete_object('http://127.0.0.1',
|
||||||
|
container='con', name='obj')
|
||||||
|
self.assertEqual(caught.exception.http_status, 404)
|
||||||
|
self.assertEqual(mock_sleep.call_count, 0)
|
||||||
|
self.assertEqual(mock_urlopen.call_count, 1)
|
||||||
|
|
||||||
|
@mock.patch.object(urllib2, 'urlopen')
|
||||||
|
def test_delete_object_with_409_no_retry(self, mock_urlopen):
|
||||||
|
mock_response = mock.MagicMock()
|
||||||
|
mock_response.read.return_value = b''
|
||||||
|
err_args = [None, 409, None, None, None]
|
||||||
|
mock_urlopen.side_effect = urllib2.HTTPError(*err_args)
|
||||||
|
|
||||||
|
with mock.patch('swift.common.internal_client.sleep') as mock_sleep, \
|
||||||
|
self.assertRaises(exceptions.ClientException) as caught:
|
||||||
|
internal_client.delete_object('http://127.0.0.1',
|
||||||
|
container='con', name='obj')
|
||||||
|
self.assertEqual(caught.exception.http_status, 409)
|
||||||
|
self.assertEqual(mock_sleep.call_count, 0)
|
||||||
|
self.assertEqual(mock_urlopen.call_count, 1)
|
||||||
|
|
||||||
def test_proxy(self):
|
def test_proxy(self):
|
||||||
# check that proxy arg is passed through to the urllib Request
|
# check that proxy arg is passed through to the urllib Request
|
||||||
scheme = 'http'
|
scheme = 'http'
|
||||||
|
|
|
@ -909,6 +909,24 @@ class TestContainerSync(unittest.TestCase):
|
||||||
self.assertEqual(cs.container_deletes, 2)
|
self.assertEqual(cs.container_deletes, 2)
|
||||||
self.assertEqual(len(exc), 3)
|
self.assertEqual(len(exc), 3)
|
||||||
self.assertEqual(str(exc[-1]), 'test client exception: 404')
|
self.assertEqual(str(exc[-1]), 'test client exception: 404')
|
||||||
|
|
||||||
|
def fake_delete_object(*args, **kwargs):
|
||||||
|
exc.append(ClientException('test client exception',
|
||||||
|
http_status=409))
|
||||||
|
raise exc[-1]
|
||||||
|
|
||||||
|
sync.delete_object = fake_delete_object
|
||||||
|
# Success because our tombstone is out of date
|
||||||
|
self.assertTrue(cs.container_sync_row(
|
||||||
|
{'deleted': True,
|
||||||
|
'name': 'object',
|
||||||
|
'created_at': '1.2'}, 'http://sync/to/path',
|
||||||
|
'key', FakeContainerBroker('broker'),
|
||||||
|
{'account': 'a', 'container': 'c', 'storage_policy_index': 0},
|
||||||
|
realm, realm_key))
|
||||||
|
self.assertEqual(cs.container_deletes, 3)
|
||||||
|
self.assertEqual(len(exc), 4)
|
||||||
|
self.assertEqual(str(exc[-1]), 'test client exception: 409')
|
||||||
finally:
|
finally:
|
||||||
sync.uuid = orig_uuid
|
sync.uuid = orig_uuid
|
||||||
sync.delete_object = orig_delete_object
|
sync.delete_object = orig_delete_object
|
||||||
|
|
Loading…
Reference in New Issue