outbox for gateways
This commit is contained in:
143
api/ledger/internal/service/ledger/outbox_reliable_test.go
Normal file
143
api/ledger/internal/service/ledger/outbox_reliable_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package ledger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tech/sendico/ledger/storage/model"
|
||||
me "github.com/tech/sendico/pkg/messaging/envelope"
|
||||
pmessagingreliable "github.com/tech/sendico/pkg/messaging/reliable"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func TestLedgerReliableProducerDispatchesLegacyOutboxRecords(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
event := &model.OutboxEvent{
|
||||
EventID: "entry-1",
|
||||
Subject: ledgerOutboxSubject,
|
||||
Payload: []byte(`{"journalEntryRef":"abc123"}`),
|
||||
Attempts: 0,
|
||||
}
|
||||
event.SetID(bson.NewObjectID())
|
||||
event.OrganizationRef = bson.NewObjectID()
|
||||
|
||||
store := &recordingLedgerOutboxStore{
|
||||
pending: []*model.OutboxEvent{event},
|
||||
}
|
||||
direct := &stubDirectProducer{}
|
||||
producer, _, err := newLedgerReliableProducer(logger, direct, store, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
processed, err := producer.DispatchPending(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, processed)
|
||||
|
||||
require.Len(t, direct.envelopes, 1)
|
||||
env := direct.envelopes[0]
|
||||
assert.Equal(t, outboxPublisherSender, env.GetSender())
|
||||
assert.Equal(t, "ledger_outbox_sent", env.GetSignature().ToString())
|
||||
|
||||
var message ledgerOutboxMessage
|
||||
require.NoError(t, json.Unmarshal(env.GetData(), &message))
|
||||
assert.Equal(t, event.EventID, message.EventID)
|
||||
assert.Equal(t, event.Subject, message.Subject)
|
||||
assert.Equal(t, event.OrganizationRef.Hex(), message.OrganizationRef)
|
||||
assert.JSONEq(t, `{"journalEntryRef":"abc123"}`, string(message.Payload))
|
||||
|
||||
require.Len(t, store.markedSent, 1)
|
||||
assert.Equal(t, *event.GetID(), store.markedSent[0])
|
||||
assert.Empty(t, store.markedFailed)
|
||||
assert.Empty(t, store.incremented)
|
||||
}
|
||||
|
||||
func TestLedgerReliableProducerMarksFailedOnDispatchError(t *testing.T) {
|
||||
logger := zap.NewNop()
|
||||
event := &model.OutboxEvent{
|
||||
EventID: "entry-2",
|
||||
Subject: ledgerOutboxSubject,
|
||||
Payload: []byte(`{"journalEntryRef":"xyz789"}`),
|
||||
Attempts: pmessagingreliable.DefaultSettings().MaxAttempts - 1,
|
||||
}
|
||||
event.SetID(bson.NewObjectID())
|
||||
event.OrganizationRef = bson.NewObjectID()
|
||||
|
||||
store := &recordingLedgerOutboxStore{
|
||||
pending: []*model.OutboxEvent{event},
|
||||
}
|
||||
direct := &stubDirectProducer{err: errors.New("publish failed")}
|
||||
producer, _, err := newLedgerReliableProducer(logger, direct, store, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
processed, err := producer.DispatchPending(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, processed)
|
||||
|
||||
require.Len(t, store.incremented, 1)
|
||||
assert.Equal(t, *event.GetID(), store.incremented[0])
|
||||
require.Len(t, store.markedFailed, 1)
|
||||
assert.Equal(t, *event.GetID(), store.markedFailed[0])
|
||||
assert.Empty(t, store.markedSent)
|
||||
}
|
||||
|
||||
type recordingLedgerOutboxStore struct {
|
||||
mu sync.Mutex
|
||||
|
||||
pending []*model.OutboxEvent
|
||||
|
||||
markedSent []bson.ObjectID
|
||||
markedFailed []bson.ObjectID
|
||||
incremented []bson.ObjectID
|
||||
}
|
||||
|
||||
func (s *recordingLedgerOutboxStore) Create(context.Context, *model.OutboxEvent) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingLedgerOutboxStore) ListPending(context.Context, int) ([]*model.OutboxEvent, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
events := s.pending
|
||||
s.pending = nil
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (s *recordingLedgerOutboxStore) MarkSent(_ context.Context, eventRef bson.ObjectID, _ time.Time) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.markedSent = append(s.markedSent, eventRef)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingLedgerOutboxStore) MarkFailed(_ context.Context, eventRef bson.ObjectID) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.markedFailed = append(s.markedFailed, eventRef)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingLedgerOutboxStore) IncrementAttempts(_ context.Context, eventRef bson.ObjectID) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.incremented = append(s.incremented, eventRef)
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubDirectProducer struct {
|
||||
mu sync.Mutex
|
||||
envelopes []me.Envelope
|
||||
err error
|
||||
}
|
||||
|
||||
func (p *stubDirectProducer) SendMessage(env me.Envelope) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
p.envelopes = append(p.envelopes, env)
|
||||
return p.err
|
||||
}
|
||||
Reference in New Issue
Block a user