Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/280-transport-spi-lifecycle-unimplemented.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

81 lines
5.1 KiB
Plaintext

# revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
## A. public types: files referencing them outside the owning leaf
MessagingTransport 12
MessagingRuntime 3
MessagingRuntimeRegistry 3
MessagingRuntimeLease 2
DefaultMessagingRuntimeRegistry 2
GracefulShutdownCoordinator 11
MessagingLifecycle 0
TransportDelivery 9
TransportSettlement 4
TransportPublishRequest 18
TransportPublishResult 10
TransportConsumerSpec 14
TransportConsumerRegistration 8
## B. MessagingLifecycle: every occurrence in the repository
src/messaging/messaging-transport-spi/src/main/java/dev/caskeleton/messaging/transport/MessagingLifecycle.java:17:public interface MessagingLifecycle {
src/messaging/messaging-transport-spi/src/test/java/dev/caskeleton/messaging/transport/MessagingLifecycleTest.java:5:import dev.caskeleton.messaging.transport.MessagingLifecycle.ShutdownPhase;
src/messaging/messaging-transport-spi/src/test/java/dev/caskeleton/messaging/transport/MessagingLifecycleTest.java:57: assertThat(MessagingLifecycle.DEFAULT_DRAIN_DEADLINE).isEqualTo(Duration.ofSeconds(30));
--- anything implementing it?
exit=1 (1 = nothing implements it)
--- anything referencing ShutdownPhase outside the leaf?
exit=1 (1 = no external consumer)
## C. what the ordering tests actually assert
@Test
void publishAdmissionClosesBeforeConsumersArePaused() {
List<ShutdownPhase> order = List.of(ShutdownPhase.values());
assertThat(order.indexOf(ShutdownPhase.STOP_PUBLISH_ADMISSION))
.isLessThan(order.indexOf(ShutdownPhase.PAUSE_CONSUMERS));
}
@Test
void handlersDrainBeforeTheirSettlementsAreFlushed() {
List<ShutdownPhase> order = List.of(ShutdownPhase.values());
assertThat(order.indexOf(ShutdownPhase.DRAIN_HANDLERS))
.as("flushing before the handlers finish would lose the settlements they produce")
.isLessThan(order.indexOf(ShutdownPhase.FLUSH_SETTLEMENTS));
}
## D. the shutdown path that IS wired
--- who implements MessagingTransport (the SPI that is used)
src/messaging/messaging-kafka/src/main/java/dev/caskeleton/messaging/kafka/KafkaMessagingTransport.java:41:public final class KafkaMessagingTransport implements MessagingTransport {
src/messaging/messaging-nats-experimental/src/main/java/dev/caskeleton/messaging/nats/NatsJetStreamTransport.java:54:public final class NatsJetStreamTransport implements MessagingTransport {
src/messaging/messaging-pulsar-experimental/src/main/java/dev/caskeleton/messaging/pulsar/PulsarMessagingTransport.java:47:public final class PulsarMessagingTransport implements MessagingTransport {
src/messaging/messaging-rabbit/src/main/java/dev/caskeleton/messaging/rabbit/RabbitMessagingTransport.java:39:public final class RabbitMessagingTransport implements MessagingTransport {
src/messaging/messaging-runtime-core/src/test/java/dev/caskeleton/messaging/runtime/DefaultMessagePublisherTest.java:426: private static final class RecordingTransport implements MessagingTransport {
src/messaging/messaging-transport-spi/src/test/java/dev/caskeleton/messaging/transport/MessagingRuntimeRegistryTest.java:230:final class FakeTransport implements MessagingTransport {
--- the wired shutdown bean and what it performs
30:public final class MessagingShutdownLifecycle implements SmartLifecycle {
88: admission.stopAcceptingNewWork();
90: drain.beginDrain(startedAt);
92: while (!drain.isDrained(clock.get()) && clock.get().isBefore(deadline)) {
121: public int getPhase() {
--- GracefulShutdownCoordinator consumers
src/messaging/messaging-kafka/src/main/java/dev/caskeleton/messaging/kafka/KafkaConsumerRegistrar.java
src/messaging/messaging-kafka/src/test/java/dev/caskeleton/messaging/kafka/KafkaBrokerCertificationIT.java
src/messaging/messaging-kafka/src/test/java/dev/caskeleton/messaging/kafka/KafkaBrokerIT.java
src/messaging/messaging-kafka/src/test/java/dev/caskeleton/messaging/kafka/KafkaConsumerRegistrarTest.java
src/messaging/messaging-kafka/src/test/java/dev/caskeleton/messaging/kafka/KafkaConsumerSettlementIT.java
src/messaging/messaging-rabbit/src/main/java/dev/caskeleton/messaging/rabbit/RabbitConsumerRegistrar.java
src/messaging/messaging-rabbit/src/test/java/dev/caskeleton/messaging/rabbit/RabbitRuntimeTest.java
src/messaging/messaging-spring-boot-starter/src/main/java/dev/caskeleton/messaging/autoconfigure/MessagingCoreAutoConfiguration.java
src/messaging/messaging-spring-boot-starter/src/main/java/dev/caskeleton/messaging/autoconfigure/MessagingShutdownLifecycle.java
src/messaging/messaging-spring-boot-starter/src/test/java/dev/caskeleton/messaging/autoconfigure/MessagingAutoConfigurationTest.java
src/messaging/messaging-spring-boot-starter/src/test/java/dev/caskeleton/messaging/autoconfigure/MessagingShutdownLifecycleTest.java
## E. the eight declared phases vs what the wired path performs
22: STOP_PUBLISH_ADMISSION,
24: STOP_NEW_HANDLERS,
26: PAUSE_CONSUMERS,
28: DRAIN_HANDLERS,
30: FLUSH_SETTLEMENTS,
32: AWAIT_PRODUCER_CONFIRMS,
34: RELEASE_OUTBOX_LEASES,
36: CLOSE_CONNECTIONS