优化结构
This commit is contained in:
@@ -2,19 +2,27 @@ package mq
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"kra/internal/integration/runtimeconfig"
|
||||
platformmq "kra/pkg/mq"
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
subscribed []string
|
||||
unsubscribed []string
|
||||
handlers map[string]platformmq.Handler
|
||||
}
|
||||
|
||||
func (*fakeClient) Publish(context.Context, string, []byte, byte, bool) error { return nil }
|
||||
func (f *fakeClient) Subscribe(_ context.Context, topic string, _ byte, _ platformmq.Handler) error {
|
||||
func (f *fakeClient) Subscribe(_ context.Context, topic string, _ byte, handler platformmq.Handler) error {
|
||||
f.subscribed = append(f.subscribed, topic)
|
||||
if f.handlers == nil {
|
||||
f.handlers = make(map[string]platformmq.Handler)
|
||||
}
|
||||
f.handlers[topic] = handler
|
||||
return nil
|
||||
}
|
||||
func (f *fakeClient) Unsubscribe(_ context.Context, topics ...string) error {
|
||||
@@ -28,7 +36,11 @@ func TestReloadableTracksSubscriptions(t *testing.T) {
|
||||
client := &fakeClient{}
|
||||
r := &Reloadable{
|
||||
clients: map[string]platformmq.Client{ProviderEMQX: client},
|
||||
subscriptions: make(map[string]map[string]subscription),
|
||||
configs: map[string]runtimeconfig.Config{ProviderEMQX: {Kind: "mq", Provider: ProviderEMQX, Enabled: true}},
|
||||
subscriptions: make(map[string]map[string]map[string]subscription),
|
||||
bindings: make(map[string]map[string]byte),
|
||||
pending: make(map[string]bool),
|
||||
nextRetry: make(map[string]time.Time),
|
||||
}
|
||||
handler := func(context.Context, platformmq.Message) {}
|
||||
if err := r.Subscribe(context.Background(), "orders/+/paid", platformmq.AtLeastOnce, handler); err != nil {
|
||||
@@ -47,15 +59,92 @@ func TestReloadableTracksSubscriptions(t *testing.T) {
|
||||
|
||||
func TestReloadableRestoresSubscriptions(t *testing.T) {
|
||||
client := &fakeClient{}
|
||||
r := &Reloadable{subscriptions: map[string]map[string]subscription{
|
||||
r := &Reloadable{subscriptions: map[string]map[string]map[string]subscription{
|
||||
ProviderEMQX: {
|
||||
"orders/+/paid": {qos: platformmq.AtLeastOnce, handler: func(context.Context, platformmq.Message) {}},
|
||||
"orders/+/paid": {
|
||||
"orders": {qos: platformmq.AtLeastOnce, handler: func(context.Context, platformmq.Message) {}},
|
||||
},
|
||||
},
|
||||
}}
|
||||
if err := r.restoreSubscriptionsLocked(ProviderEMQX, client); err != nil {
|
||||
bindings, err := r.restoreSubscriptionsLocked(ProviderEMQX, client)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(client.subscribed) != 1 || client.subscribed[0] != "orders/+/paid" {
|
||||
t.Fatalf("restored subscriptions = %v", client.subscribed)
|
||||
}
|
||||
if bindings["orders/+/paid"] != platformmq.AtLeastOnce {
|
||||
t.Fatalf("restored binding qos = %d", bindings["orders/+/paid"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReloadableRegistersWhileOfflineAndRestoresLater(t *testing.T) {
|
||||
client := &fakeClient{}
|
||||
r := &Reloadable{
|
||||
clients: make(map[string]platformmq.Client),
|
||||
configs: map[string]runtimeconfig.Config{ProviderEMQX: {Kind: "mq", Provider: ProviderEMQX, Enabled: true}},
|
||||
subscriptions: make(map[string]map[string]map[string]subscription),
|
||||
bindings: make(map[string]map[string]byte),
|
||||
pending: make(map[string]bool),
|
||||
nextRetry: make(map[string]time.Time),
|
||||
logger: slog.Default(),
|
||||
}
|
||||
called := make(chan struct{}, 1)
|
||||
err := r.Register(platformmq.SubscriptionSet{
|
||||
Owner: "orders",
|
||||
Provider: ProviderEMQX,
|
||||
Topics: []platformmq.TopicSubscription{{Topic: "orders.created", QoS: platformmq.AtLeastOnce, Handler: func(context.Context, platformmq.Message) { called <- struct{}{} }}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !r.pending[ProviderEMQX] {
|
||||
t.Fatal("offline subscription was not marked pending")
|
||||
}
|
||||
r.clients[ProviderEMQX] = client
|
||||
if err = r.reconcileProviderLocked(ProviderEMQX); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(client.subscribed) != 1 || client.subscribed[0] != "orders.created" {
|
||||
t.Fatalf("restored subscriptions = %v", client.subscribed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReloadableDispatchesSameTopicToMultipleOwners(t *testing.T) {
|
||||
client := &fakeClient{}
|
||||
r := &Reloadable{
|
||||
clients: map[string]platformmq.Client{ProviderEMQX: client},
|
||||
configs: map[string]runtimeconfig.Config{ProviderEMQX: {Kind: "mq", Provider: ProviderEMQX, Enabled: true}},
|
||||
subscriptions: make(map[string]map[string]map[string]subscription),
|
||||
bindings: make(map[string]map[string]byte),
|
||||
pending: make(map[string]bool),
|
||||
nextRetry: make(map[string]time.Time),
|
||||
logger: slog.Default(),
|
||||
}
|
||||
first, second := make(chan struct{}, 1), make(chan struct{}, 1)
|
||||
for _, set := range []platformmq.SubscriptionSet{
|
||||
{Owner: "orders", Provider: ProviderEMQX, Topics: []platformmq.TopicSubscription{{Topic: "events.created", Handler: func(context.Context, platformmq.Message) { first <- struct{}{} }}}},
|
||||
{Owner: "audit", Provider: ProviderEMQX, Topics: []platformmq.TopicSubscription{{Topic: "events.created", Handler: func(context.Context, platformmq.Message) { second <- struct{}{} }}}},
|
||||
} {
|
||||
if err := r.Register(set); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := r.reconcileProviderLocked(ProviderEMQX); err != nil {
|
||||
t.Fatalf("explicit reconcile failed: %v", err)
|
||||
}
|
||||
if len(client.subscribed) != 1 {
|
||||
t.Fatalf("broker subscriptions = %v, want one shared topic; desired=%#v bindings=%#v clients=%#v", client.subscribed, r.subscriptions, r.bindings, r.clients)
|
||||
}
|
||||
client.handlers["events.created"](context.Background(), platformmq.Message{Topic: "events.created"})
|
||||
select {
|
||||
case <-first:
|
||||
default:
|
||||
t.Fatal("orders handler was not called")
|
||||
}
|
||||
select {
|
||||
case <-second:
|
||||
default:
|
||||
t.Fatal("audit handler was not called")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user