"""Logic for retrieving top metrics.""" import json from typing import Any, Mapping from ddtrace import tracer from analytics.constants import cache from analytics.constants.ordering import ORDER_DIRECTIONS from analytics.constants.store import TIKTOK_STORE_ID from analytics.queries.format import format_row from analytics.queries.top_sound_recording_families import ( TopSoundRecordingFamiliesByIds, TopSoundRecordingFamilyIds, ) from analytics.schemas.top_sound_recording_families import ( TopSoundRecordingFamiliesSchema, ) from analytics.schemas.top_sound_recording_families_ids import ( TopSoundRecordingFamiliesIdsSchema, ) from analytics.utils import store_availability from analytics.utils.cache import cache_in_redis def _construct_item_with_top5_tiktok_scores(item, countries_set): """Parse arrays, construct an object, clean up an item.""" top_5_tiktok_scores_raw = item.get("top_5_tiktok_scores") or "{}" top_5_tiktok_score_countries_raw = item.get("top_5_tiktok_score_countries") or "{}" top_5_tiktok_scores = json.loads(top_5_tiktok_scores_raw) top_5_tiktok_score_countries = json.loads(top_5_tiktok_score_countries_raw) related_isrcs = json.loads(item.get("related_isrcs")) if related_isrcs: item["related_isrcs"] = related_isrcs if top_5_tiktok_scores and top_5_tiktok_score_countries: top5_tiktok_scores_by_country = [ {"country": country, "score": score} for country, score in zip(top_5_tiktok_score_countries, top_5_tiktok_scores) if country in countries_set or not countries_set ] item["top_5_tiktok_scores"] = top5_tiktok_scores_by_country else: top5_tiktok_scores_by_country = None item["top5_tiktok_scores_by_country"] = top5_tiktok_scores_by_country try: item.pop("top_5_tiktok_scores") item.pop("top_5_tiktok_score_countries") except KeyError: pass return item def _get_top_sound_recording_families_table_name( query_params: Mapping[str, Any] ) -> str: """Get the table name for top metrics.""" country_ids = query_params.get("country_ids", []) global_participant_ids = query_params.get("global_participant_ids", []) if global_participant_ids: if country_ids: return ( # TODO: replace with V2 "V_METRICS_BY_TRACK_PARTICIPANT_COUNTRY_FEED_DISTRIBUTOR_PRODFAM_ROLLUP" ) else: if country_ids: return "V_METRICS_BY_TRACK_COUNTRY_FEED_DISTRIBUTOR_PRODFAM_ROLLUP_V2" elif not country_ids: return "METRICS_BY_TRACK_FEED_DISTRIBUTOR_PRODFAM_ROLLUP_V2" @tracer.wrap(name="get_sound_recording_families") @cache_in_redis(ttl=cache.ONE_DAY) def get_top_sound_recording_families_ids( query_params: Mapping[str, Any], permissions: Mapping[str, Any], ): """Get the top sound recording family ids for financial label. Returns: tuple: list of top sound recording family ids, total number of results """ items = [] total_results = 0 store_ids = store_availability.get_query_store_ids( query_params.get("store_ids", []) ) if not store_ids: return TopSoundRecordingFamiliesIdsSchema.normalized_response( {"items": items, "total_results": total_results} ) store_ids.append(TIKTOK_STORE_ID) query_params["store_ids"] = store_ids if query_params["order_dir"].upper() not in ORDER_DIRECTIONS: raise Exception("Invalid order_dir value") query_params["table_name"] = _get_top_sound_recording_families_table_name( query_params ) query = TopSoundRecordingFamilyIds({**query_params, **permissions}) result = [format_row(data_point) for data_point in query.execute()] if not result: pass else: items = result total_results = result[0].get("total_results") return TopSoundRecordingFamiliesIdsSchema.normalized_response( {"items": items, "total_results": total_results} ) @tracer.wrap(name="get_sound_recording_families") @cache_in_redis(ttl=cache.ONE_DAY) def get_top_sound_recording_families_by_ids( query_params: Mapping[str, Any], permissions: Mapping[str, Any], ): """Get the top sound recording families for financial label. Returns: tuple: list of top sound recording families, total number of results """ items = [] total_results = 0 store_ids = store_availability.get_query_store_ids( query_params.get("store_ids", []) ) if not store_ids or not query_params["prod_fam_ids"]: return TopSoundRecordingFamiliesSchema.normalized_response( {"items": items, "total_results": total_results} ) store_ids.append(TIKTOK_STORE_ID) query_params["store_ids"] = store_ids if query_params["order_dir"].upper() not in ORDER_DIRECTIONS: raise Exception("Invalid order_dir value") query_params["table_name"] = _get_top_sound_recording_families_table_name( query_params ) query = TopSoundRecordingFamiliesByIds({**query_params, **permissions}) result = [format_row(data_point) for data_point in query.execute()] if not result: pass else: total_results = result[0]["total_results"] countries_set = set( query_params.get("country_ids", []) ) # optimization for performance items = [ _construct_item_with_top5_tiktok_scores(row, countries_set) for row in result ] return TopSoundRecordingFamiliesSchema.normalized_response( {"items": items, "total_results": total_results} )