chore: 初始化 eightbf-analysis-go(对齐 Java 会商作业服务)
Go 实现 /api/v1/analysis 契约、Demo/Live Worker、DeerFlow SSE;含设计文档与冒烟脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
0c45b86d67
29 files changed
+3789
No files matched your search
@@ -0,0 +1,144 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config 运行配置(环境变量优先,与 Java EBA_* / analysis.* 对齐)。
|
||||
type Config struct {
|
||||
Port int
|
||||
|
||||
// MySQL:优先 EBA_DB_DSN;否则用 HOST/PORT/NAME/USER/PASSWORD 拼,或解析 JDBC URL。
|
||||
DBDSN string
|
||||
|
||||
AnalysisMode string // live | demo
|
||||
AuthEnabled bool
|
||||
DemoEnabled bool
|
||||
LivePollMS int
|
||||
DemoTickMS int
|
||||
|
||||
DeerFlowBaseURL string
|
||||
DeerFlowUser string
|
||||
DeerFlowPassword string
|
||||
DeerFlowCoordinator string
|
||||
DeerFlowStreamIdleTimeout int // 毫秒
|
||||
}
|
||||
|
||||
// Load 从环境变量加载;缺省贴近本机联调。
|
||||
func Load() Config {
|
||||
c := Config{
|
||||
Port: envInt("SERVER_PORT", 18097),
|
||||
AnalysisMode: env("ANALYSIS_MODE", "live"),
|
||||
AuthEnabled: envBool("ANALYSIS_AUTH_ENABLED", false),
|
||||
DemoEnabled: envBool("EBA_WORKER_DEMO_ENABLED", false),
|
||||
LivePollMS: envInt("EBA_WORKER_LIVE_POLL_MS", 1000),
|
||||
DemoTickMS: envInt("EBA_WORKER_TICK_MS", 400),
|
||||
DeerFlowBaseURL: strings.TrimRight(env("EBA_DF_BASE_URL", "http://127.0.0.1:8001"), "/"),
|
||||
DeerFlowUser: env("EBA_DF_USER", "admin"),
|
||||
DeerFlowPassword: env("EBA_DF_PASSWORD", "123ewq"),
|
||||
DeerFlowCoordinator: env("EBA_DF_COORDINATOR", "roundtable-coordinator"),
|
||||
DeerFlowStreamIdleTimeout: envInt("EBA_DF_STREAM_IDLE_TIMEOUT_MS", 180000),
|
||||
}
|
||||
c.DBDSN = resolveDSN()
|
||||
// live 默认关掉 demo;显式 ANALYSIS_MODE=demo 时打开假进度
|
||||
if c.AnalysisMode == "demo" {
|
||||
c.DemoEnabled = true
|
||||
}
|
||||
if c.AnalysisMode == "live" && !envExplicit("EBA_WORKER_DEMO_ENABLED") {
|
||||
c.DemoEnabled = false
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func resolveDSN() string {
|
||||
if d := strings.TrimSpace(os.Getenv("EBA_DB_DSN")); d != "" {
|
||||
return ensureMultiStatements(d)
|
||||
}
|
||||
user := env("EBA_DB_USER", "eba")
|
||||
pass := env("EBA_DB_PASSWORD", "eba_local_dev")
|
||||
jdbc := strings.TrimSpace(os.Getenv("EBA_DB_URL"))
|
||||
if jdbc != "" {
|
||||
if dsn, ok := jdbcToDSN(jdbc, user, pass); ok {
|
||||
return dsn
|
||||
}
|
||||
}
|
||||
host := env("EBA_DB_HOST", "127.0.0.1")
|
||||
port := env("EBA_DB_PORT", "3306")
|
||||
name := env("EBA_DB_NAME", "eightbf_analysis")
|
||||
return user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + name +
|
||||
"?parseTime=true&loc=Asia%2FShanghai&charset=utf8mb4&multiStatements=true"
|
||||
}
|
||||
|
||||
// jdbcToDSN 把 Java 的 jdbc:mysql://host:port/db?... 转成 Go driver DSN。
|
||||
func jdbcToDSN(jdbc, user, pass string) (string, bool) {
|
||||
s := strings.TrimPrefix(jdbc, "jdbc:mysql://")
|
||||
if s == jdbc {
|
||||
return "", false
|
||||
}
|
||||
hostPath := s
|
||||
query := ""
|
||||
if i := strings.Index(s, "?"); i >= 0 {
|
||||
hostPath = s[:i]
|
||||
query = s[i+1:]
|
||||
}
|
||||
host := hostPath
|
||||
db := "eightbf_analysis"
|
||||
if i := strings.Index(hostPath, "/"); i >= 0 {
|
||||
host = hostPath[:i]
|
||||
db = hostPath[i+1:]
|
||||
}
|
||||
params := "parseTime=true&loc=Asia%2FShanghai&charset=utf8mb4&multiStatements=true"
|
||||
_ = query // Java JDBC 专用参数不照搬
|
||||
return user + ":" + pass + "@tcp(" + host + ")/" + db + "?" + params, true
|
||||
}
|
||||
|
||||
func ensureMultiStatements(dsn string) string {
|
||||
if strings.Contains(dsn, "multiStatements=") {
|
||||
return dsn
|
||||
}
|
||||
if strings.Contains(dsn, "?") {
|
||||
return dsn + "&multiStatements=true"
|
||||
}
|
||||
return dsn + "?multiStatements=true"
|
||||
}
|
||||
|
||||
func env(k, def string) string {
|
||||
if v := strings.TrimSpace(os.Getenv(k)); v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func envExplicit(k string) bool {
|
||||
_, ok := os.LookupEnv(k)
|
||||
return ok
|
||||
}
|
||||
|
||||
func envBool(k string, def bool) bool {
|
||||
v := strings.TrimSpace(os.Getenv(k))
|
||||
if v == "" {
|
||||
return def
|
||||
}
|
||||
switch strings.ToLower(v) {
|
||||
case "1", "true", "yes", "on":
|
||||
return true
|
||||
case "0", "false", "no", "off":
|
||||
return false
|
||||
default:
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
func envInt(k string, def int) int {
|
||||
v := strings.TrimSpace(os.Getenv(k))
|
||||
if v == "" {
|
||||
return def
|
||||
}
|
||||
n, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
return n
|
||||
}
|
||||
Reference in new issue
Block a user