feat: add JPA production capability

This commit is contained in:
donghyeon-ka
2026-07-31 23:48:51 +09:00
parent b3add0162d
commit 7eb6af5d5f
141 changed files with 13094 additions and 319 deletions
+35
View File
@@ -256,6 +256,21 @@ application 계층이 in-flight 대기·replay **정책** 을 소유하고, 저
- retryable: mismatch / in-flight 모두 `false`. 클라이언트는 body 를 고치거나 결과를 polling 해야지
단순 재시도를 하면 안 된다.
### Owner-safe idempotency V2
`idempotency.v2`는 V1의 scope-only `tryBegin/complete/discard`를 대체하는 additive contract다.
provider가 JPA인지 Redis인지와 무관하게 claim에는 secure owner token과 stable operation ID가
필요하고, 모든 mutation은 owner/attempt/claim-operation/state-revision을 검증한다.
- processing lease와 completed replay TTL을 분리한다.
- expired `CLAIMED`만 takeover하고 expired `EXECUTING`은 `RECOVERY_REQUIRED`로 닫는다.
- complete/fail/release는 operation ID와 result digest가 같은 재호출만 prior result로 replay한다.
- `SAME_STORE_TRANSACTIONAL` JPA profile의 response는 8 KiB 이하 inline 값만 지원한다.
- raw principal/client key는 versioned HMAC scope digest로 바꾼 뒤 adapter에 전달한다.
V1은 rolling migration compatibility를 위해 유지된다. 새 reliability profile이 V2 claim과 V1
scope-only mutation을 섞는 것은 금지한다.
---
## 트랜잭셔널 아웃박스 릴레이 (outbox)
@@ -383,6 +398,26 @@ claim → 트랜잭션 밖에서 발행 → at-least-once 보장.
adapter에 전달하는 framework-free outbound contract. 구조화 ERROR 필드와 runbook 렌더링은
messaging adapter가 소유한다.
### Immutable outbox/polling delivery V2
`outbox.v2`는 domain event intent와 delivery state를 분리한다.
- `NewOutboxEventV2`의 aggregate version과 deterministic ordinal이 ordering authority다.
- `OutboxAppendPortV2`는 caller의 primary write transaction에 참여하고 publication epoch와
authority를 DB control row에서 얻는다.
- immutable event ID 충돌과 aggregate ordering tuple 충돌은 서로 다른 outcome이다.
- `OutboxPollingDeliveryPortV2`는 publish 밖의 짧은 claim/completion transaction만 소유하고
owner/token/attempt/version/epoch CAS로 stale relay를 거절한다.
- broker publish와 DB completion 사이 ACK 유실은 stable event ID의 duplicate publish를 만들 수
있으므로 exactly-once delivery로 표현하지 않는다.
### Same-store inbox
`inbox.InboxStorePort`는 broker redelivery를 DB business mutation과 같은 transaction에서
deduplicate한다. `RECEIVED -> PROCESSING -> COMPLETED`가 기본이며 expired `PROCESSING`은 blind
takeover하지 않는다. broker ACK는 transaction commit 이후 adapter 바깥에서만 수행하고 remote
side effect는 outbox/workflow로 옮긴다.
---
## 분산 락 (lock)