api_views: use loop to prevent NFS errors on GET (#41379)
File can disapear more frequently on NFS as open() is not atomic (NFS filehandle refers to an inode but they don't lock it like an open file descriptor).
This commit is contained in:
parent
9a2c6b23ed
commit
7b292a2c17
|
@ -21,8 +21,11 @@ try:
|
|||
from functools import reduce
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
import requests
|
||||
try:
|
||||
from time import process_time
|
||||
except ImportError:
|
||||
from time import clock as process_time
|
||||
|
||||
from django.utils.six.moves.urllib import parse as urlparse
|
||||
|
||||
|
@ -180,30 +183,32 @@ class PetalAPIView(APIView):
|
|||
|
||||
@logit
|
||||
def get(self, request, partner_name, cut_uuid, petal_name):
|
||||
logger = logging.getLogger(__name__)
|
||||
if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
|
||||
if_none_match = if_none_match and [x.strip() for x in if_none_match.split(',')]
|
||||
|
||||
petal = self.get_petal(partner_name, cut_uuid, petal_name)
|
||||
if if_none_match:
|
||||
if if_none_match == ['*'] or petal.etag in if_none_match:
|
||||
return Response(
|
||||
status=status.HTTP_304_NOT_MODIFIED,
|
||||
headers={
|
||||
'ETag': petal.etag
|
||||
}
|
||||
)
|
||||
# verify file exists before creating a StreamingHttpResponse
|
||||
# as StreamingHttpResponse generate its content after the Django global try/catch
|
||||
try:
|
||||
petal.data.open()
|
||||
except IOError as e:
|
||||
logger.error('file not found "%s": %s', petal.data.path, e)
|
||||
return HttpResponse('missing file', status=500)
|
||||
response = StreamingHttpResponse(
|
||||
petal.data.chunks(),
|
||||
content_type=petal.content_type,
|
||||
)
|
||||
start = process_time()
|
||||
while process_time() - start < 10:
|
||||
petal = self.get_petal(partner_name, cut_uuid, petal_name)
|
||||
if if_none_match:
|
||||
if if_none_match == ['*'] or petal.etag in if_none_match:
|
||||
return Response(
|
||||
status=status.HTTP_304_NOT_MODIFIED,
|
||||
headers={
|
||||
'ETag': petal.etag
|
||||
}
|
||||
)
|
||||
# verify file exists before creating a StreamingHttpResponse
|
||||
# as StreamingHttpResponse generate its content after the Django global try/catch
|
||||
try:
|
||||
petal.data.open(mode='rb')
|
||||
response = HttpResponse(petal.data.read(), content_type=petal.content_type)
|
||||
except IOError:
|
||||
continue
|
||||
finally:
|
||||
petal.data.close()
|
||||
break
|
||||
else:
|
||||
return HttpResponse(status=500, reason='Too many updates')
|
||||
response['ETag'] = petal.etag
|
||||
return response
|
||||
|
||||
|
|
Loading…
Reference in New Issue