from ...base import BaseStep from ...mixins import ESMixin, PGMixin, SnowflakeMixin from ...search.constants import ARTIST_SEARCH_INDEX_NAME from ...utils import Cleanup from ..constants import OK_STATUS, VALIDATION_ARTIST_TIKTOK_VIDEO __all__ = ["Validation"] class Validation(SnowflakeMixin, ESMixin, PGMixin, BaseStep): depends_on = {Cleanup} base_index_name: str = ARTIST_SEARCH_INDEX_NAME @property def index_name(self) -> str: return f"{self.base_index_name}_{self.timestamp}" def _get_tiktok_artist_ids_es(self) -> list: artist_ids_es: list = [] body = { "query": {"bool": {"must": {"exists": {"field": "tiktok"}}}}, "_source": False, } res_es, _scroll_id = self.es_client.search(index=self.index_name, body=body) if res_es: artist_ids_es = artist_ids_es + [i["_id"] for i in res_es] while len(res_es): res_es, _scroll_id = self.es_client.scroll(scroll_id=_scroll_id) if res_es: artist_ids_es = artist_ids_es + [i["_id"] for i in res_es] return artist_ids_es def _get_tiktok_artist_ids_pg_aggregates(self) -> list: artist_ids_pg = [] query = """ select atv.id as id from dna.artist_tiktok_videos as atv """ res_pg = self.execute_select_query(query=query) if res_pg: artist_ids_pg = [i["id"] for i in res_pg] return artist_ids_pg def _check_number_video_values(self): """ Number of tiktok videos for artist should be not more then 6 """ query = """ select * from ( select *, jsonb_array_length(value) as value_array_length from dna.artist_tiktok_videos atv ) as basic_data where basic_data.value_array_length = 0 or basic_data.value_array_length > 6 or basic_data.value is null """ status = OK_STATUS res = self.execute_select_query(query=query) if res: status = VALIDATION_ARTIST_TIKTOK_VIDEO["correct_number_video_values"] artist_ids = [i["id"] for i in res] status = status + ":" + ",".join([str(x) for x in artist_ids]) return status def _check_artists_pg_only(self, artist_ids_pg: list, artist_ids_es: list): """ Check if artists that exist only in PG aggregates have some tiktok data (chart data etc) Case when artists don't have tiktok accounts, but they tracks are in tiktok """ status = OK_STATUS if artist_ids_pg and artist_ids_es: artists_pg_only = set(artist_ids_pg) - set(artist_ids_es) if len(artists_pg_only) > 0: self.logger.info(f"Artists tiktok videos only in PG aggregates: {len(artists_pg_only)}") else: return status str_artists_pg_only = ",".join([str(x) for x in artists_pg_only]) query = f""" SELECT DISTINCT T_NON_SIGNED_ARTIST.ID AS ID FROM DNA.DNA_PUBLIC.T_NON_SIGNED_ARTIST AS T_NON_SIGNED_ARTIST JOIN DELPHI_EXPLORATION.CHARTMETRIC.V_TIKTOK_USER AS V_TIKTOK_USER ON T_NON_SIGNED_ARTIST.TT = V_TIKTOK_USER.USER_ID AND T_NON_SIGNED_ARTIST.TT IS NOT NULL JOIN DELPHI_EXPLORATION.CHARTMETRIC.V_TIKTOK_USER_STAT AS V_TIKTOK_USER_STAT ON V_TIKTOK_USER_STAT.TIKTOK_USER = V_TIKTOK_USER.ID WHERE T_NON_SIGNED_ARTIST.ID IN ({str_artists_pg_only}) """ res = self.run_raw_query(query=query, is_async=False) if res: status = VALIDATION_ARTIST_TIKTOK_VIDEO["missed_artist_tiktok_data"] status = status + ": " + ",".join([str(x) for x in res]) return status def _check_artists_es_only(self, artist_ids_pg: list, artist_ids_es: list): """ Case when we have artist tiktok data, but don't have any data about tiktok video """ status = OK_STATUS if artist_ids_pg and artist_ids_es: artists_es_only = set(artist_ids_es) - set(artist_ids_pg) if len(artists_es_only) > 0: self.logger.info(f"Artists tiktok only in ES index: {len(artists_es_only)}") else: return status str_artists_pg_only = ",".join([str(x) for x in artists_es_only]) query = f""" SELECT DISTINCT T_NON_SIGNED_ARTIST.ID AS ID FROM DNA.DNA_PUBLIC.T_NON_SIGNED_ARTIST AS T_NON_SIGNED_ARTIST JOIN DELPHI_EXPLORATION.CHARTMETRIC.V_TIKTOK_VIDEO AS V_TIKTOK_VIDEO ON V_TIKTOK_VIDEO.USER_ID = T_NON_SIGNED_ARTIST.TT AND T_NON_SIGNED_ARTIST.TT IS NOT NULL JOIN DELPHI_EXPLORATION.CHARTMETRIC.V_TIKTOK_TOP_VIDEOS_STAT AS V_TIKTOK_TOP_VIDEOS_STAT ON V_TIKTOK_VIDEO.ID = V_TIKTOK_TOP_VIDEOS_STAT.TIKTOK_VIDEO WHERE T_NON_SIGNED_ARTIST.ID IN ({str_artists_pg_only}) """ res = self.run_raw_query(query=query, is_async=False) if res: status = VALIDATION_ARTIST_TIKTOK_VIDEO["missed_tiktok_video_data_for_artist"] status = status + ": " + ",".join([str(x) for x in res]) return status def process(self): artist_ids_pg = self._get_tiktok_artist_ids_pg_aggregates() artist_ids_es = self._get_tiktok_artist_ids_es() result = { "correct_number_video_values": self._check_number_video_values(), "missed_artist_tiktok_data": self._check_artists_pg_only(artist_ids_pg, artist_ids_es), "missed_tiktok_video_data_for_artist": self._check_artists_es_only(artist_ids_pg, artist_ids_es), } if all(x == OK_STATUS for x in result.values()): self.logger.info(result) else: self.logger.error(result) return result