import asyncio from itertools import zip_longest from typing import Dict, Iterable, List, Optional from server.client import services from server.constants import DSP, DSP_SPOTIFY_APPLE_AMAZON from server.utils.parallel import get_awaitable_or_default from server.utils.playlists.playlists_search import ElasticsearchQuery, get_dsp_elasticsearch_response, get_items_size async def get_dsp_elasticsearch_playlists_search( dsp: DSP, query: str, image_size: Optional[int] = None, items_size: int = 30 ) -> Iterable[Dict]: """ Get playlists search data for provided DSP from elasticsearch and convert it to common response format Args: dsp (DSP): DSP.APPLE or DSP.SPOTIFY query (str): searched string to be used in an elasticsearch query image_size (int): Track image height/width value. items_size (int): default count of items returned from elasticsearch Returns: List[Dict] """ result = [] items_size = get_items_size(items_size, dsp) elasticsearch_body_query = ElasticsearchQuery( dsp=dsp, query=query, items_size=items_size ).get_playlists_search_body_query() data = await services.elasticsearch.search(dsp=dsp, body=elasticsearch_body_query) if data: result = await get_dsp_elasticsearch_response(dsp=dsp, data=data, image_size=image_size, items_size=items_size) return result async def get_playlists_search(vendors: List[str], query: str, image_size: int, items_size: int) -> List[Dict]: """ Get playlists search data for provided DSP from elasticsearch and convert it to common response format Args: vendors (List[str]): ["apple", "amazon", spotify] to search data for query (str): searched string to be used in an elasticsearch query image_size (int): Track image height/width value. items_size (int): default count of items returned from elasticsearch Returns: List[Dict] """ # By sorting available_vendors.sort(reverse=True) we guarantee that tasks will be created # for ["spotify", "apple", "amazon"] order! available_vendors = DSP_SPOTIFY_APPLE_AMAZON.values() available_vendors.sort(reverse=True) tasks = [ get_awaitable_or_default( f=get_dsp_elasticsearch_playlists_search, condition=dsp in vendors, default=[], dsp=DSP(dsp), query=query, items_size=items_size, image_size=image_size, ) for dsp in available_vendors ] spotify_hits, apple_hits, amazon_hits = await asyncio.gather(*tasks) result = [] for spotify_item, apple_item, amazon_item in zip_longest(spotify_hits, apple_hits, amazon_hits): if spotify_item: result.append(spotify_item) if apple_item: result.append(apple_item) if amazon_item: result.append(amazon_item) return result[:items_size]