优化结构

This commit is contained in:
Yvan
2026-08-30 01:08:10 +08:00
parent 509df03d61
commit e0c35e4e9b
23 changed files with 1513 additions and 38 deletions
+1 -1
View File
@@ -74,7 +74,7 @@ func (t *ConnectivityTester) restoreMaskedSecrets(kind, provider string, values
}
for key := range masked {
value, _ := values[key].(string)
if !config.IsMaskedSecret(strings.TrimSpace(value)) {
if strings.TrimSpace(value) != config.MaskedSecret {
continue
}
prior, _ := currentValues[key].(string)
@@ -0,0 +1,94 @@
package integration
import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"strconv"
"strings"
"testing"
"time"
integrationbiz "kra/internal/biz/integration"
)
type kafkaConnectivityRepo struct{}
func (*kafkaConnectivityRepo) ListIntegrationConfigs(context.Context, string) ([]*integrationbiz.IntegrationConfig, error) {
return nil, nil
}
func (*kafkaConnectivityRepo) FindIntegrationConfig(context.Context, string, string) (*integrationbiz.IntegrationConfig, error) {
return nil, nil
}
func (*kafkaConnectivityRepo) SaveIntegrationConfig(context.Context, *integrationbiz.IntegrationConfig) error {
return nil
}
func (*kafkaConnectivityRepo) DeleteIntegrationConfig(context.Context, string, string) error {
return nil
}
func TestKafkaConnectivityIntegration(t *testing.T) {
rawBrokers := strings.TrimSpace(os.Getenv("KRA_KAFKA_TEST_BROKERS"))
if rawBrokers == "" {
t.Skip("KRA_KAFKA_TEST_BROKERS is not configured")
}
brokers := make([]string, 0)
for _, broker := range strings.Split(rawBrokers, ",") {
if broker = strings.TrimSpace(broker); broker != "" {
brokers = append(brokers, broker)
}
}
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "kafka")
values["brokers"] = brokers
values["client_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
values["group_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
testMQConnectivityIntegration(t, "kafka", values)
}
func TestEMQXConnectivityIntegration(t *testing.T) {
broker := strings.TrimSpace(os.Getenv("KRA_EMQX_TEST_BROKER"))
if broker == "" {
t.Skip("KRA_EMQX_TEST_BROKER is not configured")
}
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "emqx")
values["broker"] = broker
values["client_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
testMQConnectivityIntegration(t, "emqx", values)
}
func TestRabbitMQConnectivityIntegration(t *testing.T) {
address := strings.TrimSpace(os.Getenv("KRA_RABBITMQ_TEST_ADDR"))
if address == "" {
t.Skip("KRA_RABBITMQ_TEST_ADDR is not configured")
}
host, portText, err := net.SplitHostPort(address)
if err != nil {
t.Fatal(err)
}
port, err := strconv.Atoi(portText)
if err != nil {
t.Fatal(err)
}
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "rabbitmq")
values["host"] = host
values["port"] = port
testMQConnectivityIntegration(t, "rabbitmq", values)
}
func testMQConnectivityIntegration(t *testing.T, provider string, values map[string]any) {
t.Helper()
raw, err := json.Marshal(values)
if err != nil {
t.Fatal(err)
}
usecase := integrationbiz.NewIntegrationConfigUsecase(&kafkaConnectivityRepo{}, NewConnectivityTester(nil))
if err = usecase.Test(context.Background(), &integrationbiz.IntegrationConfig{
Kind: integrationbiz.IntegrationKindMQ,
Provider: provider,
Values: raw,
}); err != nil {
t.Fatalf("test JSON-decoded %s defaults: %v", provider, err)
}
}
+11
View File
@@ -46,6 +46,17 @@ func TestConnectivityTesterRestoreMaskedSecrets(t *testing.T) {
}
})
t.Run("keeps an empty optional secret", func(t *testing.T) {
values := map[string]any{"password": ""}
if err := tester.restoreMaskedSecrets("mq", "kafka", values); err != nil {
t.Fatalf("restoreMaskedSecrets() error = %v", err)
}
if got := values["password"]; got != "" {
t.Fatalf("password = %q, want empty value", got)
}
})
t.Run("does not treat non-secret fields as masked secrets", func(t *testing.T) {
values := map[string]any{
"username": "******",
+10 -1
View File
@@ -279,7 +279,13 @@ func configStrings(values map[string]any, key string) []string {
}
stringsValue, ok := values[key].([]string)
if ok {
return append([]string(nil), stringsValue...)
result := make([]string, 0, len(stringsValue))
for _, item := range stringsValue {
if value := strings.TrimSpace(item); value != "" {
result = append(result, value)
}
}
return result
}
return nil
}
@@ -327,6 +333,9 @@ func (r *Reloadable) retryOnce() {
client := r.clientLocked(provider)
if client != nil && client.Connected() {
if r.pending[provider] {
if retryAt := r.nextRetry[provider]; !retryAt.IsZero() && now.Before(retryAt) {
continue
}
if err := r.reconcileProviderLocked(provider); err != nil {
r.scheduleRetryLocked(provider, config.Values)
}
+67
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"log/slog"
"strings"
"testing"
"time"
@@ -209,3 +210,69 @@ func TestReloadableLegacySubscribeDoesNotLeaveOfflineDeclaration(t *testing.T) {
t.Fatalf("offline legacy declaration remained: %#v", r.subscriptions[ProviderEMQX])
}
}
func TestReloadableExposesKafkaNamedClient(t *testing.T) {
r := &Reloadable{}
client := r.Client(" KAFKA ")
if client == nil {
t.Fatal("kafka named client is nil")
}
if client.Connected() {
t.Fatal("unconfigured kafka named client reported connected")
}
}
func TestConfigStringsDecodesJSONArrays(t *testing.T) {
values := map[string]any{"brokers": []any{" kafka-1:9092 ", "", "kafka-2:9092"}}
brokers := configStrings(values, "brokers")
if len(brokers) != 2 || brokers[0] != "kafka-1:9092" || brokers[1] != "kafka-2:9092" {
t.Fatalf("brokers = %#v", brokers)
}
}
func TestConfigStringsNormalizesTypedSlices(t *testing.T) {
values := map[string]any{"brokers": []string{" kafka-1:9092 ", "", "kafka-2:9092"}}
brokers := configStrings(values, "brokers")
if len(brokers) != 2 || brokers[0] != "kafka-1:9092" || brokers[1] != "kafka-2:9092" {
t.Fatalf("brokers = %#v", brokers)
}
}
func TestReloadableRejectsUnsupportedKafkaQoS(t *testing.T) {
r := &Reloadable{}
err := r.Register(platformmq.SubscriptionSet{
Owner: "orders",
Provider: ProviderKafka,
Topics: []platformmq.TopicSubscription{{Topic: "orders.created", QoS: platformmq.ExactlyOnce, Handler: func(context.Context, platformmq.Message) {}}},
})
if err == nil || !strings.Contains(err.Error(), "supports qos 0 or 1") {
t.Fatalf("Register() error = %v", err)
}
}
func TestRetryOnceHonorsPendingSubscriptionDeadline(t *testing.T) {
client := &fakeClient{}
r := &Reloadable{
clients: map[string]platformmq.Client{ProviderKafka: client},
configs: map[string]runtimeconfig.Config{
ProviderKafka: {Kind: "mq", Provider: ProviderKafka, Enabled: true},
},
subscriptions: map[string]map[string]map[string]subscription{
ProviderKafka: {
"orders.created": {"orders": {qos: platformmq.AtLeastOnce, handler: func(context.Context, platformmq.Message) {}}},
},
},
bindings: map[string]map[string]byte{ProviderKafka: {}},
pending: map[string]bool{ProviderKafka: true},
nextRetry: map[string]time.Time{ProviderKafka: time.Now().Add(time.Minute)},
}
r.retryOnce()
if len(client.subscribed) != 0 {
t.Fatalf("subscription retried before deadline: %v", client.subscribed)
}
r.nextRetry[ProviderKafka] = time.Now().Add(-time.Second)
r.retryOnce()
if len(client.subscribed) != 1 || client.subscribed[0] != "orders.created" {
t.Fatalf("subscription was not retried after deadline: %v", client.subscribed)
}
}