refactor: 빌드 로직 개선, gradle 파일 경량화
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# Messaging Platform Bridge Design
|
||||
|
||||
## Goal
|
||||
|
||||
Replace the application-specific broker seam with one canonical anti-corruption bridge:
|
||||
|
||||
```
|
||||
application-core IntegrationEventPublishPort
|
||||
-> adapter/outbound/messaging/platformbridge
|
||||
-> messaging-schema-api EncodedMessagePublisher
|
||||
-> messaging-runtime-core DefaultMessagePublisher
|
||||
-> messaging transport/runtime
|
||||
```
|
||||
|
||||
The bridge must preserve canonical event identity and exact encoded bytes while reusing the platform's destination resolution, authorization, admission, runtime leasing, transport normalization, and observation pipeline.
|
||||
|
||||
## Scope
|
||||
|
||||
This phase introduces and verifies the canonical bridge. It does **not** migrate the legacy outbox storage/relay rows, because `OutboxEvent` does not retain the schema/order/tenant metadata required to reconstruct `ValidatedIntegrationEvent` without invention.
|
||||
|
||||
## Application boundary
|
||||
|
||||
Create `IntegrationEventPublishPort` in `application-core`.
|
||||
|
||||
Signature:
|
||||
|
||||
```java
|
||||
CompletionStage<OutboxPublishOutcome> publish(ValidatedIntegrationEvent event);
|
||||
```
|
||||
|
||||
The application package depends only on its own canonical event model and application outcome vocabulary.
|
||||
|
||||
## Adapter bridge
|
||||
|
||||
`PlatformIntegrationEventPublishAdapter` lives under:
|
||||
|
||||
```
|
||||
adapter/outbound/messaging/platformbridge
|
||||
```
|
||||
|
||||
It depends on `EncodedMessagePublisher`, never on a concrete broker client, runtime-core implementation, or transport SPI.
|
||||
|
||||
Mapping rules:
|
||||
|
||||
- `logicalDestinationId` -> platform `DestinationName`.
|
||||
- `contractId` -> platform `MessageType`.
|
||||
- `payloadVersion` -> `SchemaVersion`.
|
||||
- event and causation identities must parse as UUIDv7; values are preserved exactly. Incompatible identities fail closed before the platform publisher is called.
|
||||
- `occurredAt` is used for both `producedAt` and `occurredAt` until the application canonical model carries a separate production timestamp. The bridge never invents a new timestamp.
|
||||
- producer is an explicit constructor/configuration value.
|
||||
- correlation, partition key, tenant, aggregate order and exact envelope bytes are preserved.
|
||||
- trace context is explicitly absent (`TraceContext.none()`) until the application model owns canonical trace context.
|
||||
- exact `envelopeBytes` become `EncodedMessage` bytes; no re-encoding occurs.
|
||||
- schema/catalog/binding/envelope evidence that has no first-class platform field is preserved as bounded `x-ca-*` headers.
|
||||
- the schema reference subject is the canonical contract id and version is the canonical payload version.
|
||||
|
||||
## Outcome mapping
|
||||
|
||||
Mapping is based on completion **and transmission evidence**, not enum name similarity:
|
||||
|
||||
- CONFIRMED -> `OutboxPublishOutcome.CONFIRMED`.
|
||||
- AMBIGUOUS -> `OutboxPublishOutcome.AMBIGUOUS`.
|
||||
- REJECTED + NOT_TRANSMITTED -> `REJECTED_BEFORE_SEND`.
|
||||
- REJECTED + any evidence that bytes may have left the process -> `REJECTED_AFTER_BROKER`.
|
||||
|
||||
Bridge preparation failures are definite pre-send rejection.
|
||||
|
||||
## Platform boundary
|
||||
|
||||
`EncodedMessagePublisher` is owned by `messaging-schema-api`, because `EncodedMessage` is owned there and the dependency direction remains acyclic.
|
||||
|
||||
`DefaultMessagePublisher` implements both `MessagePublisher` and `EncodedMessagePublisher`. The encoded path skips only codec lookup/encoding; destination resolution, access policy, admission, runtime lease, transport send, deadline handling, result normalization and observation are shared with the normal publish path.
|
||||
|
||||
The starter exposes one `DefaultMessagePublisher` singleton, which therefore satisfies both public interfaces.
|
||||
|
||||
## Spring ownership
|
||||
|
||||
`MessagingBridgeRootAutoConfiguration` owns the bridge bean when an `EncodedMessagePublisher` is present **and** `app.messaging.producer-id` is explicitly configured. Producer identity is never inferred from `spring.application.name` or invented. Application bootstrap must not construct Kafka producer clients or implement broker-specific send behavior.
|
||||
|
||||
The existing `KafkaSender` / `KafkaMessageBroker` path remains temporarily for the legacy `OutboxEvent` and realtime publishers, which do not yet carry enough canonical metadata to enter the new bridge without invention. It is explicitly transitional and is removed only with the legacy outbox/realtime cutover. The new canonical bridge never calls it.
|
||||
|
||||
## Verification
|
||||
|
||||
Required checks:
|
||||
|
||||
1. `DefaultMessagePublisherTest`: pre-encoded publish preserves bytes and skips codec while still exercising central pipeline.
|
||||
2. `PlatformIntegrationEventPublishAdapterTest`: golden mapping, outcome mapping, fail-closed identity behavior.
|
||||
3. outbound messaging module tests/check.
|
||||
4. messaging runtime/starter tests.
|
||||
5. app-bootstrap system test and architecture test after adding the canonical bridge while retaining the documented legacy seam.
|
||||
6. search proving app-bootstrap has no direct native Kafka sender configuration.
|
||||
7. dependency/build lock refresh only where dependency ownership changed.
|
||||
8. `git diff --check`.
|
||||
|
||||
Reference in New Issue
Block a user