Google рдХреНрд▓рд╛рдЙрдб рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╢реЗрдбреНрдпреВрд▓ рдкрд░ рдмрд┐рдЧрдореИрдХреНрд╕ рд╕реЗ рд╢реЗрдбреНрдпреВрд▓ рдХреЙрд▓ рд░рд┐рдкреЛрд░реНрдЯреНрд╕ рдХреЛ рдХреЛрдЗрдПрдордХреНрдпреВ рд╕реЗ рдЖрдпрд╛рдд рдХрд░реЗрдВ

рдХрд┐рд╕ рд▓рд┐рдП


рд╡рд┐рдЬреНрдЮрд╛рдкрди рдЕрднрд┐рдпрд╛рдиреЛрдВ рдХреА рдЬрдЯрд┐рд▓ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХреЙрд▓ рдХреЗ рд╕рд╛рде, рдЗрдирдХрдорд┐рдВрдЧ рдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рднрдВрдбрд╛рд░рдг, рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдЙрдкрдХрд░рдг рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдЕрдХреНрд╕рд░ рдЖрдкрдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдбреЗрдЯрд╛ рддрдХ рддреНрд╡рд░рд┐рдд рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдХрднреА-рдХрднреА рдЖрдкрдХреЛ рдЬрдЯрд┐рд▓ рдбреЗрдЯрд╛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЪреИрдирд▓ рдпрд╛ рдЕрднрд┐рдпрд╛рди рдХреЗ рд▓рд┐рдП рд╕рд╣рд╕рдВрдмрдВрдзреА рдХреЙрд▓ред

рдХрд╛рдо рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ, рдЬреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдн рднреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, CoMagic рд╕реЗ Google BigQuery рдХреЛ рдХреЙрд▓ рдЖрдпрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реИред рдмрд╣реБрдд рдЕрдзрд┐рдХ BigQuery рдХреЗ рд▓рд╛рднреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЪрд▓рд┐рдП рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред

рдПрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЖрдпрд╛рдд рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

  1. Google рдЦрд╛рддрд╛ (рдпрджрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рдирд╣реАрдВ рд╣реИ) рдирд┐рд░реНрдорд┐рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде
  2. рдЕрдЬрдЧрд░ рдЬреНрдЮрд╛рди
  3. рдкреЗрд╢ рд╣реИ рдЧреВрдЧрд▓ рдХреНрд▓рд╛рдЙрдб рдбреЙрдХреНрдпреВрдореЗрдВрдЯреЗрд╢рди

рдХреИрд╕реЗ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдБ рд╡рд░реНрдгрд┐рдд рд╣реИ ред рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ BigQuery рдореЗрдВ рдПрдХ рдбреЗрдЯрд╛рд╕реЗрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдмреАрдХреНрдпреВ рдкреНрд░рд▓реЗрдЦрди рдФрд░ рдбреЗрдЯрд╛рд╕реЗрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ ред

CoMagic рд╕реЗ рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛


CoMagic рдкреНрд░рд▓реЗрдЦрди рдХреА рдУрд░ рдореБрдбрд╝рддреЗ рд╣реБрдПред рдХреЙрд▓ рдпрд╛ рдХреЙрд▓ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдЕрдиреБрднрд╛рдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рд╣рдо CoMagic рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВред GitHub рдХреЗ рд▓рд┐рдВрдХ рдореЗрдВ рдЕрдВрдд рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

import json import requests import random import pandas as pd class ComagicClient: """     CoMagic""" def __init__(self, login, password): """     CoMagic""" self.login = login self.password = password self.base_url = 'https://dataapi.comagic.ru/v2.0' self.payload_ = {"jsonrpc":"2.0", "id":1, "method":None, "params": None} self.token = self.get_token(self.login, self.password) def base_request(self, method, params): """     CoMagic.      API   .    JSON-like . : https://www.comagic.ru/support/api/data-api/""" id_ = random.randrange(10**7) #  payload = self.payload_.copy() payload["method"] = method payload["params"] = params payload["id"] = id_ self.r = requests.post(self.base_url, data=json.dumps(payload)) self.last_response = json.loads(self.r.text) return self.last_response def get_token(self, login, password): """   .       .  .""" method = "login.user" params = {"login":self.login, "password":self.password} response = self.base_request(method, params) token = response['result']['data']['access_token'] return token def get_report_per_page(self, method, params): """  .      10000 .    .     110000 .     JSON-like .""" response = self.base_request(method, params) print(f"""  c {params["date_from"]}  {params["date_till"]}.  = {params["offset"]}""") result = response['result']['data'] if len(result) < 10000: return result else: params['offset'] += 10000 add_result = self.get_report_per_page(method, params) return result + add_result def get_basic_report(self, method, fields, date_from, date_till, filter=None, offset=0): """   .       method  fields.       .       ,   ,       . method -- <string>   date_from -- <string>  .  "YYYY-MM-DD hh:mm:ss" date_till -- <string>  .  "YYYY-MM-DD hh:mm:ss" fields -- <list>,    filter [] - <dict>  offset [] -- <int>  return -- <list>  """ params = {"access_token":self.token, "limit":10000, "date_from":date_from, "date_till":date_till, "fields": fields, "offset": offset} if filter: params['filter'] = filter report = self.get_report_per_page(method, params) return report 

рдЕрдм рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдФрд░ рджреГрд╢реНрдпрдорд╛рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЗрд╕реЗ BigQuery рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред

рдПрдХ рд╕рд╣рд╛рдпрдХ рд╡рд░реНрдЧ рдмрдирд╛рдПрдВ рдФрд░ CoMagic рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВред

 class ComagicHandler(ComagicClient): """    ,   CoMagic""" time_partition_field = 'PARTITION_DATE' def __init__(self, login, password, first_call_date): self.day_before_first_call = pd.to_datetime(first_call_date) - pd.Timedelta(days=1) super().__init__(login, password) def get_calls_report(self, date_from, date_till): """        .           .    Pandas DataFrame.      .      Connector    .    .    .  Pnadas.DataFrame""" method = "get.calls_report" fields = ['id', 'visitor_id', 'person_id', 'start_time', 'finish_reason', 'is_lost', 'tags', 'campaign_name','communication_number', 'contact_phone_number', 'talk_duration', 'clean_talk_duration', 'virtual_phone_number', 'ua_client_id', 'ym_client_id', 'entrance_page', 'gclid', 'yclid', 'visitor_type', 'visits_count', 'visitor_first_campaign_name', 'visitor_device', 'site_domain_name','utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'eq_utm_source', 'eq_utm_medium', 'eq_utm_campaign', 'attributes'] #   CoMagic calls_data = self.get_basic_report(method, fields, date_from, date_till) # DataFrame df = pd.DataFrame(calls_data) #    .    . df[self.time_partition_field] = pd.to_datetime(df.start_time).apply(lambda x: x.date()) #  tags,   BigQuery       ,  # CoMagic.    . df['tags'] = df.tags.apply(lambda x: x if x == None else [i['tag_name'] for i in x]) return df 

BigQuery рдХреЛ рдбреЗрдЯрд╛ рднреЗрдЬрдирд╛


CoMagic рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдФрд░ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЗрд╕реЗ BigQuery рдХреЛ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

 from google.cloud import bigquery from google.cloud.exceptions import NotFound import pandas as pd class BQTableHanler: """     BigQuery""" time_partition_field = 'PARTITION_DATE' def __init__(self, full_table_id, service_account_file_key_path = None): """       `myproject.mydataset.mytable`.  ,   Application Default Credentials,           .""" self.full_table_id = full_table_id project_id, dataset_id, table_id = full_table_id.split(".") self.project_id = project_id self.dataset_id = dataset_id self.table_id = table_id if service_account_file_key_path: #      from google.oauth2 import service_account self.credentials = service_account.Credentials.from_service_account_file( service_account_file_key_path, scopes=["https://www.googleapis.com/auth/cloud-platform"],) self.bq_client = bigquery.Client(credentials = self.credentials, project = self.project_id) else: self.bq_client = bigquery.Client() self.dataset = self.bq_client.get_dataset(self.dataset_id) self.location = self.dataset.location self.table_ref = self.dataset.table(self.table_id) def get_last_update(self): """        Pandas datetime.      False.""" try: self.bq_client.get_table(self.full_table_id) except NotFound as error: return False query = f"""SELECT MAX({self.time_partition_field}) as last_call FROM `{self.full_table_id}`""" result = self.bq_client.query(query,location=self.location).to_dataframe() date = pd.to_datetime(result.iloc[0,0]).date() return date def insert_dataframe(self, dataframe): """      BigQuery.     Pandas DataFrame.    ,       .""" job_config = bigquery.LoadJobConfig() #     job_config._properties['load']['timePartitioning'] = {'type': 'DAY', 'field': self.time_partition_field} result = self.bq_client.load_table_from_dataframe(dataframe, self.table_ref, job_config=job_config).result() return result 

рдбреЗрдЯрд╛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░реЗрдВ


рдЪреВрдВрдХрд┐ CoMagic рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рдПрдХ рд╕реАрдорд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдиреБрд░реЛрдзрд┐рдд рдбреЗрдЯрд╛ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдо рдЕрдиреБрд░реЛрдз рдЕрд╡рдзрд┐ рдХреЛ рд╕реАрдорд┐рдд рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдмрдбрд╝реА рдЕрд╡рдзрд┐ рдХреЛ рдПрдХ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд▓рдВрдмрд╛рдИ рдХреЗ рдЦрдВрдбреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдЧрд╛ред

 def interval_split(array, interval): """      .   ,      2,    -   ,     -    . : get_intervals([1,2,3,4,5,6,7], 3) => [[1,3], [4,6], [7]] get_intervals([1,2,3], 4) => [[1,3]]""" intervals = [] iw, i = 0, 0 l = len(array) for v in array: if i==0 or (i)%interval==0: intervals.append([v]) if (i+1)%interval == 0 or (i+1) == l: intervals[iw].append(v) iw+=1 i+=1 return intervals 

рдкрд╣рд▓реА рдмрд╛рд░ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рддреЗ рд╕рдордп рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬрдм рдЖрдкрдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЕрд╡рдзрд┐ рдХреЛ рдХрдИ рдЫреЛрдЯреЗ рдЕрд╡рдзрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡реИрд╕реЗ, рдХреНрд▓рд╛рдЙрдб рдлрдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдРрд╕рд╛ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ рд╕рдордп рд╕реАрдорд╛ рд╣реИред рдЦреИрд░, рдпрд╛, рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдХрдИ рдмрд╛рд░ рдлрд╝рдВрдХреНрд╢рди рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рдо BigQuery рдЯреЗрдмрд▓ рдХреЛ рд▓рд┐рдВрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдиреЗрдХреНрдЯрд░ рдХреНрд▓рд╛рд╕ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╣рдо рдбреЗрдЯрд╛ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдХреЛрдордЬрд┐рдХ рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

 from helpfunctions import interval_split import pandas as pd class Connector: """      """ time_partition_field = 'PARTITION_DATE' #  -.       def __init__ (self, source, dest): """          """ self.source = source self.dest = dest self.source.time_partition_field = self.time_partition_field self.dest.time_partition_field = self.time_partition_field def insert_data_in_dest(self, start_date, end_date): """      .          ,     .""" dates = pd.date_range(start_date, end_date) week_intervals = interval_split(dates, 7) #     7  for week_interval in week_intervals: date_from = week_interval[0].strftime("%Y-%m-%d") + " 00:00:00" date_till = week_interval[1].strftime("%Y-%m-%d") + " 23:59:59" calls_df = self.source.get_calls_report(date_from, date_till) self.dest.insert_dataframe(calls_df) print (f"  {date_from}  {date_till}   ") return True def update_dest_data(self): #     BigQuery last_date = self.dest.get_last_update() if not last_date: #    last_date = self.source.day_before_first_call yesterday = pd.Timestamp.today(tz='Europe/Moscow').date() - pd.Timedelta(days=1) if last_date == yesterday: print("  ") else: last_date = last_date + pd.Timedelta(days=1) self.insert_data_in_dest(last_date, yesterday) return True 

рдЕрдЧрд▓рд╛, рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рд╢реЗрдбреНрдпреВрд▓ рдкрд░ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

 from connector import Connector from bqhandler import BQTableHanler from comagichandler import ComagicHandler from credfile import * def main(event, context): """    event, context  : https://cloud.google.com/functions/docs/writing/background#functions-writing-background-hello-pubsub-python""" #import base64 #pubsub_message = base64.b64decode(event['data']).decode('utf-8') # c      comagic_handler = ComagicHandler(COMAGIC_LOGIN, COMAGIC_PASSWORD, FIRST_CALL_DATE) bq_handelr = BQTableHanler(full_table_id, google_credintials_key_path) #  connector = Connector(comagic_handler, bq_handelr) #     connector.update_dest_data() 

Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ


рд╣рдо рдПрдХ рдЬрд╝рд┐рдк рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕рднреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВред Credfile.py рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рд╣рдо рдЯреЛрдХрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП CoMagic рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА BigQuery рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдкреВрд░рд╛ рдирд╛рдо рдФрд░ рд╕реНрдерд╛рдиреАрдп рдорд╢реАрди рд╕реЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЙрдиреНрдЪ рд╣реЛрдиреЗ рдкрд░ рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрдеред

рдХреНрд▓рд╛рдЙрдб рдлрдВрдХреНрд╢рди рдмрдирд╛рдПрдВ


  • рдХрдВрд╕реЛрд▓ рдкрд░ рдЬрд╛рдПрдВ
  • рдпрджрд┐ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдЕрднреА рддрдХ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ "рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдБ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ
  • рдЯреНрд░рд┐рдЧрд░ рдлрд╝реАрд▓реНрдб рдореЗрдВ, PUB / SUB рдЪреБрдиреЗрдВ
  • PUB / SUB рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ рдереАрдо рдмрдирд╛рдПрдБред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 'update_calls'
  • рд╕реНрд░реЛрдд: рдЬрд╝рд┐рдк рдЕрдкрд▓реЛрдб (рд╕реНрдерд╛рдиреАрдп рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓)
  • рдкрд░реНрдпрд╛рд╡рд░рдг: рдкрд╛рдпрдерди 3.7
  • рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
  • рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬ рдХрд╛ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рд╕реЗрдЧрдореЗрдВрдЯ рдЪреБрдирдирд╛
  • рдХреНрд╖реЗрддреНрд░ рдореЗрдВ 'рдлрд╝рдВрдХреНрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ' рд╣рдо 'рдореБрдЦреНрдп' рд▓рд┐рдЦрддреЗ рд╣реИрдВ
  • рдЖрд╡рдВрдЯрд┐рдд рд╕реНрдореГрддрд┐: рд╡реИрдХрд▓реНрдкрд┐рдХ



рд╢реЗрдбреНрдпреВрд▓рд░ рдФрд░ PUB / SUB рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛


рдЕрдВрддрд┐рдо рдЪрд░рдг рдореЗрдВ, рд╣рдордиреЗ `update_calls` рдЯреНрд░рд┐рдЧрд░ рдмрдирд╛рдпрд╛ред рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╡рд┐рд╖рдп рд╡рд┐рд╖рдпреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рд╣реИред

рдЕрдм, рдХреНрд▓рд╛рдЙрдб рд╢реЗрдбреНрдпреВрд▓рд░ рдХреЗ рд╕рд╛рде рдЖрдкрдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬрдм рдЖрдЧ рд▓рдЧреЗрдЧреА рдФрд░ рдЬреАрд╕реАрдПрдл рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред

  • рдХрдВрд╕реЛрд▓ рдкрд░ рдЬрд╛рдПрдВ
  • CRON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЖрд╡реГрддреНрддрд┐ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ, рд╕реЗрдЯ рдХрд░реЗрдВ рдЬрдм рдЯреНрд░рд┐рдЧрд░ рдореЗрдВ рдЖрдЧ рд▓рдЧрдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдПред
  • рдЧрдВрддрд╡реНрдп: рдкрдм / рдЙрдк
  • рд╡рд┐рд╖рдп: рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рддреЗ рд╕рдордп рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА рдЧрдИ рд╡рд┐рд╖рдпрд╡рд╕реНрддреБ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ: "update_calls"
  • рдкреЗрд▓реЛрдбреНрд╕ * (рдкреЗрд▓реЛрдбреНрд╕) - рдпрд╣ рд╡рд╣ рд╕реВрдЪрдирд╛ рд╣реИ рдЬрд┐рд╕реЗ рдкрдм / рд╕рдм рдФрд░ рдореБрдЦреНрдп рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛



рдЕрдм рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреИрдирд┐рдХ 01:00 рдмрдЬреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдХреЙрд▓ рдбреЗрдЯрд╛ рдХреЛ рдкрд┐рдЫрд▓реЗ рджрд┐рди рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

GitHub рдХреЛ рд╕реНрдерд╛рдиреАрдп рдХрдВрдкреНрдпреВрдЯрд░ рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдХрд░реЗрдВ
GitHub рдЬрд┐рдк рдлрд╛рдЗрд▓ рдХрд╛ рд▓рд┐рдВрдХ

Source: https://habr.com/ru/post/hi475804/


All Articles