adapters

package
v1.1.64 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README ยถ

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          โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
ๆ•ฐๆฎๆต
  1. ๅ‘ๅธƒๆต็จ‹:

    OutboxEvent โ†’ Outbox.Envelope โ†’ EventBus.Envelope โ†’ Kafka/NATS
    
  2. 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 ๆ–‡ๆกฃ

๐ŸŽฏ ๆœ€ไฝณๅฎž่ทต

  1. ไฝฟ็”จๅทฅๅŽ‚ๆ–นๆณ•: ๆŽจ่ไฝฟ็”จ NewKafkaEventBusAdapter() ๆˆ– NewNATSEventBusAdapter() ๅˆ›ๅปบ้€‚้…ๅ™จ
  2. ๅŠๆ—ถๅ…ณ้—ญ: ไฝฟ็”จ defer adapter.Close() ็กฎไฟ่ต„ๆบ้‡Šๆ”พ
  3. ๅฏๅŠจ ACK ็›‘ๅฌๅ™จ: ๅฟ…้กป่ฐƒ็”จ publisher.StartACKListener(ctx) ๆ‰่ƒฝๆŽฅๆ”ถ ACK ็ป“ๆžœ
  4. ็›‘ๆŽงๆŒ‡ๆ ‡: ๅฏ็”จ EnableMetrics ็›‘ๆŽงๅ‘ๅธƒๆˆๅŠŸ็އๅ’Œๅปถ่ฟŸ
  5. ๅนถๅ‘ๅ‘ๅธƒ: ๅฏ็”จ ConcurrentPublish ๆๅ‡ๅžๅ้‡

็‰ˆๆœฌ: v1.0.0
ๆ›ดๆ–ฐๆ—ถ้—ด: 2025-10-21
ไฝœ่€…: Augment Agent

Documentation ยถ

Index ยถ

Constants ยถ

This section is empty.

Variables ยถ

This section is empty.

Functions ยถ

This section is empty.

Types ยถ

type EventBusAdapter ยถ

type EventBusAdapter struct {
	// contains filtered or unexported fields
}

EventBusAdapter EventBus ้€‚้…ๅ™จ ๅฐ† jxt-core/sdk/pkg/eventbus.EventBus ้€‚้…ไธบ outbox.EventPublisher ๆŽฅๅฃ

ๅŠŸ่ƒฝ๏ผš 1. โœ… ่ฝฌๆข Outbox Envelope ไธบ EventBus Envelope 2. โœ… ่ฝฌๆข EventBus PublishResult ไธบ Outbox PublishResult 3. โœ… ่‡ชๅŠจๅฏๅŠจ ACK ็ป“ๆžœ่ฝฌๆข goroutine 4. โœ… ็บฟ็จ‹ๅฎ‰ๅ…จ๏ผŒๆ”ฏๆŒๅนถๅ‘่ฐƒ็”จ

ไฝฟ็”จ็คบไพ‹๏ผš

// 1. ๅˆ›ๅปบ EventBus ๅฎžไพ‹
eventBus, err := eventbus.NewKafkaEventBus(kafkaConfig)
if err != nil {
    panic(err)
}

// 2. ๅˆ›ๅปบ้€‚้…ๅ™จ
adapter := NewEventBusAdapter(eventBus)

// 3. ๅˆ›ๅปบ Outbox Publisher
publisher := outbox.NewOutboxPublisher(repo, adapter, topicMapper, config)

// 4. ๅฏๅŠจ ACK ็›‘ๅฌๅ™จ
publisher.StartACKListener(ctx)
defer publisher.StopACKListener()

// 5. ๅ‘ๅธƒไบ‹ไปถ
event := outbox.NewOutboxEvent(...)
publisher.PublishEvent(ctx, event)

func NewEventBusAdapter ยถ

func NewEventBusAdapter(eventBus eventbus.EventBus) *EventBusAdapter

NewEventBusAdapter ๅˆ›ๅปบ EventBus ้€‚้…ๅ™จ

ๅ‚ๆ•ฐ๏ผš

eventBus: EventBus ๅฎžไพ‹๏ผˆKafka ๆˆ– NATS๏ผ‰

่ฟ”ๅ›ž๏ผš

*EventBusAdapter: ้€‚้…ๅ™จๅฎžไพ‹

ๆณจๆ„๏ผš

  • ้€‚้…ๅ™จไผš่‡ชๅŠจๅฏๅŠจ ACK ็ป“ๆžœ่ฝฌๆข goroutine
  • ไฝฟ็”จๅฎŒๆฏ•ๅŽๅบ”่ฏฅ่ฐƒ็”จ Close() ้‡Šๆ”พ่ต„ๆบ

func NewKafkaEventBusAdapter ยถ

func NewKafkaEventBusAdapter(kafkaConfig *eventbus.KafkaConfig) (*EventBusAdapter, error)

NewKafkaEventBusAdapter ๅˆ›ๅปบ Kafka EventBus ้€‚้…ๅ™จ

ๅ‚ๆ•ฐ๏ผš

kafkaConfig: Kafka ้…็ฝฎ

่ฟ”ๅ›ž๏ผš

*EventBusAdapter: ้€‚้…ๅ™จๅฎžไพ‹
error: ๅˆ›ๅปบๅคฑ่ดฅๆ—ถ่ฟ”ๅ›ž้”™่ฏฏ

ไฝฟ็”จ็คบไพ‹๏ผš

adapter, err := NewKafkaEventBusAdapter(kafkaConfig)
if err != nil {
    panic(err)
}
defer adapter.Close()

func NewNATSEventBusAdapter ยถ

func NewNATSEventBusAdapter(natsConfig *eventbus.NATSConfig) (*EventBusAdapter, error)

NewNATSEventBusAdapter ๅˆ›ๅปบ NATS EventBus ้€‚้…ๅ™จ

ๅ‚ๆ•ฐ๏ผš

natsConfig: NATS ้…็ฝฎ

่ฟ”ๅ›ž๏ผš

*EventBusAdapter: ้€‚้…ๅ™จๅฎžไพ‹
error: ๅˆ›ๅปบๅคฑ่ดฅๆ—ถ่ฟ”ๅ›ž้”™่ฏฏ

ไฝฟ็”จ็คบไพ‹๏ผš

adapter, err := NewNATSEventBusAdapter(natsConfig)
if err != nil {
    panic(err)
}
defer adapter.Close()

func (*EventBusAdapter) Close ยถ

func (a *EventBusAdapter) Close() error

Close ๅ…ณ้—ญ้€‚้…ๅ™จ๏ผŒ้‡Šๆ”พ่ต„ๆบใ€‚ๅบ”่ฏฅๅœจๅบ”็”จๅ…ณ้—ญๆ—ถ่ฐƒ็”จใ€‚

PR2-core (Task 4, Step 4 โ€” D9 ownership split): Close returns its OWN teardown error honestly and does NOT close the injected bus ("don't close what you don't own"). The bus is injected via NewEventBusAdapter; the orchestrator (e.g. the outbox consumer) owns the bus lifecycle โ€” it calls bus.Close() and surfaces the terminal error for the non-zero exit (spec ยง3.3). This adapter's terminal error lives on the bus and is surfaced by the bus owner, NOT here.

Deterministic join (replaces the old time.Sleep(100ms), ce-doc-review #2): close(stopChan) signals ALL conversion loops (global + per-tenant) to exit via their <-stopChan cases, then loopsWg.Wait() joins them. A single Sleep could never deterministically join the per-tenant loops spawned by GetTenantPublishResultChannel.

Today the join+close can't fail, so the return is nil โ€” but the signature stays honest (never swallow a future join/close error to nil).

func (*EventBusAdapter) GetEventBus ยถ

func (a *EventBusAdapter) GetEventBus() eventbus.EventBus

GetEventBus ่Žทๅ–ๅบ•ๅฑ‚ EventBus ๅฎžไพ‹ ็”จไบŽ้œ€่ฆ็›ดๆŽฅ่ฎฟ้—ฎ EventBus ็š„ๅœบๆ™ฏ

func (*EventBusAdapter) GetPublishResultChannel ยถ

func (a *EventBusAdapter) GetPublishResultChannel() <-chan *outbox.PublishResult

GetPublishResultChannel ๅฎž็Žฐ outbox.EventPublisher ๆŽฅๅฃ ่Žทๅ–ๅผ‚ๆญฅๅ‘ๅธƒ็ป“ๆžœ้€š้“

่ฟ”ๅ›ž๏ผš

<-chan *outbox.PublishResult: ๅช่ฏป็š„ๅ‘ๅธƒ็ป“ๆžœ้€š้“

func (*EventBusAdapter) GetRegisteredTenants ยถ added in v1.1.22

func (a *EventBusAdapter) GetRegisteredTenants() []int

GetRegisteredTenants ่Žทๅ–ๆ‰€ๆœ‰ๅทฒๆณจๅ†Œ็š„็งŸๆˆทIDๅˆ—่กจ ๅง”ๆ‰˜็ป™ๅบ•ๅฑ‚ EventBus ๅฎž็Žฐ

func (*EventBusAdapter) GetTenantPublishResultChannel ยถ added in v1.1.22

func (a *EventBusAdapter) GetTenantPublishResultChannel(tenantID int) <-chan *outbox.PublishResult

GetTenantPublishResultChannel ่Žทๅ–็งŸๆˆทไธ“ๅฑž็š„ๅผ‚ๆญฅๅ‘ๅธƒ็ป“ๆžœ้€š้“๏ผˆๅคš็งŸๆˆทๆจกๅผ๏ผ‰ ่ฟ”ๅ›žไธ€ไธช่ฝฌๆขๅŽ็š„ Outbox PublishResult ้€š้“

ๆณจๆ„๏ผšๆญคๆ–นๆณ•่ฟ”ๅ›ž็š„ๆ˜ฏ EventBus ็š„็งŸๆˆท้€š้“๏ผŒ้œ€่ฆ่ฐƒ็”จ่€…่‡ช่กŒ่ฝฌๆข็ฑปๅž‹ ๆŽจ่ไฝฟ็”จ CreateTenantResultChannel() ๆ–นๆณ•๏ผŒๅฎƒไผš่‡ชๅŠจๅˆ›ๅปบ่ฝฌๆข้€š้“

func (*EventBusAdapter) IsStarted ยถ

func (a *EventBusAdapter) IsStarted() bool

IsStarted ๆฃ€ๆŸฅ้€‚้…ๅ™จๆ˜ฏๅฆๅทฒๅฏๅŠจ

func (*EventBusAdapter) PublishEnvelope ยถ

func (a *EventBusAdapter) PublishEnvelope(ctx context.Context, topic string, envelope *outbox.Envelope) error

PublishEnvelope ๅฎž็Žฐ outbox.EventPublisher ๆŽฅๅฃ ๅ‘ๅธƒ Envelope ๆถˆๆฏๅˆฐ EventBus

ๅ‚ๆ•ฐ๏ผš

ctx: ไธŠไธ‹ๆ–‡
topic: ็›ฎๆ ‡ topic
envelope: Outbox Envelope

่ฟ”ๅ›ž๏ผš

error: ๅ‘ๅธƒๅคฑ่ดฅๆ—ถ่ฟ”ๅ›ž้”™่ฏฏ๏ผˆๆณจๆ„๏ผš็ซ‹ๅณ่ฟ”ๅ›ž๏ผŒไธ็ญ‰ๅพ… ACK๏ผ‰

func (*EventBusAdapter) RegisterTenant ยถ added in v1.1.22

func (a *EventBusAdapter) RegisterTenant(tenantID int, bufferSize int) error

RegisterTenant ๆณจๅ†Œ็งŸๆˆท๏ผˆๅˆ›ๅปบ็งŸๆˆทไธ“ๅฑž็š„ ACK Channel๏ผ‰ ๅง”ๆ‰˜็ป™ๅบ•ๅฑ‚ EventBus ๅฎž็Žฐ

func (*EventBusAdapter) UnregisterTenant ยถ added in v1.1.22

func (a *EventBusAdapter) UnregisterTenant(tenantID int) error

UnregisterTenant ๆณจ้”€็งŸๆˆท๏ผˆๅ…ณ้—ญๅนถๆธ…็†็งŸๆˆท็š„ ACK Channel๏ผ‰ ๅง”ๆ‰˜็ป™ๅบ•ๅฑ‚ EventBus ๅฎž็Žฐ

type EventHandler ยถ added in v1.1.47

type EventHandler func(ctx context.Context, envelope *outbox.Envelope) error

EventHandler ่ฟ›็จ‹ๅ†…ไบ‹ไปถๅค„็†ๅ™จ

type InProcessEventPublisher ยถ added in v1.1.47

type InProcessEventPublisher struct {
	// contains filtered or unexported fields
}

InProcessEventPublisher ่ฟ›็จ‹ๅ†…ไบ‹ไปถๅ‘ๅธƒๅ™จ๏ผŒๅฎž็Žฐ outbox.EventPublisher ๆŽฅๅฃใ€‚ ไธŽ EventBusAdapter๏ผˆKafka/NATS๏ผ‰ๅฏน็งฐ๏ผŒๅฐ†ไบ‹ไปถๆดพๅ‘ๅˆฐ่ฟ›็จ‹ๅ†…ๆณจๅ†Œ็š„ Go handler ่€Œ้žๅค–้ƒจๆถˆๆฏๆ€ป็บฟใ€‚

ไฝฟ็”จๅœบๆ™ฏ๏ผšๅพฎๆœๅŠกๅ†…้ƒจ้ข†ๅŸŸไบ‹ไปถๆดพๅ‘๏ผˆๅฆ‚ IAM ่ฎพๅค‡็ฎก็†๏ผ‰๏ผŒไบ‹ไปถไธ่ทจๆœๅŠกใ€ไธ็ป่ฟ‡ brokerใ€‚

ไฝฟ็”จ็คบไพ‹่ง examples/evidence_management_adapter.go ๅบ•้ƒจ็š„ InProcessEventPublisher ็คบไพ‹ใ€‚

func NewInProcessEventPublisher ยถ added in v1.1.47

func NewInProcessEventPublisher(opts ...InProcessOption) *InProcessEventPublisher

func (*InProcessEventPublisher) Close ยถ added in v1.1.47

func (p *InProcessEventPublisher) Close() error

Close ๅ…ณ้—ญๅ‘ๅธƒๅ™จใ€‚ๅฏๅฎ‰ๅ…จๅคšๆฌก่ฐƒ็”จ๏ผˆsendMu + closed ไฟ่ฏๅน‚็ญ‰๏ผ‰ใ€‚ๅœจ sendMu ไธ‹ๅ…ณ้—ญ resultChan๏ผŒไธŽ sendResult ไบ’ๆ–ฅ๏ผŒไปŽ็ป“ๆž„ไธŠๆถˆ้™ค close-vs-send ๆ•ฐๆฎ็ซžไบ‰ใ€‚

func (*InProcessEventPublisher) GetPublishResultChannel ยถ added in v1.1.47

func (p *InProcessEventPublisher) GetPublishResultChannel() <-chan *outbox.PublishResult

GetPublishResultChannel ๅฎž็Žฐ outbox.EventPublisher ๆŽฅๅฃ

func (*InProcessEventPublisher) IsSyncSemantics ยถ added in v1.1.58

func (*InProcessEventPublisher) IsSyncSemantics()

IsSyncSemantics marks InProcessEventPublisher as a sync-semantics publisher. PublishEnvelope runs all registered handlers synchronously and returns when done.

func (*InProcessEventPublisher) PublishEnvelope ยถ added in v1.1.47

func (p *InProcessEventPublisher) PublishEnvelope(ctx context.Context, topic string, envelope *outbox.Envelope) error

PublishEnvelope ๅฎž็Žฐ outbox.EventPublisher ๆŽฅๅฃใ€‚ ๅŒๆญฅ่ฐƒ็”จ่ฏฅ topic ไธ‹็š„ๆ‰€ๆœ‰ handler๏ผŒๅ…จ้ƒจๅฎŒๆˆๅŽๅ‘้€ ACK resultใ€‚ ๆ‰€ๆœ‰ handler ้ƒฝไผš่ขซ่ฐƒ็”จ๏ผˆไธๅ› ไธญ้€”ๅคฑ่ดฅ่€Œ็Ÿญ่ทฏ๏ผ‰๏ผŒ่ฟ”ๅ›ž็ฌฌไธ€ไธช้‡ๅˆฐ็š„ errorใ€‚

func (*InProcessEventPublisher) RegisterHandler ยถ added in v1.1.47

func (p *InProcessEventPublisher) RegisterHandler(topic string, handler EventHandler)

RegisterHandler ๆณจๅ†Œไบ‹ไปถๅค„็†ๅ™จ๏ผˆ็บฟ็จ‹ๅฎ‰ๅ…จ๏ผ‰ใ€‚ๅŒไธ€ topic ๅฏๆณจๅ†Œๅคšไธช handler๏ผŒๆŒ‰ๆณจๅ†Œ้กบๅบไพๆฌก่ฐƒ็”จใ€‚ ๅฟ…้กปๅœจ Scheduler ๅฏๅŠจๅ‰่ฐƒ็”จใ€‚

type InProcessOption ยถ added in v1.1.47

type InProcessOption func(*InProcessEventPublisher)

InProcessOption ่ฟ›็จ‹ๅ†…ๅ‘ๅธƒๅ™จ้…็ฝฎ้€‰้กน

func WithBufferSize ยถ added in v1.1.47

func WithBufferSize(n int) InProcessOption

WithBufferSize ่ฎพ็ฝฎ ACK result channel ็ผ“ๅ†ฒๅŒบๅคงๅฐ๏ผŒ้ป˜่ฎค 1000

Directories ยถ

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL