# 전달 보장 ## 왜 `EXACTLY_ONCE`가 없는가 어떤 브로커도 **외부 side effect를 포함한** exactly-once를 제공하지 않는다. 실제로 존재하는 것은 at-least-once 전달 + 멱등하거나 transactional한 consumer의 조합이다. 플랫폼이 지킬 수 없는 이름을 enum에 두면 그 책임이 눈에 보이지 않는 곳으로 밀려난다. 그래서 `DeliveryGuarantee`는 증거가 끝나는 지점에서 멈춘다. ```java public enum DeliveryGuarantee { AT_MOST_ONCE, AT_LEAST_ONCE } ``` ## Publish 결과는 boolean이 아니다 ```java public enum PublishCompletion { CONFIRMED, REJECTED, AMBIGUOUS } ``` `REJECTED`와 `AMBIGUOUS`를 하나의 "실패"로 합치면 중복 주문이 만들어진다. 전자는 broker가 저장하지 않았음이 **확정**되어 포기해도 안전하고, 후자는 그렇지 않다. | 상황 | 결과 | |---|---| | 로컬 validation 실패 | `REJECTED`, `NOT_TRANSMITTED` | | broker 명시적 reject / nack | `REJECTED` | | confirm 수신 | `CONFIRMED` | | Rabbit confirm + unroutable return | `REJECTED`, `UNROUTABLE` | | bytes 전송 후 connection loss | `AMBIGUOUS` | | confirm timeout | `AMBIGUOUS` | | adapter가 판정 불가 | 보수적으로 `AMBIGUOUS` | `PublishResult` 생성자가 이 규칙을 강제한다. `CONFIRMED`인데 broker acceptance가 없거나, `AMBIGUOUS`인데 confirmation level을 주장하면 **객체 생성 자체가 실패**한다. ## Ordering ```java public enum OrderingScope { NONE, DESTINATION, PARTITION, KEY } ``` 순서는 partition·key·단일 consumer의 성질이지 destination 전체의 성질이 아니다. `GLOBAL`이 없는 이유가 이것이다. `DestinationProfileValidator`가 다음을 거부한다. - `ordering=KEY`인데 key resolver 없음 - ordered destination인데 `ALLOW_REORDER` retry - `orderingImpact=PRESERVE`인데 재발행형 retry(`RETRY_DESTINATION`, `BROKER_DELAYED`) - `ordering=DESTINATION`인데 concurrency > 1 - ordered destination인데 ordering unit당 in-flight > 1 ## External side effect ```java public enum ExternalSideEffectGuarantee { NONE, IDEMPOTENCY_REQUIRED, INBOX_TRANSACTIONAL } ``` `INBOX_TRANSACTIONAL`만이 "DB side effect와 중복 차단이 같은 transaction에서 commit된다"를 의미한다. Kafka transaction은 **Kafka 안에서만** 원자적이므로 이 값과 함께 설정하면 `KafkaTransactionProfileValidator`가 거부한다. 두 개의 독립적인 commit을 하나로 착각하게 두지 않기 위해서다. ## Consumer settlement 순서 ```text RECEIVED → DECODING → PROCESSING → HANDLER_SUCCEEDED → SETTLEMENT_SENDING ├→ SETTLED └→ SETTLEMENT_UNKNOWN ``` - handler는 broker ACK API를 호출하지 않는다. - `Success` 이후에만 source settlement한다. - `SETTLEMENT_UNKNOWN`은 성공이 아니다. redelivery 가능성을 의미한다. - `SettlementResult` 생성자가 `SETTLED`인데 `redeliveryPossible=true`인 조합을 거부한다.