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

Commit a5c0ad7

Browse files
Pierre Chaussaletjohanneswuerbach
authored andcommitted
Add read retries to avoid problems related to s3 eventual consistency
Conflicts: tests/test_s3.py
1 parent 0f54d7b commit a5c0ad7

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,7 +11,7 @@
1111
gevent.monkey.patch_all()
1212

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

@@ -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, 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
@@ -3,10 +3,14 @@
33
import StringIO
44
import sys
55

6+
import time
7+
68
from nose import tools
79

810
from docker_registry.core import exceptions
911
import docker_registry.testing as testing
12+
import docker_registry.testing.mock_boto as mock_boto
13+
from docker_registry.drivers import s3
1014

1115
from docker_registry.testing import mock_boto # noqa
1216

@@ -137,3 +141,35 @@ def test_get_tags(self):
137141

138142
tag_content = store.get_content(tag_path)
139143
assert tag_content == 'randomdata'
144+
145+
def test_consistency_latency(self):
146+
self.testCount = -1
147+
mockKey = mock_boto.Key()
148+
def mockExists():
149+
self.testCount += 1
150+
return self.testCount == 1
151+
mockKey.exists = mockExists
152+
mockKey.get_contents_as_string = lambda: "Foo bar"
153+
storage = s3.Storage(self.path, self.config)
154+
storage.makeKey = lambda x: mockKey
155+
startTime = time.time()
156+
157+
content = storage.get_content("/FOO")
158+
159+
waitTime = time.time() - startTime
160+
assert waitTime >= 0.1, "Waiting time was less than %sms (actual : %sms)" % (0.1*1000, waitTime*1000)
161+
assert content == "Foo bar", "expected : %s; actual: %s" % ("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+
def mockExists():
168+
self.testCount += 1
169+
return self.testCount == 5
170+
mockKey.exists = mockExists
171+
mockKey.get_contents_as_string = lambda: "Foo bar"
172+
storage = s3.Storage(self.path, self.config)
173+
storage.makeKey = lambda x: mockKey
174+
175+
storage.get_content("/FOO")

0 commit comments

Comments
 (0)