Files
go-sip/internal/dispatcher/mq_integration_test.go
T

98 lines
2.5 KiB
Go

//go:build integration
package dispatcher
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"git.ipao.vip/rogee/go-sip/contracts"
"git.ipao.vip/rogee/go-sip/internal/mq"
"git.ipao.vip/rogee/go-sip/internal/store"
)
func TestLocalDispatcherConsumesCommandIntoSQLiteAndPublishesOutbox(t *testing.T) {
url := os.Getenv("RABBITMQ_URL")
if url == "" {
t.Skip("RABBITMQ_URL is not configured")
}
broker, err := mq.OpenWithPrefetch(url, "", 1)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if err := broker.Close(); err != nil {
t.Error(err)
}
})
st, err := store.Open(filepath.Join(t.TempDir(), "dispatcher.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if err := st.Close(); err != nil {
t.Error(err)
}
})
d, err := New(st, broker, time.Now)
if err != nil {
t.Fatal(err)
}
raw, err := contracts.Read("examples/call.execute.json")
if err != nil {
t.Fatal(err)
}
const tenantKey = "tenant-demo-key"
routingKey := "agent-call.tenant." + tenantKey + ".call.execute"
if _, err := broker.DeclareTenantQueue(tenantKey); err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(t.Context(), 20*time.Second)
defer cancel()
consumeDone := make(chan error, 1)
go func() { consumeDone <- d.ConsumeTenant(ctx, broker, tenantKey) }()
if err := broker.Publish(ctx, mq.DefaultExchange, routingKey, raw); err != nil {
t.Fatal(err)
}
deadline := time.Now().Add(10 * time.Second)
for {
var taskCount, outboxCount int
if err := st.DB().QueryRow(`SELECT COUNT(*) FROM tasks`).Scan(&taskCount); err != nil {
t.Fatal(err)
}
if err := st.DB().QueryRow(`SELECT COUNT(*) FROM outbox`).Scan(&outboxCount); err != nil {
t.Fatal(err)
}
if taskCount == 1 && outboxCount >= 1 {
break
}
if time.Now().After(deadline) {
t.Fatalf("command was not persisted: tasks=%d outbox=%d", taskCount, outboxCount)
}
time.Sleep(50 * time.Millisecond)
}
published, err := d.FlushOutbox(ctx, 1)
if err != nil || published != 1 {
t.Fatalf("published=%d err=%v", published, err)
}
cancel()
select {
case <-consumeDone:
case <-time.After(3 * time.Second):
t.Fatal("tenant consumer did not stop")
}
var taskStatus, outboxStatus string
if err := st.DB().QueryRow(`SELECT status FROM tasks LIMIT 1`).Scan(&taskStatus); err != nil {
t.Fatal(err)
}
if err := st.DB().QueryRow(`SELECT status FROM outbox LIMIT 1`).Scan(&outboxStatus); err != nil {
t.Fatal(err)
}
if taskStatus != "accepted" || outboxStatus != "published" {
t.Fatalf("unexpected persisted statuses: task=%q outbox=%q", taskStatus, outboxStatus)
}
}