원자성 보강

브로커 전송은 나중에 해도, 발행해야 할 사실은 같은 커밋으로 먼저 남깁니다.

Outbox의 핵심은 즉시 발행이 아니라, 나중에 relay가 다시 집어 갈 수 있는 pending 상태를 DB 안에 확정해 두는 것입니다.

1
같은 트랜잭션에서 저장 업무 데이터와 발행 근거를 한 번에 커밋
orders

주문 row 생성

비즈니스 상태 변경이 먼저 DB에 반영됩니다.

outbox

event body + status = pending

아직 브로커로 나가진 않았지만, 발행해야 할 이벤트는 이미 같은 커밋 안에 기록됩니다.

결과: 주문만 저장되고 이벤트 발행 근거는 사라지는 상태를 피합니다.
relay가 pending 조회
2
커밋 뒤에 별도 처리 같은 outbox row가 성공이면 전이되고, 실패면 남아 있습니다.
relay
status = pending 인 row만 읽음

외부 발행은 트랜잭션 밖으로 분리되지만, 시작점은 항상 DB 안에 남은 outbox row입니다.

→
공유 출발점

한 번 저장된 같은 row를 기준으로 성공과 실패가 갈립니다.

발행 성공

pending
→
sent

브로커 전송이 끝나면 같은 outbox row를 sent로 갱신합니다. 이후 중복 발행 대상에서 빠집니다.

발행 실패

pending
→
pending

전송 실패나 타임아웃이 나도 row를 지우지 않습니다. pending 상태가 남아 다음 poll에서 다시 시도할 수 있습니다.

핵심 메시지: Outbox는 "지금 바로 발행"을 보장하는 패턴이 아니라, "발행해야 할 사실을 잃지 않고 나중에 이어서 보낼 수 있게" 만드는 패턴입니다.