# 주제: messaging-kafka 34개 main 타입 중 무엇이 조립되고 무엇이 조립되지 않는가 # revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 # command: git grep -nE "new ([a-zA-Z0-9_.]+\.)?\s*\(" -- src (T별 집계) KafkaMessagingTransport src/main=1 src/test+jmh=12 <- 스타터가 3-arg 로 생성 KafkaSecurityConfigurer src/main=1 src/test+jmh=2 KafkaProfileValidator src/main=1 src/test+jmh=1 KafkaTransactionProfileValidator src/main=1 src/test+jmh=0 KafkaPublishFailureClassifier src/main=2 src/test+jmh=1 KafkaPublishMapper src/main=2 src/test+jmh=0 (transport/transactional 내부) KafkaHeaderMapper src/main=2 src/test+jmh=4 (두 매퍼 내부) KafkaTransactionalPublisher src/main=1 src/test+jmh=1 (자기 정적 팩토리) KafkaDeliveryMapper src/main=1 src/test+jmh=1 (registrar 내부) KafkaSettlementQueue src/main=1 src/test+jmh=0 (registrar 내부) KafkaPartitionRetryScheduler src/main=1 src/test+jmh=0 (registrar 내부) PartitionWorkCoordinator src/main=1 src/test+jmh=6 (registrar 내부) ContiguousPartitionOffsetTracker src/main=1 src/test+jmh=2 (registrar 내부) KafkaRetryMetadataMapper src/main=2 src/test+jmh=3 ----- KafkaConsumerRegistrar src/main=0 src/test+jmh=6 <- 테스트에서만 KafkaOffsetResetExecutor src/main=0 src/test+jmh=2 <- 테스트에서만 KafkaReplayPlanner src/main=0 src/test+jmh=1 <- 테스트에서만 SpringKafkaTransactionalProcessor src/main=0 src/test+jmh=1 <- 테스트에서만 ----- KafkaBatchConsumerRegistrar src/main=0 src/test+jmh=0 <- **어디에서도 생성되지 않음** KafkaRetryExecutor src/main=0 src/test+jmh=0 <- **어디에서도** KafkaRetryTopicPublisher src/main=0 src/test+jmh=0 <- **어디에서도** KafkaDeadLetterPublisher src/main=0 src/test+jmh=0 <- **어디에서도** KafkaReplayCapability src/main=0 src/test+jmh=0 <- **어디에서도** KafkaTopologyInspector src/main=0 src/test+jmh=0 <- 인터페이스, 구현 0 # src/main 에서 이 leaf 의 타입을 만드는 외부 지점 (전수) KafkaMessagingAutoConfiguration.java:42 new KafkaProfileValidator() KafkaMessagingAutoConfiguration.java:75 new KafkaTransactionProfileValidator() KafkaMessagingAutoConfiguration.java:86 new KafkaPublishFailureClassifier() KafkaMessagingAutoConfiguration.java:111 new KafkaSecurityConfigurer(credentials, tlsPolicy) KafkaMessagingAutoConfiguration.java:168 new KafkaMessagingTransport("kafka", 1L, producer) MessagingConfigurationCompiler.java:116 new KafkaBrokerProfile(...) # => 외부에서 생성되는 것은 검증기 3 + 보안 설정기 1 + 전송 1 + 프로필 1 = 6개뿐이다. # ---- 소비 불가가 타입으로 표현되어 있다 ---- # KafkaMessagingTransport.java:74-92 (스타터가 쓰는 3-arg 생성자) # public KafkaMessagingTransport(String brokerName, long generation, Producer producer) { # this(brokerName, generation, producer, # spec -> { # throw new MessagingCapabilityUnavailableException( # "KAFKA_CONSUMER_NOT_CONFIGURED", # "this Kafka transport was created without a consumer factory"); # }); # } # KafkaMessagingTransport.java:159-167 # public TransportConsumerRegistration register(TransportConsumerSpec spec) { # ... # return consumerFactory.apply(spec); // 3-arg 경로에서는 항상 throw # } # => 부팅된 애플리케이션에서 transport.register(...) 는 KAFKA_CONSUMER_NOT_CONFIGURED 로 실패한다. # 조용히 아무 일도 안 하는 것이 아니라 이름 붙은 오류로 거절한다. # "소비 경로가 배선되지 않았다"(EVD-316)가 이 leaf 에서 타입으로 표현된 형태다. # ---- 토폴로지 인스펙터: 두 인터페이스, 구현 0 ---- # command: git grep -n "BrokerTopologyInspector" -- src # admin-runtime/BrokerTopologyInspector.java:14 (선언) # CompositeTopologyValidator:21,29 / DefaultMessagingAdminService:54,80 (소비) # MessagingAdminAutoConfiguration:5,81,83 (@ConditionalOnBean) # TopologyValidatorTest.java:133 new BrokerTopologyInspector() { ... } <- 유일한 구현, 테스트 익명클래스 # command: git grep -n "KafkaTopologyInspector" -- src # messaging-kafka/KafkaTopologyInspector.java:13 (선언) <- 그 외 등장 0 # # 두 인터페이스의 모양이 다르다: # BrokerTopologyInspector : Optional describe(String), String topologyVersion() # KafkaTopologyInspector : int partitionCount(String), short replicationFactor(String), # Map configuration(String), List topics() # # 실제로 브로커 토폴로지를 읽는 코드는 컨테이너 IT 안의 private static 헬퍼다: # KafkaTopologyValidationIT.java:42-61 # private static DestinationTopology describe(String topic) { # try (Admin admin = KafkaContainerFixture.admin()) { # Map described = admin.describeTopics(List.of(topic))...; # ... # return new DestinationTopology(topic, description.partitions().size(), replication, Map.of(), true); # } catch (...) { return DestinationTopology.absent(topic); } # } # => 어느 인터페이스도 구현하지 않는다. # # 판정: analysis/messaging/messaging-admin-api.md §17 첫 항목("BLOCKING 이면 기동 실패"가 미배선)을 # 고치려 해도 **줄 인스펙터가 없다.** Kafka leaf 는 그 자리에 다른 모양의 인터페이스를 # 선언만 해 두었고, 실제로 동작하는 20줄은 테스트의 private 메서드로만 존재한다. # ---- 이 leaf 를 import 하는 외부 파일은 3개뿐 ---- # messaging-spring-boot-starter/.../CompiledMessagingConfiguration.java # messaging-spring-boot-starter/.../KafkaMessagingAutoConfiguration.java # messaging-spring-boot-starter/.../MessagingConfigurationCompiler.java