优化结构
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"kra/app/system/internal/conf"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const integrationKindWebSocket = "websocket"
|
||||
|
||||
// saveWebSocketIntegrationConfig persists the Melody settings in the shared
|
||||
// integration table. It intentionally lives separately from storage/payment
|
||||
// persistence so adding another transport does not expand their API surface.
|
||||
func saveWebSocketIntegrationConfig(db *gorm.DB, config *conf.AdminBackend_WebSocket) error {
|
||||
if config == nil {
|
||||
config = &conf.AdminBackend_WebSocket{}
|
||||
}
|
||||
raw, err := protojson.MarshalOptions{UseProtoNames: true, EmitDefaultValues: true}.Marshal(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode websocket integration configuration: %w", err)
|
||||
}
|
||||
clean := db.Session(&gorm.Session{NewDB: true})
|
||||
var current integrationConfigPO
|
||||
err = clean.Where("kind = ? AND provider = ?", integrationKindWebSocket, "melody").First(¤t).Error
|
||||
switch {
|
||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
||||
return clean.Create(&integrationConfigPO{Kind: integrationKindWebSocket, Provider: "melody", Enabled: config.Enabled, Config: string(raw)}).Error
|
||||
case err != nil:
|
||||
return err
|
||||
default:
|
||||
return clean.Model(¤t).Updates(map[string]any{"enabled": config.Enabled, "config": string(raw)}).Error
|
||||
}
|
||||
}
|
||||
|
||||
func loadWebSocketIntegrationConfig(db *gorm.DB) (*conf.AdminBackend_WebSocket, bool, error) {
|
||||
var row integrationConfigPO
|
||||
err := db.Session(&gorm.Session{NewDB: true}).Where("kind = ? AND provider = ?", integrationKindWebSocket, "melody").First(&row).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !json.Valid([]byte(row.Config)) {
|
||||
return nil, false, errors.New("invalid websocket integration configuration")
|
||||
}
|
||||
config := &conf.AdminBackend_WebSocket{}
|
||||
if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal([]byte(row.Config), config); err != nil {
|
||||
return nil, false, fmt.Errorf("decode websocket integration configuration: %w", err)
|
||||
}
|
||||
config.Enabled = row.Enabled
|
||||
return config, true, nil
|
||||
}
|
||||
|
||||
func resolveWebSocketIntegrationConfig(db *gorm.DB, legacy *conf.AdminBackend_WebSocket) (*conf.AdminBackend_WebSocket, error) {
|
||||
clean := db.Session(&gorm.Session{NewDB: true})
|
||||
if !clean.Migrator().HasTable(&integrationConfigPO{}) {
|
||||
if legacy == nil {
|
||||
return &conf.AdminBackend_WebSocket{}, nil
|
||||
}
|
||||
return proto.Clone(legacy).(*conf.AdminBackend_WebSocket), nil
|
||||
}
|
||||
config, found, err := loadWebSocketIntegrationConfig(clean)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if found {
|
||||
return config, nil
|
||||
}
|
||||
if legacy == nil {
|
||||
legacy = &conf.AdminBackend_WebSocket{}
|
||||
}
|
||||
if err = saveWebSocketIntegrationConfig(clean, legacy); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, _, err = loadWebSocketIntegrationConfig(clean)
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (d *Data) PersistWebSocketConfig(ctx context.Context, config *conf.AdminBackend_WebSocket) error {
|
||||
if !d.databaseReady.Load() {
|
||||
return errors.New("database is not initialized")
|
||||
}
|
||||
db := d.gormDB.WithContext(ctx)
|
||||
if !db.Migrator().HasTable(&integrationConfigPO{}) {
|
||||
return errors.New("integration configuration table does not exist")
|
||||
}
|
||||
return saveWebSocketIntegrationConfig(db, config)
|
||||
}
|
||||
Reference in New Issue
Block a user