优化结构

This commit is contained in:
Yvan
2026-08-24 13:25:16 +08:00
parent 7a9a738c6a
commit 0b6b8ddf1a
72 changed files with 2475 additions and 1443 deletions
+19 -45
View File
@@ -9,29 +9,23 @@ import (
"path/filepath"
"strconv"
"kra/internal/conf"
"kra/internal/config"
"kra/internal/integration/storage"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"gopkg.in/yaml.v3"
"gorm.io/gorm"
)
func protoMap(message proto.Message) (map[string]any, error) {
raw, err := (protojson.MarshalOptions{
UseProtoNames: true,
EmitDefaultValues: true,
}).Marshal(message)
func configMap(input any) (map[string]any, error) {
raw, err := yaml.Marshal(input)
if err != nil {
return nil, err
}
var value map[string]any
if err = json.Unmarshal(raw, &value); err != nil {
var output map[string]any
if err = yaml.Unmarshal(raw, &output); err != nil {
return nil, err
}
delete(value, "config_path")
return value, nil
return output, nil
}
func setYAMLMapping(node *yaml.Node, key string, value any) error {
@@ -60,9 +54,8 @@ func setYAMLMapping(node *yaml.Node, key string, value any) error {
}
// mergeYAMLNode updates values produced from the runtime configuration while
// retaining keys that are not represented by the protobuf and comments that
// were already present in the user's config file. Replacing an entire mapping
// with protojson output would discard configuration hints and extension keys.
// retaining keys that are not represented by the typed configuration and
// comments that were already present in the user's config file.
func mergeYAMLNode(dst, src *yaml.Node) {
if dst.Kind == yaml.MappingNode && src.Kind == yaml.MappingNode {
for i := 0; i+1 < len(src.Content); i += 2 {
@@ -138,7 +131,7 @@ func deleteYAMLMapping(node *yaml.Node, keys ...string) {
}
}
func setServerHTTPPort(document *yaml.Node, port int32) error {
func setServerHTTPPort(document *yaml.Node, port int) error {
if port <= 0 {
return nil
}
@@ -156,13 +149,13 @@ func (d *Data) persistConfig() error {
return d.persistConfigValues(dataConfig, adminConfig)
}
func (d *Data) persistConfigValues(dataConfig *conf.Data, adminConfig *conf.AdminBackend) error {
func (d *Data) persistConfigValues(dataConfig *config.Data, adminConfig *config.Admin) error {
d.configMu.Lock()
defer d.configMu.Unlock()
return d.persistConfigValuesLocked(dataConfig, adminConfig)
}
func (d *Data) persistConfigValuesLocked(dataConfig *conf.Data, adminConfig *conf.AdminBackend) error {
func (d *Data) persistConfigValuesLocked(dataConfig *config.Data, adminConfig *config.Admin) error {
if adminConfig == nil || adminConfig.ConfigPath == "" {
return nil
}
@@ -175,14 +168,14 @@ func (d *Data) persistConfigValuesLocked(dataConfig *conf.Data, adminConfig *con
if err = yaml.Unmarshal(raw, &document); err != nil {
return err
}
dataValue, err := protoMap(dataConfig)
dataValue, err := configMap(dataConfig)
if err != nil {
return err
}
fileAdmin := cloneAdminConfig(adminConfig)
fileAdmin.Storage = nil
fileAdmin.Email = nil
adminValue, err := protoMap(fileAdmin)
adminValue, err := configMap(fileAdmin)
if err != nil {
return err
}
@@ -207,7 +200,7 @@ func (d *Data) persistConfigValuesLocked(dataConfig *conf.Data, adminConfig *con
// partially populated runtime config back over the template: doing so removes
// all omitted/default settings from data and admin and leaves the next startup
// with no visible configuration.
func (d *Data) persistDatabaseConfig(database *conf.Data_Database, signingKey string) error {
func (d *Data) persistDatabaseConfig(database *config.Database, signingKey string) error {
d.configMu.Lock()
defer d.configMu.Unlock()
@@ -227,11 +220,8 @@ func (d *Data) persistDatabaseConfig(database *conf.Data_Database, signingKey st
if err != nil {
return err
}
// Do not marshal the init request through protojson here. Proto3 omits
// empty and zero values, which makes a merge retain stale values from the
// template (an empty database password is the common example). Update the
// fields owned by the init page explicitly and leave advanced database,
// Redis, Mongo, admin and server settings untouched.
// Update the fields owned by the init page explicitly and leave advanced
// database, Redis, Mongo, admin and server settings untouched.
databaseValue := map[string]any{
"driver": database.Driver,
"source": source,
@@ -428,7 +418,7 @@ func (d *Data) reloadConfig(ctx context.Context) error {
closeCandidate = false
candidateDBListAccepted = true
candidateRedisAccepted = true
d.runtime.Replace(next.Data, next.Admin)
d.runtime.Replace(next)
if d.integrations != nil {
d.integrations.Replace(integrationConfigs)
}
@@ -438,22 +428,6 @@ func (d *Data) reloadConfig(ctx context.Context) error {
return nil
}
func readBootstrap(configPath string) (*conf.Bootstrap, error) {
raw, err := os.ReadFile(configPath)
if err != nil {
return nil, err
}
var plain map[string]any
if err = yaml.Unmarshal(raw, &plain); err != nil {
return nil, err
}
encoded, err := json.Marshal(plain)
if err != nil {
return nil, err
}
var next conf.Bootstrap
if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(encoded, &next); err != nil {
return nil, err
}
return &next, nil
func readBootstrap(configPath string) (*config.Config, error) {
return config.Load(configPath)
}