Merge branch 'feature-NEWDWH2021-1902' of nds-tyo.git.backlog.com:/NEWDWH2021/newsdwh2021 into feature-NEWDWH2021-1902

This commit is contained in:
yono 2025-05-28 10:39:37 +09:00
commit ca36186e6f
5 changed files with 65 additions and 44 deletions

View File

@ -1,8 +1,3 @@
import gzip
import os
import os.path as path
import shutil
import tempfile
import boto3 import boto3
from src.system_var import environment from src.system_var import environment
@ -12,7 +7,8 @@ class S3Client:
_bucket_name: str _bucket_name: str
def list_objects(self, bucket_name: str, folder_name: str): def list_objects(self, bucket_name: str, folder_name: str):
response = self.__s3_client.list_objects_v2(Bucket=bucket_name, Prefix=folder_name) response = self.__s3_client.list_objects_v2(
Bucket=bucket_name, Prefix=folder_name)
if response['KeyCount'] == 0: if response['KeyCount'] == 0:
return [] return []
contents = response['Contents'] contents = response['Contents']
@ -47,10 +43,12 @@ class S3Client:
Key=file_key Key=file_key
) )
class S3Bucket(): class S3Bucket():
_s3_client = S3Client() _s3_client = S3Client()
_bucket_name: str = None _bucket_name: str = None
class JskultArchiveBucket(S3Bucket): class JskultArchiveBucket(S3Bucket):
_bucket_name = environment.JSKULT_ARCHIVE_BUCKET _bucket_name = environment.JSKULT_ARCHIVE_BUCKET
@ -58,5 +56,6 @@ class JskultArchiveBucket(S3Bucket):
# S3バケットにファイルを移動 # S3バケットにファイルを移動
archive_zip_name = f'{send_folder}/{archive_zip}' archive_zip_name = f'{send_folder}/{archive_zip}'
s3_client = S3Client() s3_client = S3Client()
s3_client.upload_file(archive_zip_path, self._bucket_name, archive_zip_name) s3_client.upload_file(
archive_zip_path, self._bucket_name, archive_zip_name)
return f"{self._bucket_name}/{archive_zip_name}" return f"{self._bucket_name}/{archive_zip_name}"

View File

@ -1,15 +1,16 @@
from src.logging.get_logger import get_logger
from src.batch.jskult_archive_manager import JskultArchiveManager
from src.aws.s3 import JskultArchiveBucket
import os.path as path
from datetime import timedelta
import tempfile
import csv import csv
import os.path as path
import tempfile
import zipfile import zipfile
from datetime import timedelta
from src.aws.s3 import JskultArchiveBucket
from src.batch.jskult_archive_manager import JskultArchiveManager
from src.logging.get_logger import get_logger
logger = get_logger("実消化_過去データアーカイブ処理") logger = get_logger("実消化_過去データアーカイブ処理")
def exec(): def exec():
"""実消化_過去データアーカイブ処理""" """実消化_過去データアーカイブ処理"""
try: try:
@ -21,21 +22,25 @@ def exec():
# 取得したレコード分繰り返す # 取得したレコード分繰り返す
for jskult_archive_manage_data in jskult_archive_manage_data_list: for jskult_archive_manage_data in jskult_archive_manage_data_list:
# 対象テーブルで条件項目が条件年月以前のデータを取得 # 対象テーブルで条件項目が条件年月以前のデータを取得
archive_data = jskult_archive_manager.get_archive_data(jskult_archive_manage_data["target_table"], jskult_archive_manage_data["filter_column"], jskult_archive_manage_data["filter_date"]) archive_data = jskult_archive_manager.get_archive_data(
jskult_archive_manage_data["target_table"], jskult_archive_manage_data["filter_column"], jskult_archive_manage_data["filter_date"])
# 取得データが0件の場合、スキップする # 取得データが0件の場合、スキップする
if not archive_data: if not archive_data:
logger.info(f"アーカイブ対象データがありませんでした。対象テーブル:{jskult_archive_manage_data['target_table']} 条件年月:{jskult_archive_manage_data['filter_date']}") logger.info(
f"アーカイブ対象データがありませんでした。対象テーブル:{jskult_archive_manage_data['target_table']} 条件年月:{jskult_archive_manage_data['filter_date']}")
continue continue
# 一時フォルダ作成 # 一時フォルダ作成
with tempfile.TemporaryDirectory() as temporary_dir: with tempfile.TemporaryDirectory() as temporary_dir:
# 取得したデータをCSVに出力 # 取得したデータをCSVに出力
day_after_prev_filter_date = jskult_archive_manage_data["prev_filter_date"] + timedelta(days=1) day_after_prev_filter_date = jskult_archive_manage_data["prev_filter_date"] + timedelta(
days=1)
file_name = f'{jskult_archive_manage_data["target_table"]}_{day_after_prev_filter_date.strftime('%Y%m%d')}_{jskult_archive_manage_data["filter_date"].strftime('%Y%m%d')}' file_name = f'{jskult_archive_manage_data["target_table"]}_{day_after_prev_filter_date.strftime('%Y%m%d')}_{jskult_archive_manage_data["filter_date"].strftime('%Y%m%d')}'
csv_file_path = path.join(temporary_dir, f"{file_name}.csv") csv_file_path = path.join(temporary_dir, f"{file_name}.csv")
headers = archive_data[0].keys() headers = archive_data[0].keys()
with open(csv_file_path, 'w', newline='') as file: with open(csv_file_path, 'w', newline='') as file:
writer = csv.DictWriter(file, fieldnames=headers, quoting=csv.QUOTE_ALL) writer = csv.DictWriter(
file, fieldnames=headers, quoting=csv.QUOTE_ALL)
writer.writeheader() writer.writeheader()
writer.writerows(archive_data) writer.writerows(archive_data)
logger.info(f"CSVファイル作成に成功しました。{file_name}.csv") logger.info(f"CSVファイル作成に成功しました。{file_name}.csv")
@ -48,16 +53,23 @@ def exec():
# 圧縮したCSVを保存先へアップロード # 圧縮したCSVを保存先へアップロード
archive_bucket = JskultArchiveBucket() archive_bucket = JskultArchiveBucket()
upload_file_path = archive_bucket.upload_archive_zip_file(f"{file_name}.zip", zip_file_path, jskult_archive_manage_data["archive_storage"]) upload_file_path = archive_bucket.upload_archive_zip_file(
f"{file_name}.zip", zip_file_path, jskult_archive_manage_data["archive_storage"])
logger.info(f"{upload_file_path}へのアップロードに成功しました。") logger.info(f"{upload_file_path}へのアップロードに成功しました。")
# アーカイブしたデータをDBから削除 # アーカイブしたデータをDBから削除
jskult_archive_manager.delete_archive_data(jskult_archive_manage_data["target_table"], jskult_archive_manage_data["filter_column"], jskult_archive_manage_data["filter_date"]) jskult_archive_manager.delete_archive_data(
logger.info(f"アーカイブしたデータのDBから削除に成功しました。対象テーブル{jskult_archive_manage_data['target_table']} 条件年月:{jskult_archive_manage_data['filter_date']}") jskult_archive_manage_data["target_table"],
jskult_archive_manage_data["filter_column"],
jskult_archive_manage_data["filter_date"])
logger.info(
f"アーカイブしたデータのDBから削除に成功しました。対象テーブル{jskult_archive_manage_data['target_table']} 条件年月:{jskult_archive_manage_data['filter_date']}")
# 次回に向けてアーカイブ管理テーブルを更新する # 次回に向けてアーカイブ管理テーブルを更新する
jskult_archive_manager.update_archive_manage(jskult_archive_manage_data["target_table"]) jskult_archive_manager.update_archive_manage(
logger.info(f"アーカイブ管理テーブルの更新に成功しました。対象テーブル:{jskult_archive_manage_data['target_table']}") jskult_archive_manage_data["target_table"])
logger.info(
f"アーカイブ管理テーブルの更新に成功しました。対象テーブル:{jskult_archive_manage_data['target_table']}")
logger.info("処理終了:実消化_過去データアーカイブ処理") logger.info("処理終了:実消化_過去データアーカイブ処理")
except Exception as e: except Exception as e:
logger.exception(f"異常終了:実消化_過去データアーカイブ処理 {e}") logger.exception(f"異常終了:実消化_過去データアーカイブ処理 {e}")

View File

@ -1,9 +1,12 @@
from src.db.database import Database from src.db.database import Database
from src.logging.get_logger import get_logger from src.logging.get_logger import get_logger
logger = get_logger("アーカイブ管理テーブル操作") logger = get_logger("アーカイブ管理テーブル操作")
class JskultArchiveManager: class JskultArchiveManager:
_db : Database = None _db: Database = None
def __init__(self): def __init__(self):
self._db = Database.get_instance() self._db = Database.get_instance()
@ -72,7 +75,7 @@ class JskultArchiveManager:
self._db.commit() self._db.commit()
logger.info("処理終了delete_archive_data") logger.info("処理終了delete_archive_data")
return return
except: except Exception as e:
self._db.rollback() self._db.rollback()
logger.info("異常終了delete_archive_data") logger.info("異常終了delete_archive_data")
raise raise
@ -101,7 +104,7 @@ class JskultArchiveManager:
self._db.commit() self._db.commit()
logger.info("処理終了update_archive_manage") logger.info("処理終了update_archive_manage")
return return
except: except Exception as e:
self._db.rollback() self._db.rollback()
logger.info("異常終了update_archive_manage") logger.info("異常終了update_archive_manage")
raise raise

View File

@ -1,11 +1,10 @@
from sqlalchemy import (Connection, CursorResult, Engine, QueuePool, from sqlalchemy import (Connection, CursorResult, Engine, QueuePool,
create_engine, text) create_engine, text)
from sqlalchemy.engine.url import URL from sqlalchemy.engine.url import URL
from tenacity import retry, stop_after_attempt, wait_exponential
from src.error.exceptions import DBException from src.error.exceptions import DBException
from src.logging.get_logger import get_logger from src.logging.get_logger import get_logger
from src.system_var import environment from src.system_var import environment
from tenacity import retry, stop_after_attempt, wait_exponential
logger = get_logger(__name__) logger = get_logger(__name__)
@ -57,7 +56,8 @@ class Database:
poolclass=QueuePool poolclass=QueuePool
) )
self.__autocommit_engine = self.__transactional_engine.execution_options(isolation_level='AUTOCOMMIT') self.__autocommit_engine = self.__transactional_engine.execution_options(
isolation_level='AUTOCOMMIT')
@classmethod @classmethod
def get_instance(cls, autocommit=False): def get_instance(cls, autocommit=False):
@ -120,10 +120,12 @@ class Database:
try: try:
# トランザクションが開始している場合は、トランザクションを引き継ぐ # トランザクションが開始している場合は、トランザクションを引き継ぐ
if self.__connection.in_transaction(): if self.__connection.in_transaction():
result = self.__connection.execute(text(select_query), parameters) result = self.__connection.execute(
text(select_query), parameters)
else: else:
# トランザクションが明示的に開始していない場合は、クエリ単位でトランザクションをbegin-commitする。 # トランザクションが明示的に開始していない場合は、クエリ単位でトランザクションをbegin-commitする。
result = self.__execute_with_transaction(select_query, parameters) result = self.__execute_with_transaction(
select_query, parameters)
except Exception as e: except Exception as e:
raise DBException(f'SQL Error: {e}') raise DBException(f'SQL Error: {e}')
@ -187,7 +189,8 @@ class Database:
# トランザクションを開始してクエリを実行する # トランザクションを開始してクエリを実行する
with self.__connection.begin(): with self.__connection.begin():
try: try:
result = self.__connection.execute(text(query), parameters=parameters) result = self.__connection.execute(
text(query), parameters=parameters)
except Exception as e: except Exception as e:
self.__connection.rollback() self.__connection.rollback()
raise e raise e

View File

@ -12,7 +12,11 @@ JSKULT_ARCHIVE_BUCKET = os.environ['JSKULT_ARCHIVE_BUCKET']
# 初期値がある環境変数 # 初期値がある環境変数
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO') LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')
DB_CONNECTION_MAX_RETRY_ATTEMPT = int(os.environ.get('DB_CONNECTION_MAX_RETRY_ATTEMPT', 4)) DB_CONNECTION_MAX_RETRY_ATTEMPT = int(
DB_CONNECTION_RETRY_INTERVAL_INIT = int(os.environ.get('DB_CONNECTION_RETRY_INTERVAL', 5)) os.environ.get('DB_CONNECTION_MAX_RETRY_ATTEMPT', 4))
DB_CONNECTION_RETRY_INTERVAL_MIN_SECONDS = int(os.environ.get('DB_CONNECTION_RETRY_MIN_SECONDS', 5)) DB_CONNECTION_RETRY_INTERVAL_INIT = int(
DB_CONNECTION_RETRY_INTERVAL_MAX_SECONDS = int(os.environ.get('DB_CONNECTION_RETRY_MAX_SECONDS', 50)) os.environ.get('DB_CONNECTION_RETRY_INTERVAL', 5))
DB_CONNECTION_RETRY_INTERVAL_MIN_SECONDS = int(
os.environ.get('DB_CONNECTION_RETRY_MIN_SECONDS', 5))
DB_CONNECTION_RETRY_INTERVAL_MAX_SECONDS = int(
os.environ.get('DB_CONNECTION_RETRY_MAX_SECONDS', 50))