from typing import List, Optional, Dict, Tuple from aiohttp import ClientError, ClientConnectorError, ServerTimeoutError from utils.async_helpers import safe_gather from global_search.constants import MAX_ARTISTS_COUNT from external_api.base.clients.client import ApiUnavailable from global_search.repositories.global_search_repository import GlobalSearchRepository from shared.schemas import ArtistSchema from services.recent_search.schemas import ArtistSearchSchema, Image from utils.exceptions import BadGateway from global_search.providers.abstract_search_provider import AbstractSearchProvider from utils.test_helpers import sync from artists.services.artists_service import ArtistsService class ArtistsSearchProvider(AbstractSearchProvider): artists_service: ArtistsService = ArtistsService() repository = GlobalSearchRepository() @sync async def search(self) -> Optional[Tuple[List[ArtistSearchSchema], int]]: try: tasks = [ self.artists_service.get_artists_by_name(self.query, self.limit, self.offset), self.artists_service.get_artists_by_name_count(self.query, MAX_ARTISTS_COUNT), ] responses = await safe_gather(tasks, []) artists_models = responses[0] count = responses[1] artists_ids = [artist.id for artist in artists_models] projects_counts_dict = self.__get_projects_count_by_artists(artists_ids) artists = [self.__map_artist_to_schema(artist, projects_counts_dict) for artist in artists_models] return artists, count except (ClientError, ClientConnectorError, ServerTimeoutError, BadGateway, ApiUnavailable): return None def __get_projects_count_by_artists(self, artists_ids) -> Dict: projects_counts_data = self.repository.projects_count_by_artists(artists_ids) projects_counts_dict = {} for artist_id, proj_count in projects_counts_data: projects_counts_dict[artist_id] = proj_count return projects_counts_dict def __map_artist_to_schema(self, artist: ArtistSchema, counts_dict: Dict): schema = ArtistSearchSchema( id=artist.id, name=artist.name, projectsCount=counts_dict.get(artist.id, 0), isUnknown=artist.isUnknown ) if artist.image: schema.image = Image(url=artist.image.url, width=artist.image.width, height=artist.image.height) schema.isSony = artist.isSony return schema