feat: recover from panic
All checks were successful
submodules sync / sync (push) Successful in 1m4s
build / build (push) Successful in 2m21s
build / trigger-build-image (push) Successful in 11s

This commit is contained in:
张泊明518370910136 2025-03-31 05:36:47 -04:00
parent ab41926fc0
commit 4639e84ad5
GPG Key ID: D47306D7062CDA9D
3 changed files with 153 additions and 116 deletions

View File

@ -146,8 +146,18 @@ func mainImpl() (err error) {
} }
func main() { func main() {
if err := mainImpl(); err != nil { var err error
slog.Error("main exit", "error", err) exitCode := 0
os.Exit(1) defer func() {
} if r := recover(); r != nil {
slog.Error("panic recovered", "panic", r)
exitCode = 2
}
if err != nil {
slog.Error("main exit", "error", err)
exitCode = 1
}
os.Exit(exitCode)
}()
err = mainImpl()
} }

View File

@ -22,7 +22,10 @@ func generateStages(confStages []conf.ConfStage, groups []string) (
) { ) {
stages := []stage.Stage{} stages := []stage.Stage{}
existNames := map[string]bool{} existNames := map[string]bool{}
for _, s := range confStages { for i, s := range confStages {
if s.Name == "" {
s.Name = fmt.Sprintf("stage-%d", i)
}
if s.Group != "" { if s.Group != "" {
var ok bool var ok bool
for _, group := range groups { for _, group := range groups {

View File

@ -16,140 +16,164 @@ func Run(stages []Stage) (
var tmpParserResults []ParserResult var tmpParserResults []ParserResult
slog.Info("stage run start") slog.Info("stage run start")
for _, stage := range stages { for _, stage := range stages {
slog.Info("stage start", "name", stage.Name) func() {
slog.Info( defer func() {
"executor run start", if r := recover(); r != nil {
"stageName", stage.Name, slog.Error(
"name", stage.Executor.Name, "stage panic recovered",
) "stageName", stage.Name,
slog.Debug( "panic", r,
"executor run start", )
"stageName", stage.Name, stageResults = append(stageResults, StageResult{
"name", stage.Executor.Name, Name: stage.Name,
"cmds", stage.Executor.Cmds, Results: []ParserResult{
) {
executor, ok := executorMap[stage.Executor.Name] Score: 0,
if !ok { Comment: "JOJ3 internal error. " +
slog.Error( "Please contact the administrator.\n",
"executor not found", },
},
ForceQuit: true,
})
forceQuitStageName = stage.Name
err = fmt.Errorf("panic in stage %s: %v", stage.Name, r)
}
}()
slog.Info("stage start", "name", stage.Name)
slog.Info(
"executor run start",
"stageName", stage.Name, "stageName", stage.Name,
"name", stage.Executor.Name, "name", stage.Executor.Name,
) )
err = fmt.Errorf("executor not found: %s", stage.Executor.Name) slog.Debug(
return stageResults, forceQuitStageName, err "executor run start",
}
executorResults, err = executor.Run(stage.Executor.Cmds)
if err != nil {
slog.Error(
"executor run error",
"stageName", stage.Name, "stageName", stage.Name,
"name", stage.Executor.Name, "name", stage.Executor.Name,
"error", err, "cmds", stage.Executor.Cmds,
) )
return stageResults, forceQuitStageName, err executor, ok := executorMap[stage.Executor.Name]
} if !ok {
for i, executorResult := range executorResults { slog.Error(
"executor not found",
"stageName", stage.Name,
"name", stage.Executor.Name,
)
err = fmt.Errorf("executor not found: %s", stage.Executor.Name)
return
}
executorResults, err = executor.Run(stage.Executor.Cmds)
if err != nil {
slog.Error(
"executor run error",
"stageName", stage.Name,
"name", stage.Executor.Name,
"error", err,
)
return
}
for i, executorResult := range executorResults {
slog.Debug(
"executor run done",
"stageName", stage.Name,
"case", i,
"name", stage.Executor.Name,
"result", executorResult,
)
}
slog.Debug( slog.Debug(
"executor run done", "executor run done",
"stageName", stage.Name, "stageName", stage.Name,
"case", i,
"name", stage.Executor.Name, "name", stage.Executor.Name,
"result", executorResult, "summary", SummarizeExecutorResults(executorResults),
) )
} parserResults = []ParserResult{}
slog.Debug( stageDetail := StageDetail{
"executor run done", Name: stage.Name,
"stageName", stage.Name, CaseDetails: make([]CaseDetail, len(executorResults)),
"name", stage.Executor.Name, }
"summary", SummarizeExecutorResults(executorResults), parserScoresMap := map[string][]int{}
) for _, parser := range stage.Parsers {
parserResults = []ParserResult{} parserScoresMap[parser.Name] = make([]int, len(executorResults))
stageDetail := StageDetail{ }
Name: stage.Name, for _, stageParser := range stage.Parsers {
CaseDetails: make([]CaseDetail, len(executorResults)), slog.Info(
} "parser run start",
parserScoresMap := map[string][]int{}
for _, parser := range stage.Parsers {
parserScoresMap[parser.Name] = make([]int, len(executorResults))
}
for _, stageParser := range stage.Parsers {
slog.Info(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
)
slog.Debug(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
"conf", stageParser.Conf,
)
parser, ok := parserMap[stageParser.Name]
if !ok {
slog.Error(
"parser not found",
"stageName", stage.Name, "stageName", stage.Name,
"name", stageParser.Name, "name", stageParser.Name,
) )
err = fmt.Errorf("parser not found: %s", stageParser.Name) slog.Debug(
return stageResults, forceQuitStageName, err "parser run start",
}
var parserForceQuit bool
tmpParserResults, parserForceQuit, err = parser.Run(
executorResults, stageParser.Conf)
if err != nil {
slog.Error(
"parser run error",
"stageName", stage.Name, "stageName", stage.Name,
"name", stageParser.Name, "name", stageParser.Name,
"error", err, "conf", stageParser.Conf,
) )
forceQuitStageName = stage.Name parser, ok := parserMap[stageParser.Name]
break if !ok {
} slog.Error(
for i, parserResult := range tmpParserResults { "parser not found",
parserScoresMap[stageParser.Name][i] += parserResult.Score "stageName", stage.Name,
} "name", stageParser.Name,
if parserForceQuit { )
slog.Error( err = fmt.Errorf("parser not found: %s", stageParser.Name)
"parser force quit", return
}
var parserForceQuit bool
tmpParserResults, parserForceQuit, err = parser.Run(
executorResults, stageParser.Conf)
if err != nil {
slog.Error(
"parser run error",
"stageName", stage.Name,
"name", stageParser.Name,
"error", err,
)
forceQuitStageName = stage.Name
break
}
for i, parserResult := range tmpParserResults {
parserScoresMap[stageParser.Name][i] += parserResult.Score
}
if parserForceQuit {
slog.Error(
"parser force quit",
"stageName", stage.Name,
"name", stageParser.Name,
)
forceQuitStageName = stage.Name
}
slog.Debug(
"parser run done",
"stageName", stage.Name, "stageName", stage.Name,
"name", stageParser.Name, "name", stageParser.Name,
"results", tmpParserResults,
) )
forceQuitStageName = stage.Name if len(parserResults) == 0 {
} parserResults = tmpParserResults
slog.Debug( } else {
"parser run done", for i := range len(parserResults) {
"stageName", stage.Name, parserResults[i].Score += tmpParserResults[i].Score
"name", stageParser.Name, parserResults[i].Comment += tmpParserResults[i].Comment
"results", tmpParserResults, }
)
if len(parserResults) == 0 {
parserResults = tmpParserResults
} else {
for i := range len(parserResults) {
parserResults[i].Score += tmpParserResults[i].Score
parserResults[i].Comment += tmpParserResults[i].Comment
} }
} }
} for i := range executorResults {
for i := range executorResults { caseDetail := CaseDetail{
caseDetail := CaseDetail{ Index: i,
Index: i, ExecutorResult: executorResults[i],
ExecutorResult: executorResults[i], ParserScores: make(map[string]int),
ParserScores: make(map[string]int), }
for name, scores := range parserScoresMap {
caseDetail.ParserScores[name] = scores[i]
}
stageDetail.CaseDetails[i] = caseDetail
} }
for name, scores := range parserScoresMap { stageResults = append(stageResults, StageResult{
caseDetail.ParserScores[name] = scores[i] Name: stage.Name,
} Results: parserResults,
stageDetail.CaseDetails[i] = caseDetail ForceQuit: forceQuitStageName != "",
} })
stageResults = append(stageResults, StageResult{ slog.Debug("stage done", "name", stage.Name, "stageDetail", stageDetail)
Name: stage.Name, }()
Results: parserResults,
ForceQuit: forceQuitStageName != "",
})
slog.Debug("stage done", "name", stage.Name, "stageDetail", stageDetail)
if forceQuitStageName != "" { if forceQuitStageName != "" {
break break
} }