From fcac3d7b23a7da41e29ad832820823b1fe896ac8 Mon Sep 17 00:00:00 2001 From: Y_SAKAI Date: Mon, 1 Aug 2022 19:28:15 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8C=87=E6=91=98=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=81=AE=E5=8F=8D=E6=98=A0=E3=80=81=E3=83=AD=E3=82=B0=E5=87=BA?= =?UTF-8?q?=E5=8A=9B=E3=81=AE=E5=BE=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/backup_crm_csv_data_process.py | 6 +-- ecs/crm-datafetch/src/config/objects.py | 12 ++--- ecs/crm-datafetch/src/controller.py | 10 ++-- ...convert_factory.py => convert_strategy.py} | 9 ++-- ecs/crm-datafetch/src/converter/converter.py | 2 +- ecs/crm-datafetch/src/error/exceptions.py | 2 +- .../src/fetch_crm_data_process.py | 54 +++++++------------ ecs/crm-datafetch/src/util/dict_checker.py | 6 ++- .../src/util/execute_datetime.py | 4 +- 9 files changed, 45 insertions(+), 60 deletions(-) rename ecs/crm-datafetch/src/converter/{convert_factory.py => convert_strategy.py} (83%) diff --git a/ecs/crm-datafetch/src/backup_crm_csv_data_process.py b/ecs/crm-datafetch/src/backup_crm_csv_data_process.py index d40c7a13..ba7bb8ea 100644 --- a/ecs/crm-datafetch/src/backup_crm_csv_data_process.py +++ b/ecs/crm-datafetch/src/backup_crm_csv_data_process.py @@ -6,12 +6,12 @@ from src.util.execute_datetime import ExecuteDateTime from src.util.logger import logger_instance as logger -def backup_crm_csv_data_process(target_object: TargetObject, exetute_datetime: ExecuteDateTime, csv_string: str): +def backup_crm_csv_data_process(target_object: TargetObject, execute_datetime: ExecuteDateTime, csv_string: str): """CSVバックアップ処理 Args: target_object (TargetObject): 取得対象オブジェクト情報インスタンス - exetute_datetime (ExecuteDateTime): 実行日次取得インスタンス + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス csv_string (str): csvデータ Raises: @@ -29,7 +29,7 @@ def backup_crm_csv_data_process(target_object: TargetObject, exetute_datetime: E # ② CRMバックアップ保管用バケットに、変換後のCSVデータのバックアップを保管する backup_bucket = BackupBucket() backup_bucket.put_csv( - f'{exetute_datetime.to_path()}/{upload_file_name}.csv', csv_string) + f'{execute_datetime.to_path()}/{upload_file_name}.csv', csv_string) logger.debug( f'D-CSVBK-02 [{target_object_name}] のCSVデータバックアップ 正常終了') diff --git a/ecs/crm-datafetch/src/config/objects.py b/ecs/crm-datafetch/src/config/objects.py index 3ac08851..3368a1db 100644 --- a/ecs/crm-datafetch/src/config/objects.py +++ b/ecs/crm-datafetch/src/config/objects.py @@ -94,22 +94,19 @@ class TargetObject(): def is_update_last_fetch_datetime(self) -> bool: if self.__dict_checker.check_key_exist(IS_UPDATE_LAST_FETCH_DATETIME_KEY): return self.__object_info[IS_UPDATE_LAST_FETCH_DATETIME_KEY] - else: - return False + return False @property def last_fetch_datetime_file_name(self) -> str: if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_FILE_NAME_KEY): return self.__object_info[LAST_FETCH_DATETIME_FILE_NAME_KEY] - else: - return f'{self.__object_info[OBJECT_NAME_KEY]}.json' + return f'{self.__object_info[OBJECT_NAME_KEY]}.json' @property def upload_file_name(self) -> str: if self.__dict_checker.check_key_exist(UPLOAD_FILE_NAME_KEY): return self.__object_info[UPLOAD_FILE_NAME_KEY].format(execute_datetime=self.__execute_datetime) - else: - return f'{self.__object_info[OBJECT_NAME_KEY]}_{self.__execute_datetime}' + return f'{self.__object_info[OBJECT_NAME_KEY]}_{self.__execute_datetime}' @property def datetime_column(self) -> str: @@ -138,5 +135,4 @@ class LastFetchDatetime(): def last_fetch_datetime_to(self) -> str: if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_TO_KEY): return self.__last_fetch_datetime_file_dict[LAST_FETCH_DATETIME_TO_KEY] - else: - return self.__execute_datetime + return self.__execute_datetime diff --git a/ecs/crm-datafetch/src/controller.py b/ecs/crm-datafetch/src/controller.py index 3c92277b..c531f113 100644 --- a/ecs/crm-datafetch/src/controller.py +++ b/ecs/crm-datafetch/src/controller.py @@ -39,17 +39,17 @@ def controller() -> None: logger.info(f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果:[{process_result}]') # ⑤ 取得処理実施結果アップロード処理を呼び出す - logger.info('I-CTRL-19 CRM_取得処理実施結果ファイルアップロード処理開始') + logger.info('I-CTRL-18 CRM_取得処理実施結果ファイルアップロード処理開始') upload_result_data_process(process_result, execute_datetime) # ⑥ 最終結果をチェックし、チェック結果をログに出力 if not all([v == 'success' for v in process_result.values()]): logger.error('E-CTRL-01 一部のデータ取得に失敗しています。詳細はログをご確認ください。') else: - logger.info('I-CTRL-20 すべてのデータの取得に成功しました。') + logger.info('I-CTRL-19 すべてのデータの取得に成功しました。') # ⑦ CRMデータ取得処理終了ログを出力する - logger.info('I-CTRL-21 CRMデータ取得処理を終了します') + logger.info('I-CTRL-20 CRMデータ取得処理を終了します') return exit(0) @@ -106,7 +106,7 @@ def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTi """ # 1. オブジェクト処理結果の初期化 - logger.debug(f'D-CTRL-04 対象のオブジェクト情報を出力します オブジェクト情報:{object_info}') + logger.debug(f'D-CTRL-04 対象のオブジェクト情報を出力します オブジェクト情報:[{object_info}]') # 2. オブジェクト情報形式チェック処理を呼び出す logger.info('I-CTRL-05 オブジェクト情報形式チェック処理呼び出し') @@ -138,7 +138,7 @@ def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTi # 7. 出力ファイル名をログ出力する logger.info( - f'I-CTRL-10 [{target_object_name}] の出力ファイル名は [{target_object.upload_file_name}]となります') + f'I-CTRL-10 [{target_object_name}] の出力ファイル名は [{target_object.upload_file_name}] となります') # 8. CRM電文データバックアップ処理を呼び出す logger.info( diff --git a/ecs/crm-datafetch/src/converter/convert_factory.py b/ecs/crm-datafetch/src/converter/convert_strategy.py similarity index 83% rename from ecs/crm-datafetch/src/converter/convert_factory.py rename to ecs/crm-datafetch/src/converter/convert_strategy.py index bf949a6e..92500588 100644 --- a/ecs/crm-datafetch/src/converter/convert_factory.py +++ b/ecs/crm-datafetch/src/converter/convert_strategy.py @@ -1,5 +1,5 @@ import re -from datetime import datetime +from datetime import datetime, timedelta, timezone from src.system_var.constants import (CRM_DATETIME_FORMAT, CSV_FALSE_VALUE, CSV_TRUE_VALUE, @@ -12,7 +12,7 @@ class ConvertStrategyFactory: self.__none_value_convert_strategy = NoneValueConvertStrategy() self.__float_convert_strategy = FloatConvertStrategy() self.__boolean_convert_strategy = BooleanConvertStrategy() - self.__datetime_convert_strategy = DatatimeConvertStrategy() + self.__datetime_convert_strategy = DatetimeConvertStrategy() self.__non_convert_strategy = NonConvertStrategy() def create(self, value): @@ -45,9 +45,10 @@ class BooleanConvertStrategy: return CSV_TRUE_VALUE if convert_value is True else CSV_FALSE_VALUE -class DatatimeConvertStrategy: +class DatetimeConvertStrategy: def convert_value(self, convert_value: str) -> str: - return datetime.strptime(convert_value, CRM_DATETIME_FORMAT).strftime(YYYYMMDDHHMMSS) + # データ登録処理がJSTとして登録するため、変換処理内で事前にJSTの日次文字列に変換する + return datetime.strptime(convert_value, CRM_DATETIME_FORMAT).astimezone(timezone(timedelta(hours=+9))).strftime(YYYYMMDDHHMMSS) class FloatConvertStrategy: diff --git a/ecs/crm-datafetch/src/converter/converter.py b/ecs/crm-datafetch/src/converter/converter.py index 9c223182..761f550e 100644 --- a/ecs/crm-datafetch/src/converter/converter.py +++ b/ecs/crm-datafetch/src/converter/converter.py @@ -2,7 +2,7 @@ import csv import io from src.config.objects import TargetObject -from src.converter.convert_factory import ConvertStrategyFactory +from src.converter.convert_strategy import ConvertStrategyFactory class CSVStringConverter: diff --git a/ecs/crm-datafetch/src/error/exceptions.py b/ecs/crm-datafetch/src/error/exceptions.py index f231804b..5085dbca 100644 --- a/ecs/crm-datafetch/src/error/exceptions.py +++ b/ecs/crm-datafetch/src/error/exceptions.py @@ -31,5 +31,5 @@ class DataConvertException(MeDaCaCRMDataFetchException): class SalesforceAPIException(MeDaCaCRMDataFetchException): - """SalseforceのAPI実行失敗が発生した場合の例外""" + """SalesforceのAPI実行失敗が発生した場合の例外""" pass diff --git a/ecs/crm-datafetch/src/fetch_crm_data_process.py b/ecs/crm-datafetch/src/fetch_crm_data_process.py index d22efb7e..1c37f860 100644 --- a/ecs/crm-datafetch/src/fetch_crm_data_process.py +++ b/ecs/crm-datafetch/src/fetch_crm_data_process.py @@ -3,7 +3,7 @@ from tenacity import retry, stop_after_attempt from tenacity.wait import wait_exponential from src.config.objects import LastFetchDatetime, TargetObject -from src.error.exceptions import DataConvertException, SalesforceAPIException +from src.error.exceptions import SalesforceAPIException from src.salesforce.salesforce_api import SalesforceApiClient from src.salesforce.soql_builder import SOQLBuilder from src.system_var.constants import FETCH_JP_NAME @@ -27,8 +27,7 @@ def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: Las last_fetch_datetime (LastFetchDatetime): データ取得期間設定インスタンス Raises: - SalesforceAPIException: SalseforceのAPI実行失敗が発生した場合 - DataConvertException: データ変換が失敗した場合 + SalesforceAPIException: SalesforceのAPI実行失敗が発生した場合 Returns: crm_data_response: Salesforceオブジェクトデータ @@ -40,12 +39,9 @@ def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: Las target_object_name = target_object.object_name - # リトライ回数判定用のカウンタオブジェクトを生成(@retryデコレータを利用したことによるリトライ対象の関数内でのカウント変数保持不可の対策のためオブジェクト化する) - count_contime_counter = CounterObject(1) - count_readtime_counter = CounterObject(1) + # リトライ回数判定用のカウンタオブジェクトを生成 + # @retryデコレータを利用した関数のリトライ処理で、基本データ型だとリトライ回数をカウントすることができないため、オブジェクト化する count_counter = CounterObject(1) - data_contime_counter = CounterObject(1) - data_readtime_counter = CounterObject(1) data_counter = CounterObject(1) try: @@ -55,7 +51,7 @@ def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: Las soql_builder = SOQLBuilder(target_object, last_fetch_datetime) count_soql = soql_builder.create_count_soql() - record_count = fetch_record_count_retry(count_soql, target_object_name, count_contime_counter, count_readtime_counter, count_counter) + record_count = fetch_record_count_retry(count_soql, target_object_name, count_counter) logger.info(f'I-FETCH-03 [{target_object_name}] の件数:[{record_count}]') @@ -69,26 +65,16 @@ def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: Las fetch_soql = soql_builder.create_fetch_soql() - record_all = fetch_sf_data_retry(fetch_soql, target_object_name, data_contime_counter, data_readtime_counter, data_counter) + crm_data_response = fetch_sf_data_retry(fetch_soql, target_object_name, data_counter) except Exception as e: raise SalesforceAPIException( 'E-FETCH-02', FETCH_JP_NAME, f'[{target_object_name}] のレコード取得に失敗しました エラー内容:[{e}]') - try: - # ④ 取得対象オブジェクトをJSONに変換 - logger.info(f'I-FETCH-05 [{target_object_name}] のレコードをJSONに変換します') + # ④ CRMデータ取得処理終了ログを出力する + logger.info(f'I-FETCH-05 [{target_object_name}] のレコード取得が成功しました') - crm_data_response = [record for record in record_all] - - except Exception as e: - raise DataConvertException( - 'E-FETCH-03', FETCH_JP_NAME, f'[{target_object_name}] のレコードのJSON変換に失敗しました エラー内容:[{e}]') - - # ⑤ CRMデータ取得処理終了ログを出力する - logger.info(f'I-FETCH-06 [{target_object_name}] のレコード取得が成功しました') - - # ⑥ 次の処理へ移行する + # ⑤ 次の処理へ移行する return crm_data_response @@ -96,24 +82,23 @@ def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: Las wait=wait_exponential(multiplier=CRM_GET_RECORD_COUNT_RETRY_INTERVAL, min=CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL, max=CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL), stop=stop_after_attempt(CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT)) -def fetch_record_count_retry(soql: str, target_object_name: str, - count_contime_counter: CounterObject, count_readtime_counter: CounterObject, count_counter: CounterObject): +def fetch_record_count_retry(soql: str, target_object_name: str, count_counter: CounterObject): try: salesforce_api_client = SalesforceApiClient() return salesforce_api_client.fetch_sf_count(soql) except ConnectTimeout as e: # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う - if count_contime_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: - count_contime_counter.increment(1) + if count_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: + count_counter.increment(1) logger.warning(f'W-FETCH-01 CRMの接続処理がタイムアウトしため、リトライします:[{CRM_AUTH_TIMEOUT}] エラー内容:[{e}]') raise e except ReadTimeout as e: # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う - if count_readtime_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: - count_readtime_counter.increment(1) + if count_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: + count_counter.increment(1) logger.warning( f'W-FETCH-02 [{target_object_name}] の件数取得処理がタイムアウトしたため、リトライします:[{CRM_GET_RECORD_COUNT_TIMEOUT}] エラー内容:[{e}]') raise e @@ -131,23 +116,22 @@ def fetch_record_count_retry(soql: str, target_object_name: str, wait=wait_exponential(multiplier=CRM_FETCH_RECORD_RETRY_INTERVAL, min=CRM_FETCH_RECORD_RETRY_MIN_INTERVAL, max=CRM_FETCH_RECORD_RETRY_MAX_INTERVAL), stop=stop_after_attempt(CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT)) -def fetch_sf_data_retry(soql: str, target_object_name: str, - data_contime_counter: CounterObject, data_readtime_counter: CounterObject, data_counter: CounterObject): +def fetch_sf_data_retry(soql: str, target_object_name: str, data_counter: CounterObject): try: salesforce_api_client = SalesforceApiClient() return salesforce_api_client.fetch_sf_data(soql) except ConnectTimeout as e: # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う - if data_contime_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: - data_contime_counter.increment(1) + if data_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: + data_counter.increment(1) logger.warning(f'W-FETCH-04 CRMの接続処理がタイムアウトしため、リトライします:[{CRM_AUTH_TIMEOUT}] エラー内容:[{e}]') raise e except ReadTimeout as e: # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う - if data_readtime_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: - data_readtime_counter.increment(1) + if data_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: + data_counter.increment(1) logger.warning( f'W-FETCH-05 [{target_object_name}] のレコード取得処理がタイムアウトしたため、リトライします:[{CRM_FETCH_RECORD_TIMEOUT}] エラー内容:[{e}]') raise e diff --git a/ecs/crm-datafetch/src/util/dict_checker.py b/ecs/crm-datafetch/src/util/dict_checker.py index 1f97dded..39ebf9f0 100644 --- a/ecs/crm-datafetch/src/util/dict_checker.py +++ b/ecs/crm-datafetch/src/util/dict_checker.py @@ -5,9 +5,13 @@ class DictChecker: def __init__(self, object_dict: dict) -> None: self.__object_dict = object_dict + def is_empty(self, check_key): + """辞書型バリュー空文字チェック""" + return self.__object_dict[check_key] != '' and self.__object_dict[check_key] is not None + def check_key_exist(self, check_key: str) -> bool: """辞書型キー存在チェック""" - return check_key in self.__object_dict and self.__object_dict[check_key] != '' + return check_key in self.__object_dict and self.is_empty(check_key) def check_data_type(self, check_key: str, check_type: type) -> bool: """辞書型バリュー型チェック""" diff --git a/ecs/crm-datafetch/src/util/execute_datetime.py b/ecs/crm-datafetch/src/util/execute_datetime.py index 8a804291..bdf7f053 100644 --- a/ecs/crm-datafetch/src/util/execute_datetime.py +++ b/ecs/crm-datafetch/src/util/execute_datetime.py @@ -1,11 +1,11 @@ -from datetime import datetime +from datetime import datetime, timezone from src.system_var.constants import MILLISEC_FORMAT, YYYYMMDDTHHMMSSTZ class ExecuteDateTime: def __init__(self): - self.__execute_datetime = datetime.now().strftime(YYYYMMDDTHHMMSSTZ) + self.__execute_datetime = datetime.now(timezone.utc).strftime(YYYYMMDDTHHMMSSTZ) def __str__(self) -> str: return self.__execute_datetime