概要
Lambdaで定期的に実行するバッチ削除処理APIの作成方法
目的
掲題の方法を説明する
使用技術
application/pyproject.toml
python = "^3.11.2"
Django = "^4.2.7"
djangorestframework = "^3.14.0"
pytest = "^7.4.3"
pytest-django = "^4.7.0"
早速コードを見ていきましょう!
今回の削除する対象はSMS送信履歴とします
application/project/serializers.py
from rest_framework import serializers
class DeleteSmsSendHistorySerializer(serializers.Serializer):
"""SMS送信履歴削除用のシリアライザ"""
token = serializers.CharField(max_length=64)
application/project/views/sms.py
from datetime import timedelta
from django.db import DatabaseError, transaction
from django.utils import timezone
from rest_framework import mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
# マジックナンバーを防ぐため、定数化しています
from common.constant import (
DELETE_THRESHOLD_DAYS,
DELETED_RECORDS_COUNT_INDEX,
DELETED_SMS_SEND_HISTORY_RECORDS_INDEX,
)
# settingsはpydanticを使用して環境変数情報を持っています
from common.environment_variable import settings
from project.models import SmsSendHistory
from project.serializers import DeleteSmsSendHistorySerializer
class SmsSendHistoryViewSet(viewsets.GenericViewSet):
"""SMS送信履歴削除用のAPI"""
serializer_class = DeleteSmsSendHistorySerializer
@action(methods=["post"], detail=False)
def delete_old_record(self, request):
"""Lambdaで使用するSMS送信履歴削除API
180日以前の古いSMS送信履歴を削除する
Parameters:
token(str): Lambda実行用のトークン
Returns:
detail (str): メッセージ
"""
serializer = self.get_serializer_class()(data=request.data)
serializer.is_valid(raise_exception=True)
if serializer.validated_data.get("token") != settings.LAMBDA_TOKEN:
return Response(
{"detail": "無効なトークンです"},
status.HTTP_400_BAD_REQUEST,
)
delete_date = timezone.localtime() - timedelta(
days=DELETE_THRESHOLD_DAYS
)
try:
with transaction.atomic():
deleted_records_info = SmsSendHistory.objects.filter(
created_at__lte=delete_date
).delete()
except DatabaseError:
return Response(
{"detail": "SMS送信履歴の削除に失敗しました"},
status.HTTP_500_INTERNAL_SERVER_ERROR,
)
deleted_count = 0
if deleted_records_info[DELETED_RECORDS_COUNT_INDEX] != 0:
deleted_count = deleted_records_info[
DELETED_SMS_SEND_HISTORY_RECORDS_INDEX
]["project.SmsSendHistory"]
return Response(
{"detail": f"180日前のSMS送信履歴を{deleted_count}件削除しました"},
status.HTTP_200_OK,
)
重要なポイントを解説していきましょう!
期待しているLambdaからのリクエストかどうかをチェックしています
if serializer.validated_data.get("token") != settings.LAMBDA_TOKEN:
return Response(
{"detail": "無効なトークンです"},
status.HTTP_400_BAD_REQUEST,
)
現在の時間から指定した過去の日付を取得します(今回は180日前)
delete_date = timezone.localtime() - timedelta(
days=DELETE_THRESHOLD_DAYS
)
# 結果例
delete_date: 2023-09-24 15:52:39.155157+09:00
type(delete_date): <class 'datetime.datetime'>
objectsマネージャーを使用し、180日以前のSMS送信履歴を削除します
トランザクション処理に失敗した場合は500エラーを返すようにしています
try:
with transaction.atomic():
deleted_records_info = SmsSendHistory.objects.filter(
created_at__lte=delete_date
).delete()
except DatabaseError:
return Response(
{"detail": "SMS送信履歴の削除に失敗しました"},
status.HTTP_500_INTERNAL_SERVER_ERROR,
)