更新依赖和调整目录结构,未修改模块

This commit is contained in:
2026-09-14 22:17:59 +08:00
parent 63aeedc2fe
commit 13e4b8e363
70 changed files with 3092 additions and 90 deletions

View File

@@ -0,0 +1,130 @@
package config
import (
"net"
"os"
"strings"
"time"
ftsService "bsm/full/module/base/fts/service"
mgtService "bsm/full/module/base/mgt/service"
passportService "bsm/full/module/base/passport/service"
senderService "bsm/full/module/base/sender/service"
walletService "bsm/full/module/finance/wallet/service"
"git.apinb.com/bsm-sdk/core/conf"
"git.apinb.com/bsm-sdk/core/env"
"git.apinb.com/bsm-sdk/core/printer"
coreVars "git.apinb.com/bsm-sdk/core/vars"
)
// SrvConfig is the ecmall aggregate configuration. It only carries the
// services registered by pkgs/ecmall: the e-commerce domain (address, mall,
// market, order), the payment domain (wallet), the platform domain (ads, cms,
// feedback, fts, logs, mgt) and the base support services they rely on
// (initial, passport, sender). Modules that are not part of ecmall keep their
// own configuration in their own process.
type SrvConfig struct {
conf.Base `yaml:",inline"`
Server ServerConfig `yaml:"Server"`
Authorization AuthorizationConfig `yaml:"Authorization"`
Databases *conf.DBConf `yaml:"Databases"`
MicroService *conf.MicroServiceConf `yaml:"MicroService"`
Rpc map[string]conf.RpcConf `yaml:"Rpc"`
Apm *conf.ApmConf `yaml:"APM"`
Etcd *conf.EtcdConf `yaml:"Etcd"`
Services []string `yaml:"Services"`
Fts *ftsService.Config `yaml:"Fts"`
Mgt *mgtService.Config `yaml:"Mgt"`
Passport *passportService.Config `yaml:"Passport"`
Sender *senderService.Config `yaml:"Sender"`
Wallet *walletService.Config `yaml:"Wallet"`
}
type ListenerConfig struct {
BindIP string `yaml:"BindIP"`
Port string `yaml:"Port"`
Addr string `yaml:"-"`
}
type ServerConfig struct {
GRPC ListenerConfig `yaml:"GRPC"`
HTTP ListenerConfig `yaml:"HTTP"`
}
type AuthorizationConfig struct {
Key string `yaml:"Key"`
Expire int64 `yaml:"Expire"`
Anonymous []string `yaml:"Anonymous"`
}
var Spec SrvConfig
func New(serviceKey string) {
conf.New(serviceKey, &Spec)
normalizeListener(&Spec.Server.GRPC)
normalizeListener(&Spec.Server.HTTP)
if Spec.Server.GRPC.Addr == Spec.Server.HTTP.Addr {
panic("gRPC and HTTP listeners must use different addresses")
}
if strings.TrimSpace(Spec.Authorization.Key) == "" {
panic("Authorization.Key must not be empty")
}
keyLength := len(Spec.Authorization.Key)
if keyLength != 16 && keyLength != 24 && keyLength != 32 {
panic("Authorization.Key must contain 16, 24, or 32 bytes")
}
if Spec.Authorization.Expire <= 0 {
panic("Authorization.Expire must be greater than zero")
}
env.NewEnv().JwtSecretKey = Spec.Authorization.Key
coreVars.JwtExpire = time.Duration(Spec.Authorization.Expire) * time.Second
// Keep the embedded base address meaningful for module configurations that
// still consume it, while ecmall itself uses the two explicit listeners.
Spec.BindIP, Spec.Port, Spec.Addr = Spec.Server.HTTP.BindIP, Spec.Server.HTTP.Port, Spec.Server.HTTP.Addr
conf.NotNil(Spec.Service, Spec.Cache)
assignSharedConfig()
conf.PrintInfo(Spec.Server.GRPC.Addr)
printer.Info("gRPC Address: %s", Spec.Server.GRPC.Addr)
printer.Info("HTTP Address: %s", Spec.Server.HTTP.Addr)
}
func normalizeListener(listener *ListenerConfig) {
listener.Port = conf.CheckPort(listener.Port)
listener.BindIP = conf.CheckIP(listener.BindIP)
listener.Addr = net.JoinHostPort(listener.BindIP, listener.Port)
}
func assignSharedConfig() {
if Spec.Fts != nil {
Spec.Fts.Base, Spec.Fts.Databases, Spec.Fts.Rpc, Spec.Fts.Apm, Spec.Fts.Etcd = Spec.Base, Spec.Databases, Spec.Rpc, Spec.Apm, Spec.Etcd
}
if Spec.Mgt != nil {
Spec.Mgt.Base, Spec.Mgt.Databases, Spec.Mgt.Rpc, Spec.Mgt.Apm, Spec.Mgt.Etcd = Spec.Base, Spec.Databases, Spec.Rpc, Spec.Apm, Spec.Etcd
}
if Spec.Passport != nil {
Spec.Passport.Base, Spec.Passport.Databases, Spec.Passport.MicroService, Spec.Passport.Rpc, Spec.Passport.Apm, Spec.Passport.Etcd = Spec.Base, Spec.Databases, Spec.MicroService, Spec.Rpc, Spec.Apm, Spec.Etcd
}
if Spec.Sender != nil {
Spec.Sender.Base, Spec.Sender.Databases, Spec.Sender.MicroService, Spec.Sender.Rpc, Spec.Sender.Apm, Spec.Sender.Etcd = Spec.Base, Spec.Databases, Spec.MicroService, Spec.Rpc, Spec.Apm, Spec.Etcd
}
if Spec.Wallet != nil {
Spec.Wallet.Base, Spec.Wallet.Databases, Spec.Wallet.MicroService, Spec.Wallet.Rpc, Spec.Wallet.Apm, Spec.Wallet.Etcd = Spec.Base, Spec.Databases, Spec.MicroService, Spec.Rpc, Spec.Apm, Spec.Etcd
}
}
func Enabled(name string) bool {
if raw := strings.TrimSpace(os.Getenv("BSM_SERVICES")); raw != "" {
for _, selected := range strings.Split(raw, ",") {
if strings.EqualFold(strings.TrimSpace(selected), name) || strings.EqualFold(strings.TrimSpace(selected), "all") {
return true
}
}
return false
}
for _, service := range Spec.Services {
if strings.EqualFold(strings.TrimSpace(service), name) || strings.EqualFold(strings.TrimSpace(service), "all") {
return true
}
}
return false
}

View File

@@ -0,0 +1,53 @@
package config
import (
"os"
"path/filepath"
"sort"
"strings"
"testing"
"go.yaml.in/yaml/v3"
)
// ecmallServices is the aggregate registry of pkgs/ecmall. Keep it in sync with
// the services table in internal/service.
var ecmallServices = []string{"address", "ads", "cms", "feedback", "fts", "initial", "logs", "mgt", "mall", "market", "order", "passport", "sender", "wallet"}
func TestEcmallDevConfig(t *testing.T) {
data, err := os.ReadFile(filepath.Join("..", "..", "etc", "default_dev.yaml"))
if err != nil {
t.Fatal(err)
}
var cfg SrvConfig
if err := yaml.Unmarshal(data, &cfg); err != nil {
t.Fatal(err)
}
if len(cfg.Services) == 0 {
t.Fatal("services must not be empty")
}
if cfg.Server.GRPC.Port == "" || cfg.Server.HTTP.Port == "" || cfg.Server.GRPC.Port == cfg.Server.HTTP.Port {
t.Fatal("separate gRPC and HTTP ports are required")
}
if cfg.Authorization.Key == "" || cfg.Authorization.Expire <= 0 {
t.Fatal("authorization key and expiration are required")
}
keyLength := len(cfg.Authorization.Key)
if keyLength != 16 && keyLength != 24 && keyLength != 32 {
t.Fatal("authorization key must be compatible with the JWT issuer")
}
if cfg.Fts == nil || cfg.Mgt == nil || cfg.Passport == nil || cfg.Sender == nil || cfg.Wallet == nil {
t.Fatal("service-specific configuration is incomplete")
}
enabled := make([]string, 0, len(cfg.Services))
for _, service := range cfg.Services {
enabled = append(enabled, strings.ToLower(strings.TrimSpace(service)))
}
sort.Strings(enabled)
expected := append([]string(nil), ecmallServices...)
sort.Strings(expected)
if strings.Join(enabled, ",") != strings.Join(expected, ",") {
t.Fatalf("ecmall must only enable %v, got %v", expected, enabled)
}
}