Outbox EventBus ้้
ๅจ
๐ ๆฆ่ฟฐ
EventBusAdapter ๆฏไธไธช็ๆญฃๅฏ็จ็้้
ๅจ๏ผๅฐ jxt-core/sdk/pkg/eventbus.EventBus ้้
ไธบ outbox.EventPublisher ๆฅๅฃใ
ๅ่ฝ:
- โ
่ฝฌๆข Outbox Envelope ไธบ EventBus Envelope
- โ
่ฝฌๆข EventBus PublishResult ไธบ Outbox PublishResult
- โ
่ชๅจๅฏๅจ ACK ็ปๆ่ฝฌๆข goroutine
- โ
็บฟ็จๅฎๅ
จ๏ผๆฏๆๅนถๅ่ฐ็จ
- โ
ๆฏๆ Kafka ๅ NATS ไธค็ง EventBus ๅฎ็ฐ
๐ ๅฟซ้ๅผๅง
1. ไฝฟ็จ Kafka EventBus
package main
import (
"context"
"log"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/eventbus"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox/adapters"
)
func main() {
// 1. ๅๅปบ Kafka ้
็ฝฎ
kafkaConfig := &eventbus.KafkaConfig{
Brokers: []string{"localhost:9092"},
ClientID: "outbox-service",
ConsumerGroup: "outbox-consumer-group",
}
// 2. ๅๅปบ Kafka EventBus ้้
ๅจ
adapter, err := adapters.NewKafkaEventBusAdapter(kafkaConfig)
if err != nil {
log.Fatalf("Failed to create adapter: %v", err)
}
defer adapter.Close()
// 3. ๅๅปบ Outbox Repository
repo := outbox.NewGormOutboxRepository(db)
// 4. ๅๅปบ Topic Mapper
topicMapper := outbox.NewSimpleTopicMapper(map[string]string{
"Order": "business.orders",
"Payment": "business.payments",
})
// 5. ๅๅปบ Outbox Publisher
config := &outbox.PublisherConfig{
MaxRetries: 3,
PublishTimeout: 30 * time.Second,
EnableMetrics: true,
ConcurrentPublish: true,
PublishConcurrency: 10,
}
publisher := outbox.NewOutboxPublisher(repo, adapter, topicMapper, config)
// 6. ๅฏๅจ ACK ็ๅฌๅจ
ctx := context.Background()
publisher.StartACKListener(ctx)
defer publisher.StopACKListener()
// 7. ๅๅธไบไปถ
event := outbox.NewOutboxEvent(
"order-123",
"Order",
"OrderCreated",
[]byte(`{"orderId":"order-123","amount":99.99}`),
)
if err := publisher.PublishEvent(ctx, event); err != nil {
log.Fatalf("Failed to publish event: %v", err)
}
log.Println("โ
Event published successfully")
// โ
ACK ็ปๆ้่ฟ ACK ็ๅฌๅจๅผๆญฅๅค็
// โ
ACK ๆๅๆถ๏ผไบไปถ่ชๅจๆ ่ฎฐไธบ Published
// โ
ACK ๅคฑ่ดฅๆถ๏ผไบไปถไฟๆ Pending๏ผ็ญๅพ
ไธๆฌก้่ฏ
}
2. ไฝฟ็จ NATS EventBus
package main
import (
"context"
"log"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/eventbus"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox/adapters"
)
func main() {
// 1. ๅๅปบ NATS ้
็ฝฎ
natsConfig := &eventbus.NATSConfig{
URL: "nats://localhost:4222",
ClientID: "outbox-service",
ClusterID: "test-cluster",
DurableName: "outbox-durable",
}
// 2. ๅๅปบ NATS EventBus ้้
ๅจ
adapter, err := adapters.NewNATSEventBusAdapter(natsConfig)
if err != nil {
log.Fatalf("Failed to create adapter: %v", err)
}
defer adapter.Close()
// 3-7. ไธ Kafka ็คบไพ็ธๅ
// ...
}
3. ไฝฟ็จๅทฒๆ็ EventBus ๅฎไพ
package main
import (
"github.com/ChenBigdata421/jxt-core/sdk/pkg/eventbus"
"github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox/adapters"
)
func main() {
// 1. ๅๅปบ EventBus ๅฎไพ๏ผKafka ๆ NATS๏ผ
eventBus, err := eventbus.NewKafkaEventBus(kafkaConfig)
if err != nil {
panic(err)
}
// 2. ๅๅปบ้้
ๅจ
adapter := adapters.NewEventBusAdapter(eventBus)
defer adapter.Close()
// 3. ไฝฟ็จ้้
ๅจๅๅปบ Outbox Publisher
// ...
}
๐ ๅทฅไฝๅ็
ๆถๆๅพ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Outbox Publisher โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PublishEvent() โ โ
โ โ โ โ โ
โ โ toEnvelope() โโโ EventPublisher.PublishEnvelope() โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ACK Listener โ โ
โ โ โ โ โ
โ โ GetPublishResultChannel() โโโ handleACKResult() โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ EventBusAdapter โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PublishEnvelope() โ โ
โ โ โ โ โ
โ โ toEventBusEnvelope() โโโ EventBus.PublishEnvelope() โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Result Conversion Loop โ โ
โ โ โ โ โ
โ โ EventBus.GetPublishResultChannel() โ โ
โ โ โ โ โ
โ โ toOutboxPublishResult() โ โ
โ โ โ โ โ
โ โ outboxResultChan โโโ Outbox ACK Listener โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ EventBus (Kafka/NATS) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PublishEnvelope() โโโ AsyncProducer/PublishAsync() โ โ
โ โ โ โ โ
โ โ Success/Error Handler โโโ publishResultChan โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ๆฐๆฎๆต
-
ๅๅธๆต็จ:
OutboxEvent โ Outbox.Envelope โ EventBus.Envelope โ Kafka/NATS
-
ACK ๆต็จ:
Kafka/NATS โ EventBus.PublishResult โ Outbox.PublishResult โ ACK Listener
๐ง API ๆๆกฃ
EventBusAdapter
ๆ้ ๅฝๆฐ
// NewEventBusAdapter ๅๅปบ EventBus ้้
ๅจ
func NewEventBusAdapter(eventBus eventbus.EventBus) *EventBusAdapter
// NewKafkaEventBusAdapter ๅๅปบ Kafka EventBus ้้
ๅจ
func NewKafkaEventBusAdapter(kafkaConfig *eventbus.KafkaConfig) (*EventBusAdapter, error)
// NewNATSEventBusAdapter ๅๅปบ NATS EventBus ้้
ๅจ
func NewNATSEventBusAdapter(natsConfig *eventbus.NATSConfig) (*EventBusAdapter, error)
ๆนๆณ
// PublishEnvelope ๅๅธ Envelope ๆถๆฏๅฐ EventBus
func (a *EventBusAdapter) PublishEnvelope(ctx context.Context, topic string, envelope *outbox.Envelope) error
// GetPublishResultChannel ่ทๅๅผๆญฅๅๅธ็ปๆ้้
func (a *EventBusAdapter) GetPublishResultChannel() <-chan *outbox.PublishResult
// Close ๅ
ณ้ญ้้
ๅจ๏ผ้ๆพ่ตๆบ
func (a *EventBusAdapter) Close() error
// IsStarted ๆฃๆฅ้้
ๅจๆฏๅฆๅทฒๅฏๅจ
func (a *EventBusAdapter) IsStarted() bool
// GetEventBus ่ทๅๅบๅฑ EventBus ๅฎไพ
func (a *EventBusAdapter) GetEventBus() eventbus.EventBus
โ
ๆต่ฏ
่ฟ่กๆต่ฏ๏ผ
cd jxt-core/sdk/pkg/outbox/adapters
go test -v .
ๆต่ฏ็ปๆ๏ผ
=== RUN TestNewEventBusAdapter
--- PASS: TestNewEventBusAdapter (0.10s)
=== RUN TestEventBusAdapter_PublishEnvelope
--- PASS: TestEventBusAdapter_PublishEnvelope (0.10s)
=== RUN TestEventBusAdapter_GetPublishResultChannel_Success
--- PASS: TestEventBusAdapter_GetPublishResultChannel_Success (0.10s)
=== RUN TestEventBusAdapter_GetPublishResultChannel_Failure
--- PASS: TestEventBusAdapter_GetPublishResultChannel_Failure (0.10s)
=== RUN TestEventBusAdapter_Close
--- PASS: TestEventBusAdapter_Close (0.10s)
=== RUN TestEventBusAdapter_GetEventBus
--- PASS: TestEventBusAdapter_GetEventBus (0.10s)
PASS
ok github.com/ChenBigdata421/jxt-core/sdk/pkg/outbox/adapters 0.614s
๐ ็ธๅ
ณๆๆกฃ
../ASYNC_ACK_IMPLEMENTATION_REPORT.md - ๅผๆญฅ ACK ๅค็ๅฎๆฝๆฅๅ
../ASYNC_ACK_HANDLING_ANALYSIS.md - ๅผๆญฅ ACK ๅค็ๅๆๆฅๅ
../../eventbus/README.md - EventBus ๆๆกฃ
๐ฏ ๆไฝณๅฎ่ทต
- ไฝฟ็จๅทฅๅๆนๆณ: ๆจ่ไฝฟ็จ
NewKafkaEventBusAdapter() ๆ NewNATSEventBusAdapter() ๅๅปบ้้
ๅจ
- ๅๆถๅ
ณ้ญ: ไฝฟ็จ
defer adapter.Close() ็กฎไฟ่ตๆบ้ๆพ
- ๅฏๅจ ACK ็ๅฌๅจ: ๅฟ
้กป่ฐ็จ
publisher.StartACKListener(ctx) ๆ่ฝๆฅๆถ ACK ็ปๆ
- ็ๆงๆๆ : ๅฏ็จ
EnableMetrics ็ๆงๅๅธๆๅ็ๅๅปถ่ฟ
- ๅนถๅๅๅธ: ๅฏ็จ
ConcurrentPublish ๆๅๅๅ้
็ๆฌ: v1.0.0
ๆดๆฐๆถ้ด: 2025-10-21
ไฝ่
: Augment Agent