feat: a new status for canceled workflow run

This commit is contained in:
Fu Diwei
2025-01-22 02:47:56 +08:00
parent 8dc86209df
commit 79c1da6d14
20 changed files with 280 additions and 104 deletions

View File

@@ -134,7 +134,7 @@ func (a *applyNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workflo
renewalInterval := time.Duration(currentNodeConfig.SkipBeforeExpiryDays) * time.Hour * 24
expirationTime := time.Until(lastCertificate.ExpireAt)
if lastCertificate != nil && expirationTime > renewalInterval {
return true, fmt.Sprintf("已申请过证书,且证书尚未临近过期(到期尚余 %d 天,距 %d 天时续期)", int(expirationTime.Hours()/24), currentNodeConfig.SkipBeforeExpiryDays)
return true, fmt.Sprintf("已申请过证书,且证书尚未临近过期(到期尚余 %d 天,预计距 %d 天时续期)", int(expirationTime.Hours()/24), currentNodeConfig.SkipBeforeExpiryDays)
}
}

View File

@@ -19,15 +19,15 @@ func NewWorkflowProcessor(workflow *domain.Workflow) *workflowProcessor {
}
}
func (w *workflowProcessor) Log(ctx context.Context) []domain.WorkflowRunLog {
return w.logs
}
func (w *workflowProcessor) Run(ctx context.Context) error {
ctx = setContextWorkflowId(ctx, w.workflow.Id)
return w.processNode(ctx, w.workflow.Content)
}
func (w *workflowProcessor) GetRunLogs() []domain.WorkflowRunLog {
return w.logs
}
func (w *workflowProcessor) processNode(ctx context.Context, node *domain.WorkflowNode) error {
current := node
for current != nil {
@@ -39,26 +39,26 @@ func (w *workflowProcessor) processNode(ctx context.Context, node *domain.Workfl
}
}
var runErr error
var processor nodes.NodeProcessor
var runErr error
for {
if current.Type == domain.WorkflowNodeTypeBranch || current.Type == domain.WorkflowNodeTypeExecuteResultBranch {
break
if current.Type != domain.WorkflowNodeTypeBranch && current.Type != domain.WorkflowNodeTypeExecuteResultBranch {
processor, runErr = nodes.GetProcessor(current)
if runErr != nil {
break
}
runErr = processor.Run(ctx)
log := processor.Log(ctx)
if log != nil {
w.logs = append(w.logs, *log)
}
if runErr != nil {
break
}
}
processor, runErr = nodes.GetProcessor(current)
if runErr != nil {
break
}
runErr = processor.Run(ctx)
log := processor.Log(ctx)
if log != nil {
w.logs = append(w.logs, *log)
}
if runErr != nil {
break
}
break
}
if runErr != nil && current.Next != nil && current.Next.Type != domain.WorkflowNodeTypeExecuteResultBranch {

View File

@@ -35,35 +35,20 @@ type WorkflowService struct {
}
func NewWorkflowService(repo workflowRepository) *WorkflowService {
rs := &WorkflowService{
srv := &WorkflowService{
repo: repo,
ch: make(chan *workflowRunData, 1),
}
ctx, cancel := context.WithCancel(context.Background())
rs.cancel = cancel
srv.cancel = cancel
rs.wg.Add(defaultRoutines)
srv.wg.Add(defaultRoutines)
for i := 0; i < defaultRoutines; i++ {
go rs.process(ctx)
go srv.run(ctx)
}
return rs
}
func (s *WorkflowService) process(ctx context.Context) {
defer s.wg.Done()
for {
select {
case data := <-s.ch:
// 执行
if err := s.run(ctx, data); err != nil {
app.GetLogger().Error("failed to run workflow", "id", data.Workflow.Id, "err", err)
}
case <-ctx.Done():
return
}
}
return srv
}
func (s *WorkflowService) InitSchedule(ctx context.Context) error {
@@ -90,7 +75,6 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
}
func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) error {
// 查询
workflow, err := s.repo.GetById(ctx, req.WorkflowId)
if err != nil {
app.GetLogger().Error("failed to get workflow", "id", req.WorkflowId, "err", err)
@@ -101,9 +85,8 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err
return errors.New("workflow is running")
}
// set last run
workflow.LastRunTime = time.Now()
workflow.LastRunStatus = domain.WorkflowRunStatusTypeRunning
workflow.LastRunStatus = domain.WorkflowRunStatusTypePending
workflow.LastRunId = ""
if err := s.repo.Save(ctx, workflow); err != nil {
@@ -118,42 +101,56 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err
return nil
}
func (s *WorkflowService) run(ctx context.Context, runData *workflowRunData) error {
// 执行
func (s *WorkflowService) Stop(ctx context.Context) {
s.cancel()
s.wg.Wait()
}
func (s *WorkflowService) run(ctx context.Context) {
defer s.wg.Done()
for {
select {
case data := <-s.ch:
if err := s.runWithData(ctx, data); err != nil {
app.GetLogger().Error("failed to run workflow", "id", data.Workflow.Id, "err", err)
}
case <-ctx.Done():
return
}
}
}
func (s *WorkflowService) runWithData(ctx context.Context, runData *workflowRunData) error {
workflow := runData.Workflow
run := &domain.WorkflowRun{
WorkflowId: workflow.Id,
Status: domain.WorkflowRunStatusTypeRunning,
Trigger: runData.RunTrigger,
StartedAt: time.Now(),
EndedAt: time.Now(),
}
processor := processor.NewWorkflowProcessor(workflow)
if err := processor.Run(ctx); err != nil {
if runErr := processor.Run(ctx); runErr != nil {
run.Status = domain.WorkflowRunStatusTypeFailed
run.EndedAt = time.Now()
run.Logs = processor.Log(ctx)
run.Error = err.Error()
run.Logs = processor.GetRunLogs()
run.Error = runErr.Error()
if err := s.repo.SaveRun(ctx, run); err != nil {
app.GetLogger().Error("failed to save workflow run", "err", err)
}
return fmt.Errorf("failed to run workflow: %w", err)
return fmt.Errorf("failed to run workflow: %w", runErr)
}
// 保存日志
logs := processor.Log(ctx)
runStatus := domain.WorkflowRunStatusTypeSucceeded
runError := domain.WorkflowRunLogs(logs).FirstError()
if runError != "" {
runStatus = domain.WorkflowRunStatusTypeFailed
}
run.Status = runStatus
run.EndedAt = time.Now()
run.Logs = processor.Log(ctx)
run.Error = runError
run.Logs = processor.GetRunLogs()
run.Error = domain.WorkflowRunLogs(run.Logs).ErrorString()
if run.Error == "" {
run.Status = domain.WorkflowRunStatusTypeSucceeded
} else {
run.Status = domain.WorkflowRunStatusTypeFailed
}
if err := s.repo.SaveRun(ctx, run); err != nil {
app.GetLogger().Error("failed to save workflow run", "err", err)
return err
@@ -161,8 +158,3 @@ func (s *WorkflowService) run(ctx context.Context, runData *workflowRunData) err
return nil
}
func (s *WorkflowService) Stop(ctx context.Context) {
s.cancel()
s.wg.Wait()
}