Fix #163: Avoid downloading audio files multiple times from remote libraries

This commit is contained in:
Eliot Berriot 2018-04-19 21:19:40 +02:00
parent fc4f006858
commit ced851891d
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
2 changed files with 19 additions and 9 deletions

View File

@ -23,13 +23,14 @@ from rest_framework import permissions
from musicbrainzngs import ResponseError from musicbrainzngs import ResponseError
from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.common import utils as funkwhale_utils
from funkwhale_api.federation import actors
from funkwhale_api.requests.models import ImportRequest
from funkwhale_api.musicbrainz import api
from funkwhale_api.common.permissions import ( from funkwhale_api.common.permissions import (
ConditionalAuthentication, HasModelPermission) ConditionalAuthentication, HasModelPermission)
from taggit.models import Tag from taggit.models import Tag
from funkwhale_api.federation import actors
from funkwhale_api.federation.authentication import SignatureAuthentication from funkwhale_api.federation.authentication import SignatureAuthentication
from funkwhale_api.federation.models import LibraryTrack
from funkwhale_api.musicbrainz import api
from funkwhale_api.requests.models import ImportRequest
from . import filters from . import filters
from . import forms from . import forms
@ -195,12 +196,13 @@ class TrackFileViewSet(viewsets.ReadOnlyModelViewSet):
@detail_route(methods=['get']) @detail_route(methods=['get'])
def serve(self, request, *args, **kwargs): def serve(self, request, *args, **kwargs):
try: queryset = models.TrackFile.objects.select_related(
f = models.TrackFile.objects.select_related(
'library_track', 'library_track',
'track__album__artist', 'track__album__artist',
'track__artist', 'track__artist',
).get(pk=kwargs['pk']) )
try:
f = queryset.get(pk=kwargs['pk'])
except models.TrackFile.DoesNotExist: except models.TrackFile.DoesNotExist:
return Response(status=404) return Response(status=404)
@ -213,6 +215,13 @@ class TrackFileViewSet(viewsets.ReadOnlyModelViewSet):
if library_track and not audio_file: if library_track and not audio_file:
if not library_track.audio_file: if not library_track.audio_file:
# we need to populate from cache # we need to populate from cache
with transaction.atomic():
# why the transaction/select_for_update?
# this is because browsers may send multiple requests
# in a short time range, for partial content,
# thus resulting in multiple downloads from the remote
qs = LibraryTrack.objects.select_for_update()
library_track = qs.get(pk=library_track.pk)
library_track.download_audio() library_track.download_audio()
audio_file = library_track.audio_file audio_file = library_track.audio_file
mt = library_track.audio_mimetype mt = library_track.audio_mimetype

View File

@ -0,0 +1 @@
Avoid downloading audio files multiple times from remote libraries (#163)