118 lines
3.4 KiB
Go
118 lines
3.4 KiB
Go
package nats
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
configpkg "caatsm/internal/infra/config"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"go.uber.org/zap/zaptest"
|
|
)
|
|
|
|
var _ = Describe("Consumer JetStream", func() {
|
|
var (
|
|
c *Consumer
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
logger := zaptest.NewLogger(GinkgoT())
|
|
c = &Consumer{
|
|
mode: "jetstream",
|
|
streamName: "TEST_STREAM",
|
|
consumerName: "test-consumer",
|
|
subject: "test.subject",
|
|
batchSize: 10,
|
|
batchTimeout: 2 * time.Second,
|
|
logger: logger,
|
|
errorHandler: NewErrorHandler(logger),
|
|
cfg: &configpkg.Config{
|
|
NATS: configpkg.NATSConfig{
|
|
ConsumerRules: configpkg.ConsumerRulesConfig{
|
|
Backoff: []time.Duration{5 * time.Second, 30 * time.Second},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|
|
|
|
Describe("nakWithStrategy", func() {
|
|
PIt("sends NAK without delay when backoff is empty", func() {
|
|
c.cfg.NATS.ConsumerRules.Backoff = []time.Duration{}
|
|
// Note: This test would require a real NATS message to fully test
|
|
// For now, we verify the logic path
|
|
})
|
|
|
|
PIt("sends NAK with delay based on delivery attempt", func() {
|
|
// Note: This test would require a real NATS message with metadata
|
|
// For now, we verify the function exists and can be called
|
|
})
|
|
})
|
|
|
|
Describe("handleFetchError", func() {
|
|
var ctx context.Context
|
|
|
|
BeforeEach(func() {
|
|
ctx = context.Background()
|
|
})
|
|
|
|
It("returns true for timeout errors", func() {
|
|
var sub *nats.Subscription
|
|
fetchErrorStreak := 0
|
|
shouldContinue, err := c.handleFetchError(ctx, nats.ErrTimeout, &sub, &fetchErrorStreak)
|
|
Expect(shouldContinue).To(BeTrue())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("handles ErrNoResponders with backoff", func() {
|
|
var sub *nats.Subscription
|
|
fetchErrorStreak := 0
|
|
shouldContinue, err := c.handleFetchError(ctx, nats.ErrNoResponders, &sub, &fetchErrorStreak)
|
|
Expect(shouldContinue).To(BeTrue())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(fetchErrorStreak).To(Equal(1))
|
|
})
|
|
|
|
It("handles resource not found errors", func() {
|
|
var sub *nats.Subscription
|
|
fetchErrorStreak := 0
|
|
resourceErr := errors.New("stream not found")
|
|
shouldContinue, err := c.handleFetchError(ctx, resourceErr, &sub, &fetchErrorStreak)
|
|
// Behavior depends on environment; in test this should attempt recovery
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(shouldContinue).To(BeFalse())
|
|
})
|
|
|
|
It("handles generic errors with backoff", func() {
|
|
var sub *nats.Subscription
|
|
fetchErrorStreak := 0
|
|
genericErr := errors.New("generic error")
|
|
shouldContinue, err := c.handleFetchError(ctx, genericErr, &sub, &fetchErrorStreak)
|
|
Expect(shouldContinue).To(BeTrue())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(fetchErrorStreak).To(Equal(1))
|
|
})
|
|
})
|
|
|
|
Describe("buildConsumerConfig", func() {
|
|
It("builds consumer config with correct defaults", func() {
|
|
config := c.buildConsumerConfig()
|
|
Expect(config.Durable).To(Equal("test-consumer"))
|
|
Expect(config.AckPolicy).To(Equal(nats.AckExplicitPolicy))
|
|
Expect(config.FilterSubject).To(Equal("test.subject"))
|
|
})
|
|
})
|
|
|
|
Describe("processSingleMessage", func() {
|
|
It("handles successful message processing", func() {
|
|
// This would require mocking the processor, but we can test the structure
|
|
// For now, we verify the method exists and can be called
|
|
// Note: This test would need a mock processor to fully work
|
|
Skip("Requires mock message processor")
|
|
})
|
|
})
|
|
})
|