트랜잭션 안에서 Celery Task가 호출되는 경우, 트랜잭션이 커밋되기 전에 Task가 실행될 수 있다.
이 때, Task가 커밋되지 않은 데이터를 참조하는 경우, 오류가 발생할 수 있다.
위와 같은 상황의 예시와 이를 회피하는 방법에 대해서 정리해보고자 한다.
문제상황
아래의 코드는 회원가입을 처리하는 가상의 코드이다.
from django.db import transaction
from coupon.util import create_welcome_coupon
from mileage.util import create_welcome_mileage
@transaction.atomic()
def create_user(user_data):
user = User.objects.create(**user_data)
send_email_welcome_join.delay(user.pk)
create_welcome_coupon(user.pk)
create_welcome_mileage(user.pk)
이 때, 트랜잭션이 실행되는 도중에 이메일 발송 태스크가 먼저 실행되는 경우, 이메일 발송 태스크에서는 회원 데이터를 조회할 수 없다.
Celery에서는 회원가입 로직과 다른 DB session에서 데이터를 조회하기 때문이다.
해결방법
django transaction의 on_commit를 활용하면, commit이 성공한 이후에 셀러리 함수가 호출되도록 할 수 있다.
from django.db import transaction
from coupon.util import create_welcome_coupon
from mileage.util import create_welcome_mileage
@transaction.atomic()
def create_user(user_data):
user = User.objects.create(**user_data)
transaction.on_commit(lambda: send_email_welcome_join.delay(user.pk))
create_welcome_coupon(user.pk)
create_welcome_mileage(user.pk)
Celery Task 함수를 on_commit 함수로 감싸주면 된다.
참고
'소프트웨어-이야기 > 프로그래밍 언어와 프레임워크' 카테고리의 다른 글
[Django] Django에서 MultiProccess 사용 시 주의사항 (0) | 2020.03.08 |
---|---|
(Django) Django에서 Thread를 다룰 때 주의할 점 (0) | 2020.01.27 |
(Django) Association Table Multiple Filter Chaining 주의사항 (2) | 2019.07.28 |
(Django) Django와 PostgreSQL 성능 개선을 위한 7가지 패턴 (0) | 2019.06.15 |
(Django) Django에서 비즈니스 로직 관리하기 (0) | 2019.05.12 |