Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Commit 2ee2d28

Browse files
committed
Merge pull request #600 from johanneswuerbach/retry-s3
Add read retries to avoid problems related to s3 eventual consistency
2 parents 6af878c + c4da4c2 commit 2ee2d28

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

docker_registry/drivers/s3.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
gevent.monkey.patch_all()
1212

1313
import docker_registry.core.boto as coreboto
14-
# from docker_registry.core import exceptions
1514
from docker_registry.core import compat
15+
from docker_registry.core import exceptions
1616
from docker_registry.core import lru
1717

1818
import logging
@@ -146,3 +146,13 @@ def content_redirect_url(self, path):
146146

147147
# Have cloudfront? Sign it
148148
return self.signer(path, expire_time=60)
149+
150+
def get_content(self, path, tries=0):
151+
try:
152+
return super(Storage, self).get_content(path)
153+
except exceptions.FileNotFoundError as e:
154+
if tries <= 3:
155+
time.sleep(.1)
156+
return self.get_content(path, tries + 1)
157+
else:
158+
raise e

tests/test_s3.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import StringIO
44
import sys
5+
import time
56

67
from nose import tools
78

@@ -137,3 +138,38 @@ def test_get_tags(self):
137138

138139
tag_content = store.get_content(tag_path)
139140
assert tag_content == 'randomdata'
141+
142+
def test_consistency_latency(self):
143+
self.testCount = -1
144+
mockKey = mock_boto.Key()
145+
146+
def mockExists():
147+
self.testCount += 1
148+
return self.testCount == 1
149+
mockKey.exists = mockExists
150+
mockKey.get_contents_as_string = lambda: "Foo bar"
151+
self._storage.makeKey = lambda x: mockKey
152+
startTime = time.time()
153+
154+
content = self._storage.get_content("/FOO")
155+
156+
waitTime = time.time() - startTime
157+
assert waitTime >= 0.1, ("Waiting time was less than %sms "
158+
"(actual : %sms)" %
159+
(0.1 * 1000, waitTime * 1000))
160+
assert content == "Foo bar", ("expected : %s; actual: %s" %
161+
("Foo bar", content))
162+
163+
@tools.raises(exceptions.FileNotFoundError)
164+
def test_too_many_read_retries(self):
165+
self.testCount = -1
166+
mockKey = mock_boto.Key()
167+
168+
def mockExists():
169+
self.testCount += 1
170+
return self.testCount == 5
171+
mockKey.exists = mockExists
172+
mockKey.get_contents_as_string = lambda: "Foo bar"
173+
self._storage.makeKey = lambda x: mockKey
174+
175+
self._storage.get_content("/FOO")

0 commit comments

Comments
 (0)