# 조립 팩토리 둘. 앞의 것이 왜 그렇게 만드는지 적혀 있다. /** * The retry coordinator for one retry profile. * *

The policy and the coordinator's budget are built from the same profile on purpose. * Configuring them independently is how a deployment ends up with a policy that says "retry" and * a budget that permits one attempt — which looks like retry being broken rather than like a * misconfiguration. */ public FullTransactionRetryCoordinator retryCoordinator( SpringJpaTransactionExecutor executor, RetryProfile retryProfile, RetryEventListener listener) { return retryCoordinator(executor, DefaultJpaRetryPolicy.forProfile(retryProfile), listener); } /** The retry coordinator for an application-supplied policy. */ public FullTransactionRetryCoordinator retryCoordinator( SpringJpaTransactionExecutor executor, JpaRetryPolicy policy, RetryEventListener listener) { return new FullTransactionRetryCoordinator( executor, policy, retrySleeper(), clock, DEFAULT_MAX_RETRY_ELAPSED, listener); } # 뒤의 오버로드가 넘긴 정책이 담기는 필드 /** * Fallback policy, used only when a call supplies no retry profile of its own. * *

The coordinator used to apply this policy's eligibility and backoff to every call while * taking the attempt budget from whatever profile the caller passed. Two profiles then decided * one retry between them: profile A said which failures are retryable and how long to wait, * profile B said how many attempts were left. A caller reading either profile would have * predicted the wrong behaviour. */ private final JpaRetryPolicy fallbackRetryPolicy; # 그 필드를 읽는 유일한 자리 // One profile decides everything about this call: which failures are retryable, how long to // wait, and how many attempts remain. JpaRetryPolicy retryPolicy = profile.retryProfile() == null ? fallbackRetryPolicy : DefaultJpaRetryPolicy.forProfile(profile.retryProfile()); RetryBudget budget = RetryBudget.forProfile(profile.retryProfile(), defaultMaxElapsed); # 그런데 프로파일 타입이 그 조건을 금지한다 public TransactionProfile { Objects.requireNonNull(name, "name"); Objects.requireNonNull(propagation, "propagation"); Objects.requireNonNull(isolation, "isolation"); Objects.requireNonNull(retryProfile, "retryProfile"); # retryCoordinator( 호출 전수 (선언 제외) app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaPlatformRuntimeAutoConfiguration.java:173: .retryCoordinator( app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaTransactionAutoConfiguration.java:103: return retryCoordinator(executor, DefaultJpaRetryPolicy.forProfile(retryProfile), listener); # 코디네이터를 직접 생성하는 곳과 그때 넘기는 정책 app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaTransactionAutoConfiguration.java-110- executor, policy, retrySleeper(), clock, DEFAULT_MAX_RETRY_ELAPSED, listener); adapter/outbound/persistence-jpa/src/test/java/dev/caskeleton/adapter/outbound/persistence/transaction/FullTransactionRetryCoordinatorTest.java-47- DefaultJpaRetryPolicy.forProfile(retryProfile),