# 주제: messaging-spring-boot-starter 가 실제로 만드는 빈 전수와, 만들지 않는 것
# revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916

# ---- 진입점 ----
# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
#   dev.caskeleton.messaging.autoconfigure.MessagingPlatformRootAutoConfiguration
#   (한 줄. 나머지 설정은 전부 @Import 로 끌려온다.)
#
# MessagingPlatformRootAutoConfiguration
#   @ConditionalOnProperty(prefix="app.messaging", name="enabled", havingValue="true")
#   @Import({MessagingCoreAutoConfiguration, MessagingProviderSelection,
#            MessagingReliabilityAutoConfiguration, MessagingAdminAutoConfiguration})

# ---- 만드는 @Bean 전수 (38개) ----
# MessagingCoreAutoConfiguration (23)
#   messagingCredentialRequirementValidator, messagingPrefixMigrationValidator,
#   compiledMessagingConfiguration, messagingConfigurationKeyValidator,
#   validatedDestinationRegistry, destinationProfileValidator, messageSecurityValidator,
#   retryDecisionEngine, deadLetterOrchestrator, messagingRuntimeRegistry,
#   gracefulShutdownCoordinator, brokerSecurityStartupValidation, messagingShutdownLifecycle,
#   messagingRedactor, cardinalityGuard, blockingMessagePublisher, reactiveMessagePublisher,
#   batchMessagePublisher, credentialRuntimeRegistry(@ConditionalOnBean CredentialProvider),
#   brokerTlsPolicy, messagingEndpoint, messagingCodecs, messagingDestinationProfiles,
#   messagingDestinationAccess, messagingAdmission, messagingPublisher, messagingRuntimeInstallation
# KafkaMessagingAutoConfiguration (7)
#   kafkaProfileValidator, kafkaProfileStartupValidation, kafkaTransactionProfileValidator,
#   kafkaPublishFailureClassifier, kafkaSecurityConfigurer(@ConditionalOnBean),
#   messagingKafkaProducer, messagingKafkaTransport
# RabbitMessagingAutoConfiguration (4)  — 단, 선택 불가 (아래)
#   rabbitProfileValidator, rabbitProfileStartupValidation, rabbitPublishFailureClassifier,
#   rabbitSecurityConfigurer(@ConditionalOnBean)
# MessagingReliabilityAutoConfiguration (9)
#   outboxProperties, outboxRetryScheduler, outboxRelay(@ConditionalOnBean),
#   outboxRelayWorker(@ConditionalOnBean), outboxRelayLifecycle(@ConditionalOnBean),
#   outboxCleanupJob(@ConditionalOnBean), inboxRetentionPolicy,
#   inboxCleanupJob(@ConditionalOnBean), transactionalInboxHandler(@ConditionalOnBean)
# MessagingAdminAutoConfiguration (4)
#   destructiveOperationGuard, adminOperationJournal, messagingAdminDurabilityValidator,
#   compositeTopologyValidator(@ConditionalOnBean)

# ---- 만들지 않는 것 ----
# command: git grep -nE "ConsumerRegistrar|DeliveryProcessor|RetryExecutor|DeadLetterPublisher|MessagingConsumer|MessageListener|MessagingObservation|MessagingMetrics" -- src/messaging/messaging-spring-boot-starter/src/main
# exit: 1  (출력 없음)
#
# => 스타터 전체에 컨슈머·배달 처리기·재시도 실행기·DLQ 발행기·관측 구현 빈이 하나도 없다.
#    확정되는 것:
#      (a) 배포되는 컨텍스트는 발행할 수 있고 소비할 수 없다.
#      (b) MessagingObservation 빈이 없으므로 관측은 no-op 이다.
#          MessagingCoreAutoConfiguration:253 messagingRedactor, :264 cardinalityGuard 는
#          MessagingMetrics 의 두 생성자 협력자인데, MessagingMetrics 자체를 만드는 곳이 없다.
#          messagingPublisher(:439-447)는 DefaultMessagePublisher 의 6-arg 생성자를 쓰고,
#          그 체인은 NO_OBSERVATION 으로 끝난다(DefaultMessagePublisher.java:126-135).
#      (c) retryDecisionEngine(:167)·deadLetterOrchestrator(:179) 빈은 만들어지되
#          그 유일한 소비자(KafkaRetryExecutor, Kafka/RabbitDeadLetterPublisher)가 생성되지 않는다.

# ---- 브로커 선택: rabbit 은 선택 불가 ----
# MessagingProviderSelection.java:63-68
#   static final Map<String, String> BROKERS_WITHOUT_A_TRANSPORT =
#       Map.of("rabbit",
#           "the Rabbit adapter ships its validators and security configuration but no "
#         + "MessagingTransport: its native channel publisher is not implemented, so a publish "
#         + "has nothing to travel on");
# selectedBroker(...):121-131 이 rabbit 을 IllegalStateException 으로 거절한다.
# => 오늘 선택 가능한 브로커는 kafka 하나다. assemblableBrokerIds() == ["kafka"].
#    RabbitMessagingAutoConfiguration 의 4개 빈은 도달 불가 경로에 있다.

# ---- 프로바이더 설정 javadoc 자체 모순 ----
# KafkaMessagingAutoConfiguration.java:16-17 (첫 문단)
#   "Conditional on the Kafka client being present, so a service that depends on the starter for
#    RabbitMQ alone does not fail to start because a Kafka class is missing."
# KafkaMessagingAutoConfiguration.java:26-29 (셋째 문단)
#   "Reached only when app.messaging.broker=kafka selected it. The @ConditionalOnClass this used to
#    carry could not select ..."
# 클래스에 @ConditionalOnClass 가 없다(@Configuration(proxyBeanMethods=false) 뿐).
# RabbitMessagingAutoConfiguration.java:15-16 / 22-23 도 같은 형태다.
# => 같은 javadoc 안에서 첫 문단과 셋째 문단이 어긋난다.

# ---- 선언된 의존 중 스타터가 import 하지 않는 것 ----
# command: git grep -n "import dev.caskeleton.messaging.cloudevents|import dev.caskeleton.messaging.claimcheck" -- src/messaging/messaging-spring-boot-starter
# exit: 1  (출력 없음)
# build.gradle 은 둘 다 implementation 으로 선언하고 modules.json 의 allowed_dependencies 에도 있다.
# => messaging-cloudevents 와 messaging-claim-check 이 runtime_memberships:["app-bootstrap"] 을
#    갖는 이유가 이 선언이며, 스타터는 그 둘의 타입을 하나도 쓰지 않는다.
#    (두 리프의 외부 참조 0건은 각 리프 문서에 기록되어 있다.)

# ---- 정리 잡은 빈이지만 스케줄되지 않는다 ----
# MessagingReliabilityAutoConfiguration.java:32-34 (클래스 javadoc)
#   "The cleanup jobs are beans but no scheduler is registered for them. Scheduling is the
#    application's decision: a service running several replicas usually wants one of them to run
#    cleanup, and auto-registering a fixed-rate task would have every replica delete the same rows."
# => OutboxCleanupJob / InboxCleanupJob 의 runOnce 를 부르는 프로덕션 코드가 없다.
#    EVD-311 의 무제한 DELETE 는 애플리케이션이 이 잡을 스케줄하는 순간 발동한다.
#    (기본 배포에서는 아무것도 실행되지 않으므로, EVD-311 의 "프로덕션 기본 경로" 표현은
#     "애플리케이션이 문서 지시대로 스케줄하면 발동하는 경로" 로 읽어야 정확하다.)
