Agregada integracion a cache de recordings

Fue un leseo la parte de recordings_of_release, pero ya esta esa parte

Me faltan un par de recordings no mas :3
This commit is contained in:
Daniel Cortes
2020-06-10 04:06:04 -04:00
parent 65c77c679f
commit 2a639f557f
3 changed files with 97 additions and 33 deletions

View File

@@ -62,6 +62,37 @@ def load_release_group_cover_art(release_group):
_log.info('Cover art de release group %s almacenado en cache', mbid)
@django_rq.job
def load_entities_of_recording(recording):
"""Carga en cache una recording y sus releases
Este difiere del resto e intenta obtener su padre, release, porque cargar recording como tal
no da tanto valor como hacer lo contrario, se aprovecha mejor las requests usadas
"""
mbid = recording
if isinstance(recording, dict):
mbid = recording.get('id')
with get_redis_connection() as redis:
if f'recording:{mbid}' not in redis:
# La única forma de agregar en cache una recording es a través de su release
# por lo que si ya esta guardada, su release lo estará
return
offset = 0
while True:
releases = mb.browse_releases({'recording': mbid},
includes=['recordings', 'artists'],
limit=100, offset=offset)
for release in releases:
load_entities_of_release.delay(release.get('id'))
offset += 100
if offset > releases.get('release-count'):
break
@django_rq.job
def load_entities_of_release(release):
"""Carga en cache una release y sus entidades relacionadas"""
@@ -94,6 +125,7 @@ def load_entities_of_release(release):
# o menos me lo voy a saltar, lo único que interesa de la track es su orden dentro de su
# media
medias = release.get('media', [])
redis.set(f'release:{mbid}:media:count', len(medias))
for raw_media in medias:
media = {
'format': raw_media.get('format'),
@@ -102,11 +134,12 @@ def load_entities_of_release(release):
}
redis.zadd(f'release:{mbid}:media', {json.dumps(media): media['position']})
for track in raw_media.get('tracks', []):
recording_key = f'release:{mbid}:{media.get("position")}:recordings'
recording_key = f'release:{mbid}:media:{media.get("position")}:recordings'
recording = track.get('recording')
redis.zadd(recording_key, {recording.get('id'): track.get("position")})
redis.set(f'recording:{mbid}', json.dumps(recording))
redis.set(f'recording:{mbid}:release', mbid)
recording_id = recording.get('id')
redis.zadd(recording_key, {recording_id: track.get("position")})
redis.set(f'recording:{recording_id}', json.dumps(recording))
redis.set(f'recording:{recording_id}:release', mbid)
@django_rq.job

View File

@@ -120,6 +120,18 @@ def map_release(mb_release, cover_art=None):
}
def map_media(mb_media):
"""Transforma una instancia de media dentro de una release a una util para mis propósitos"""
media = {
'format': mb_media.get('format'),
'position': mb_media.get('position'),
'track_count': mb_media.get('track_count'),
'recordings': [track.get('recording') for track in mb_media.get('tracks')]
}
return media
def map_recording(mb_recording):
"""Mapea el modelo de recording entregado por musicbrainz a uno propio"""
return {
@@ -341,32 +353,58 @@ def get_artist_of_release(mbid, limit, page):
def get_recording(mbid):
"""Obtiene una grabación incluyendo a su artista"""
mb_recording = mb.get_recording_by_mbid(mbid)
if mb_recording is None:
mb_recording = mb.get_recording_by_mbid(mbid)
else:
mb_recording = json.loads(mb_recording)
if 'error' in mb_recording:
return mb_recording
"""Obtiene una grabación"""
recording = map_recording(mb_recording)
with get_redis_connection() as redis:
mb_recording = redis.get(f'recording:{mbid}')
if mb_recording is None:
mb_recording = mb.get_recording_by_mbid(mbid)
else:
mb_recording = json.loads(mb_recording)
return recording
if 'error' in mb_recording:
return mb_recording
jobs.load_entities_of_recording.delay(mbid)
return map_recording(mb_recording)
def get_recordings_of_release(mbid, limit, page):
"""Obtiene las grabaciones de una release incluyendo los creditos a su artista"""
mb_recordings = mb.browse_recordings(params={'release': mbid}, includes=['artist-credits'],
limit=limit, offset=limit * (page - 1))
def get_recordings_of_release(mbid):
"""Obtiene las grabaciones de una release
if 'error' in mb_recordings:
return mb_recordings
Realmente no existen grabaciones para este caso de uso, si no, media, el cual representa
los medios físicos en los que esta una grabación, asi que se entrega una lista de medias con sus
grabaciones acopladas, todo ordenado y con indexes de orden
"""
return {
'paginate': paginate(mb_recordings.get('recording_count', 0), limit, page),
'recordings': [map_recording(recording) for recording in mb_recordings['recordings']]
}
medias = []
with get_redis_connection() as redis:
medias_key = f'release:{mbid}:media'
count = redis.get(f'{medias_key}:count')
if count and redis.zcard(medias_key) == int(count):
medias = [json.loads(media) for media in redis.zrange(medias_key, 0, -1)]
for media in medias:
recordings_key = f'{medias_key}:{media.get("position")}:recordings'
recordings_id = redis.zrange(recordings_key, 0, -1)
media['recordings'] = []
for recording_id in recordings_id:
media['recordings'].append(json.loads(redis.get(f'recording:{recording_id}')))
if len(medias) == 0:
# Si es que no habían medias cargadas en cache, puede ser que la release nunca se alla
# cargado.
jobs.load_entities_of_release.delay(mbid)
mb_release = mb.get_release_by_mbid(mbid, ['recordings'])
if 'error' in mb_release:
return mb_release
medias = [map_media(media) for media in mb_release.get('media', [])]
return {'medias': medias}
def get_release_of_recording(mbid, limit, page):

View File

@@ -152,15 +152,8 @@ def search_recording(request):
@api_view(['GET'])
def get_recordings_of_release(request, mbid):
""" Obtiene las recordings de una release dada su mbid
Como los datos son paginables la query puede contener per_page y page para definir cuantos
elementos mostrar por pagina y que pagina mostrar.
"""
limit = int(request.GET.get('per_page', 100))
page = int(request.GET.get('page', 1))
return Response(medium.get_recordings_of_release(mbid, limit, page))
""" Obtiene las recordings de una release dada su mbid"""
return Response(medium.get_recordings_of_release(mbid))
@api_view(['GET'])