优化结构
This commit is contained in:
@@ -2,7 +2,6 @@ package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"kra/internal/config"
|
||||
)
|
||||
|
||||
// watchConfig refreshes the in-memory config snapshot on file changes, while
|
||||
@@ -79,10 +80,13 @@ func (d *Data) watchConfig() func() {
|
||||
logger.Error("reload changed config", "mod", "system", "error", loadErr)
|
||||
continue
|
||||
}
|
||||
if next.Data == nil || next.Admin == nil {
|
||||
logger.Error("reload changed config: data and admin configuration are required", "mod", "system")
|
||||
if next.Data == nil {
|
||||
logger.Error("reload changed config: data configuration is required", "mod", "system")
|
||||
continue
|
||||
}
|
||||
if next.Admin == nil {
|
||||
next.Admin = &config.Admin{}
|
||||
}
|
||||
if current := d.runtime.Admin(); current != nil {
|
||||
next.Admin.Storage = current.Storage
|
||||
next.Admin.Email = current.Email
|
||||
|
||||
@@ -13,15 +13,15 @@ import (
|
||||
func TestConfigWatcherStopWaitsForDebouncedReload(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
configPath := filepath.Join(root, "config.yaml")
|
||||
config := []byte("data:\n database:\n driver: sqlite\n path: " + filepath.ToSlash(root) + "\nadmin: {}\n")
|
||||
if err := os.WriteFile(configPath, config, 0o600); err != nil {
|
||||
rawConfig := []byte("data:\n database:\n driver: sqlite\n path: " + filepath.ToSlash(root) + "\nadmin: {}\n")
|
||||
if err := os.WriteFile(configPath, rawConfig, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
runtime := config.NewStore(&config.Config{Data: &config.Data{}, Admin: &config.Admin{ConfigPath: configPath}})
|
||||
started := make(chan struct{})
|
||||
release := make(chan struct{})
|
||||
var startOnce sync.Once
|
||||
stopListener := runtime.Subscribe(func(*config.Data, *config.Admin) {
|
||||
stopListener := runtime.Subscribe(func(*config.Config) {
|
||||
startOnce.Do(func() { close(started) })
|
||||
<-release
|
||||
})
|
||||
@@ -30,7 +30,7 @@ func TestConfigWatcherStopWaitsForDebouncedReload(t *testing.T) {
|
||||
stop := data.watchConfig()
|
||||
|
||||
// A write event schedules the 100ms debounce reload.
|
||||
if err := os.WriteFile(configPath, config, 0o600); err != nil {
|
||||
if err := os.WriteFile(configPath, rawConfig, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
select {
|
||||
|
||||
@@ -78,7 +78,7 @@ extension:
|
||||
if err := os.WriteFile(configPath, []byte(original), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
runtime := config.NewStore(&config.Data{}, &config.Admin{ConfigPath: configPath})
|
||||
runtime := config.NewStore(&config.Config{Data: &config.Data{}, Admin: &config.Admin{ConfigPath: configPath}})
|
||||
data := &Data{runtime: runtime}
|
||||
if err := data.persistDatabaseConfig(&config.Database{Driver: "mysql", Host: "db", Port: "3306", User: "root", Password: "secret", Name: "kra", Config: "parseTime=True"}, "new-key"); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
dataintegration "kra/internal/data/integration"
|
||||
"kra/internal/integration/storage"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"gopkg.in/yaml.v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -59,9 +58,9 @@ func TestStorageIntegrationConfigRoundTrip(t *testing.T) {
|
||||
Qiniu: &config.Qiniu{
|
||||
Zone: "ZoneHuadong", Bucket: "qiniu-bucket", AccessKey: "qiniu-key", SecretKey: "qiniu-secret",
|
||||
},
|
||||
AliyunOss: &config.ObjectStore{
|
||||
AliyunOSS: &config.ObjectStore{
|
||||
Endpoint: "oss-cn-hangzhou.aliyuncs.com", Region: "cn-hangzhou", Bucket: "assets",
|
||||
AccessKey: "aliyun-key", SecretKey: "aliyun-secret", BaseUrl: "https://cdn.example.com", PathPrefix: "uploads",
|
||||
AccessKey: "aliyun-key", SecretKey: "aliyun-secret", BaseURL: "https://cdn.example.com", PathPrefix: "uploads",
|
||||
},
|
||||
Minio: &config.ObjectStore{Endpoint: "127.0.0.1:9000", Bucket: "local", ForcePathStyle: true},
|
||||
}
|
||||
@@ -70,7 +69,7 @@ func TestStorageIntegrationConfigRoundTrip(t *testing.T) {
|
||||
}
|
||||
email := &config.Email{
|
||||
To: "ops@example.com", From: "mailer@example.com", Host: "smtp.example.com",
|
||||
Secret: "smtp-secret", Nickname: "Kra", Port: 465, IsSsl: true,
|
||||
Secret: "smtp-secret", Nickname: "Kra", Port: 465, IsSSL: true,
|
||||
}
|
||||
if err := saveEmailIntegrationConfig(db, email); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -135,7 +134,7 @@ func TestResolveStorageIntegrationConfigMigratesLegacyOnlyOnce(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loaded.Type != "qiniu" || loaded.Qiniu.GetBucket() != "legacy" {
|
||||
if loaded.Type != "qiniu" || loaded.Qiniu.Bucket != "legacy" {
|
||||
t.Fatalf("migrated storage = %#v", loaded)
|
||||
}
|
||||
|
||||
@@ -147,7 +146,7 @@ func TestResolveStorageIntegrationConfigMigratesLegacyOnlyOnce(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loaded.Type != "qiniu" || loaded.Qiniu.GetSecretKey() != "legacy-secret" {
|
||||
if loaded.Type != "qiniu" || loaded.Qiniu.SecretKey != "legacy-secret" {
|
||||
t.Fatalf("database configuration was replaced by legacy config: %#v", loaded)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +154,7 @@ func TestResolveStorageIntegrationConfigMigratesLegacyOnlyOnce(t *testing.T) {
|
||||
func TestMaskStorageSecretsLeavesUnconfiguredProvidersEmpty(t *testing.T) {
|
||||
storage := &config.Storage{
|
||||
Qiniu: &config.Qiniu{},
|
||||
AliyunOss: &config.ObjectStore{SecretKey: "configured-secret"},
|
||||
AliyunOSS: &config.ObjectStore{SecretKey: "configured-secret"},
|
||||
Minio: &config.ObjectStore{},
|
||||
}
|
||||
maskStorageSecrets(storage)
|
||||
@@ -169,7 +168,7 @@ func TestMaskStorageSecretsLeavesUnconfiguredProvidersEmpty(t *testing.T) {
|
||||
|
||||
func TestResolveEmailIntegrationConfigMigratesLegacyOnlyOnce(t *testing.T) {
|
||||
db := openIntegrationConfigTestDB(t)
|
||||
legacy := &config.Email{To: "ops@example.com", From: "old@example.com", Host: "smtp.old.example.com", Secret: "old-secret", Port: 465, IsSsl: true}
|
||||
legacy := &config.Email{To: "ops@example.com", From: "old@example.com", Host: "smtp.old.example.com", Secret: "old-secret", Port: 465, IsSSL: true}
|
||||
loaded, err := resolveEmailIntegrationConfig(db, legacy)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -259,17 +258,9 @@ func TestPersistRuntimeConfigReplacesActiveStorage(t *testing.T) {
|
||||
nextAdmin.Local = &config.Local{StorePath: newRoot, PathPrefix: "new-files"}
|
||||
nextAdmin.Email = &config.Email{
|
||||
To: "ops@example.com", From: "mailer@example.com", Host: "smtp.example.com",
|
||||
Secret: "runtime-secret", Port: 465, IsSsl: true,
|
||||
Secret: "runtime-secret", Port: 465, IsSSL: true,
|
||||
}
|
||||
dataRaw, err := protojson.Marshal(&config.Data{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
adminRaw, err := protojson.Marshal(nextAdmin)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = d.PersistRuntimeConfig(context.Background(), dataRaw, adminRaw); err != nil {
|
||||
if err = d.PersistRuntimeConfig(context.Background(), &config.Config{Data: &config.Data{}, Admin: nextAdmin}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user