You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Def.sequential实现全量顺序执行任务并上报错误?

最优实现方案:全量顺序执行任务并收集错误信息

核心思路

要满足「全量顺序执行、失败不中断、错误可追溯」的需求,核心是对每个任务单独做异常捕获,串行遍历执行所有任务,并收集每个失败任务的详细信息。

通用代码实现(以Scala为例)

我们可以封装一个通用的任务执行器,负责串行执行任务、捕获异常并记录错误:

// 定义错误信息结构,绑定任务标识和异常详情
case class TaskError(taskId: String, errorMsg: String, stackTrace: String)

def runTasksSequentially(tasks: (String, () => Any)*): List[TaskError] = {
  val errorList = scala.collection.mutable.ListBuffer[TaskError]()
  
  tasks.foreach { case (taskName, taskFunc) =>
    try {
      taskFunc() // 同步执行单个任务
    } catch {
      case e: Throwable =>
        // 收集错误信息,包括任务名、错误消息和栈轨迹
        val error = TaskError(
          taskId = taskName,
          errorMsg = e.getMessage,
          stackTrace = e.getStackTrace.mkString("\n")
        )
        errorList += error
    }
  }
  
  errorList.toList
}

// 使用示例
val testTask1 = () => println("执行测试任务1")
val testTask2 = () => throw new RuntimeException("测试任务2断言失败")
val testTask3 = () => println("执行测试任务3")

// 执行所有任务并获取错误列表
val errors = runTasksSequentially(
  "测试任务1" -> testTask1,
  "测试任务2" -> testTask2,
  "测试任务3" -> testTask3
)

// 上报/输出错误信息
errors.foreach { err =>
  println(s"=== 任务[${err.taskId}]执行失败 ===")
  println(s"错误信息:${err.errorMsg}")
  println(s"栈轨迹:\n${err.stackTrace}\n")
}

方案优势

  • 严格串行执行:通过foreach逐个调用任务,完全保证任务按顺序执行,不会并行
  • 全量执行不中断:单个任务抛出的异常被即时捕获,后续任务不受影响,能完整执行所有任务
  • 错误精准追溯:每个错误都绑定任务标识,能清晰定位到具体失败的测试任务,便于排查
  • 灵活扩展:可根据需求调整错误收集的字段(比如添加执行时间、任务类型等),适配不同场景

针对sbt任务场景的适配(结合Def.sequential)

如果是在sbt构建系统中使用Def.sequential相关的任务定义,可以调整为适配sbt任务体系的实现:

import sbt._

// 定义sbt任务错误结构
case class SbtTaskError(taskKey: TaskKey[_], exception: Throwable)

def executeAllSbtTasks(settings: Setting[_]*): Def.Initialize[Task[List[SbtTaskError]]] = Def.task {
  val errors = scala.collection.mutable.ListBuffer[SbtTaskError]()
  
  settings.foreach { setting =>
    setting.key match {
      case taskKey: TaskKey[_] =>
        try {
          taskKey.value // 执行sbt任务
        } catch {
          case e: Throwable =>
            errors += SbtTaskError(taskKey, e)
        }
      case _ => // 忽略非任务类型的配置
    }
  }
  
  errors.toList
}

// 使用示例
val test1 = taskKey[Unit]("单元测试1")
val test2 = taskKey[Unit]("单元测试2")
val test3 = taskKey[Unit]("单元测试3")

// 定义全量执行任务
val runAllTests = taskKey[Unit]("执行所有测试并收集错误")
runAllTests := {
  val errors = executeAllSbtTasks(test1, test2, test3).value
  
  // 输出错误到sbt日志
  val log = streams.value.log
  errors.foreach { err =>
    log.error(s"任务[${err.taskKey.label}]执行失败:${err.exception.getMessage}")
    log.error("栈轨迹:")
    err.exception.getStackTrace.foreach(stack => log.error(s"  $stack"))
  }
  
  // 若有错误,可抛出异常触发构建失败(可选)
  if (errors.nonEmpty) throw new RuntimeException(s"共${errors.size}个测试任务执行失败")
}

内容的提问来源于stack exchange,提问作者david.perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:42:28