feat: 增强桌面启动失败提示与测试覆盖
This commit is contained in:
96
backend/cmd/desktop/startup_error.go
Normal file
96
backend/cmd/desktop/startup_error.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type startupPhase string
|
||||
|
||||
const (
|
||||
phaseConfig startupPhase = "config"
|
||||
phaseSingleton startupPhase = "singleton"
|
||||
phasePort startupPhase = "port"
|
||||
phaseLogger startupPhase = "logger"
|
||||
phaseDatabase startupPhase = "database"
|
||||
phaseMigration startupPhase = "migration"
|
||||
phaseAdapter startupPhase = "adapter"
|
||||
phaseStaticResource startupPhase = "static"
|
||||
phaseServer startupPhase = "server"
|
||||
phaseTray startupPhase = "tray"
|
||||
)
|
||||
|
||||
type startupError struct {
|
||||
phase startupPhase
|
||||
message string
|
||||
cause error
|
||||
}
|
||||
|
||||
func newStartupError(phase startupPhase, message string, cause error) *startupError {
|
||||
return &startupError{
|
||||
phase: phase,
|
||||
message: redactSensitive(message),
|
||||
cause: cause,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *startupError) Error() string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
if e.cause == nil {
|
||||
return fmt.Sprintf("%s: %s", e.phase, e.message)
|
||||
}
|
||||
return fmt.Sprintf("%s: %s: %s", e.phase, e.message, redactSensitive(e.cause.Error()))
|
||||
}
|
||||
|
||||
func (e *startupError) Unwrap() error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
return e.cause
|
||||
}
|
||||
|
||||
func (e *startupError) Phase() string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
return string(e.phase)
|
||||
}
|
||||
|
||||
func (e *startupError) UserMessage() string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
return redactSensitive(e.message)
|
||||
}
|
||||
|
||||
var sensitiveReplacers = []struct {
|
||||
pattern *regexp.Regexp
|
||||
replacement string
|
||||
}{
|
||||
{regexp.MustCompile(`(?i)(password\s*[:=]\s*)[^\s,;&]+`), `${1}<redacted>`},
|
||||
{regexp.MustCompile(`(?i)(api[_-]?key\s*[:=]\s*)[^\s,;&]+`), `${1}<redacted>`},
|
||||
{regexp.MustCompile(`(?i)(secret\s*[:=]\s*)[^\s,;&]+`), `${1}<redacted>`},
|
||||
{regexp.MustCompile(`([^\s:/]+):([^\s@]+)@tcp\(`), `${1}:<redacted>@tcp(`},
|
||||
{regexp.MustCompile(`(://[^\s:/]+):([^\s@]+)@`), `${1}:<redacted>@`},
|
||||
}
|
||||
|
||||
func redactSensitive(s string) string {
|
||||
for _, replacer := range sensitiveReplacers {
|
||||
s = replacer.pattern.ReplaceAllString(s, replacer.replacement)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func startupTitle() string {
|
||||
return appName + " 启动失败"
|
||||
}
|
||||
|
||||
func startupServerErrorMessage() string {
|
||||
return "后端服务启动失败\n\n请检查端口占用、网络权限或查看日志获取更多信息"
|
||||
}
|
||||
|
||||
func startupInternalErrorMessage() string {
|
||||
return "应用初始化失败\n\n请查看日志或重新安装应用"
|
||||
}
|
||||
Reference in New Issue
Block a user