Skip to content

Commit

Permalink
Merge pull request #4426 from irwinsun/issue_4420
Browse files Browse the repository at this point in the history
完善用户取消与系统强制终止的状态区别 #4420
  • Loading branch information
irwinsun authored Jun 15, 2021
2 parents 2d8ec9e + 6203794 commit 4eff940
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ object BuildStatusSwitcher {
BuildStatus.RUNNING,
BuildStatus.CALL_WAITING,
BuildStatus.REVIEWING,
BuildStatus.PAUSE,
BuildStatus.CANCELED,
BuildStatus.REVIEW_ABORT,
BuildStatus.REVIEW_PROCESSED,
BuildStatus.PAUSE,
BuildStatus.CANCELED,
BuildStatus.SUCCEED,
BuildStatus.FAILED,
BuildStatus.TERMINATE,
Expand All @@ -196,6 +196,7 @@ object BuildStatusSwitcher {
BuildStatus.CANCELED,
BuildStatus.SUCCEED,
BuildStatus.FAILED,
BuildStatus.TERMINATE,
BuildStatus.QUEUE_TIMEOUT,
BuildStatus.STAGE_SUCCESS
)
Expand All @@ -214,6 +215,7 @@ object BuildStatusSwitcher {
BuildStatus.CANCELED,
BuildStatus.SUCCEED,
BuildStatus.FAILED,
BuildStatus.TERMINATE,
BuildStatus.SKIP,
BuildStatus.UNEXEC,
BuildStatus.QUEUE_TIMEOUT,
Expand All @@ -236,9 +238,9 @@ object BuildStatusSwitcher {
BuildStatus.SUCCEED,
BuildStatus.FAILED,
BuildStatus.TERMINATE,
BuildStatus.QUEUE_TIMEOUT,
BuildStatus.SKIP,
BuildStatus.UNEXEC,
BuildStatus.QUEUE_TIMEOUT,
BuildStatus.HEARTBEAT_TIMEOUT
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ class BuildStatusSwitcherTest {
BuildStatusSwitcher.pipelineStatusMaker.finish(status)
)
}
status == BuildStatus.TERMINATE -> {
Assert.assertEquals(
BuildStatus.TERMINATE,
BuildStatusSwitcher.pipelineStatusMaker.finish(status)
)
}
status.isReadyToRun() -> {
Assert.assertEquals(BuildStatus.CANCELED, BuildStatusSwitcher.pipelineStatusMaker.finish(status))
}
Expand Down Expand Up @@ -123,8 +129,17 @@ class BuildStatusSwitcherTest {
BuildStatusSwitcher.pipelineStatusMaker.forceFinish(status)
)
}
status == BuildStatus.TERMINATE -> {
Assert.assertEquals(
BuildStatus.TERMINATE,
BuildStatusSwitcher.pipelineStatusMaker.forceFinish(status)
)
}
status.isFailure() -> {
Assert.assertEquals(BuildStatus.FAILED, BuildStatusSwitcher.pipelineStatusMaker.forceFinish(status))
Assert.assertEquals(
BuildStatus.FAILED,
BuildStatusSwitcher.pipelineStatusMaker.forceFinish(status)
)
}
status.isFinish() -> {
Assert.assertTrue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,20 @@ import javax.xml.bind.Element
@Component
class VmOperateTaskGenerator {

val startVmTaskAtom = "dispatchVMStartupTaskAtom"
val shutdownVmTaskAtom = "dispatchVMShutdownTaskAtom"
val startNormalTaskAtom = "dispatchBuildLessDockerStartupTaskAtom"
val shutdownNormalTaskAtom = "dispatchBuildLessDockerShutdownTaskAtom"
companion object {
const val START_VM_TASK_ATOM = "dispatchVMStartupTaskAtom"
const val SHUTDOWN_VM_TASK_ATOM = "dispatchVMShutdownTaskAtom"
const val START_NORMAL_TASK_ATOM = "dispatchBuildLessDockerStartupTaskAtom"
const val SHUTDOWN_NORMAL_TASK_ATOM = "dispatchBuildLessDockerShutdownTaskAtom"

fun isVmAtom(task: PipelineBuildTask) = isStartVM(task) || isStopVM(task)

fun isStartVM(task: PipelineBuildTask) =
task.taskAtom == START_VM_TASK_ATOM || task.taskAtom == START_NORMAL_TASK_ATOM

fun isStopVM(task: PipelineBuildTask) =
task.taskAtom == SHUTDOWN_VM_TASK_ATOM || task.taskAtom == SHUTDOWN_NORMAL_TASK_ATOM
}

/**
* 生成编译环境的开机插件任务
Expand All @@ -75,15 +85,15 @@ class VmOperateTaskGenerator {
if (container is VMBuildContainer) {
val buildType = container.dispatchType?.buildType()?.name ?: BuildType.DOCKER.name
val baseOS = container.baseOS.name
atomCode = "$startVmTaskAtom-$buildType-$baseOS"
atomCode = "$START_VM_TASK_ATOM-$buildType-$baseOS"
taskType = EnvControlTaskType.VM.name
taskName = "Prepare_Job#${container.id!!}"
taskAtom = startVmTaskAtom
taskAtom = START_VM_TASK_ATOM
} else {
atomCode = startNormalTaskAtom
atomCode = START_NORMAL_TASK_ATOM
taskType = EnvControlTaskType.NORMAL.name
taskName = "Prepare_Job#${container.id!!}(N)"
taskAtom = startNormalTaskAtom
taskAtom = START_NORMAL_TASK_ATOM
}

return PipelineBuildTask(
Expand Down Expand Up @@ -131,10 +141,10 @@ class VmOperateTaskGenerator {
val taskAtom: String
if (container is VMBuildContainer) {
taskType = EnvControlTaskType.VM.name
taskAtom = shutdownVmTaskAtom
taskAtom = SHUTDOWN_VM_TASK_ATOM
} else {
taskType = EnvControlTaskType.NORMAL.name
taskAtom = shutdownNormalTaskAtom
taskAtom = SHUTDOWN_NORMAL_TASK_ATOM
}

val containerId = container.id!!
Expand Down Expand Up @@ -166,7 +176,7 @@ class VmOperateTaskGenerator {
approver = null,
subBuildId = null,
additionalOptions = additionalOptions,
atomCode = "$shutdownVmTaskAtom-END"
atomCode = "$SHUTDOWN_VM_TASK_ATOM-END"
)
)

Expand Down Expand Up @@ -198,7 +208,7 @@ class VmOperateTaskGenerator {
approver = null,
subBuildId = null,
additionalOptions = additionalOptions,
atomCode = "$shutdownVmTaskAtom-FINISH"
atomCode = "$SHUTDOWN_VM_TASK_ATOM-FINISH"
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.tencent.devops.common.log.utils.BuildLogPrinter
import com.tencent.devops.common.pipeline.enums.BuildStatus
import com.tencent.devops.common.service.utils.CommonUtils
import com.tencent.devops.common.service.utils.SpringContextUtil
import com.tencent.devops.process.engine.control.VmOperateTaskGenerator
import com.tencent.devops.process.engine.exception.BuildTaskException
import com.tencent.devops.process.engine.pojo.PipelineBuildTask
import com.tencent.devops.process.engine.service.PipelineBuildDetailService
Expand Down Expand Up @@ -70,6 +71,9 @@ class TaskAtomService @Autowired(required = false) constructor(
jmxElements.execute(task.taskType)
var atomResponse = AtomResponse(BuildStatus.FAILED)
try {
if (!VmOperateTaskGenerator.isVmAtom(task)) {
dispatchBroadCastEvent(task, ActionType.START)
}
// 更新状态
pipelineRuntimeService.updateTaskStatus(
task = task,
Expand Down Expand Up @@ -110,6 +114,20 @@ class TaskAtomService @Autowired(required = false) constructor(
return atomResponse
}

private fun dispatchBroadCastEvent(task: PipelineBuildTask, actionType: ActionType) {
pipelineEventDispatcher.dispatch(
PipelineBuildStatusBroadCastEvent(
source = "task-${task.taskId}",
projectId = task.projectId,
pipelineId = task.pipelineId,
userId = task.starter,
taskId = task.taskId,
buildId = task.buildId,
actionType = actionType
)
)
}

/**
* 插件启动之后的处理,根据插件返回的结果[atomResponse]判断是否要结束任务[task]
*/
Expand Down Expand Up @@ -169,17 +187,11 @@ class TaskAtomService @Autowired(required = false) constructor(
} catch (ignored: Throwable) {
logger.warn("Fail to post the task($task): ${ignored.message}")
}
pipelineEventDispatcher.dispatch(
PipelineBuildStatusBroadCastEvent(
source = "task-end-${task.taskId}",
projectId = task.projectId,
pipelineId = task.pipelineId,
userId = task.starter,
taskId = task.taskId,
buildId = task.buildId,
actionType = ActionType.END
)
)

if (!VmOperateTaskGenerator.isVmAtom(task)) {
dispatchBroadCastEvent(task, ActionType.END)
}

buildLogPrinter.stopLog(
buildId = task.buildId,
tag = task.taskId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ class TaskControl @Autowired constructor(
// 构建机上运行中任务目前无法直接后台干预,便在此处设置状态,使流程继续
if (actionType.isEnd()) {
LOG.info("ENGINE|$buildId|$source|ATOM_$actionType|$stageId|j($containerId)|t($taskId)|code=$errorCode")
val buildStatus = BuildStatus.CANCELED
val buildStatus = if (actionType.isTerminate()) { // 区分系统终止还是用户手动终止
BuildStatus.TERMINATE
} else {
BuildStatus.CANCELED
}
val atomResponse = AtomResponse(
buildStatus = buildStatus,
errorCode = errorCode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class PipelineTaskPauseListener @Autowired constructor(
redisLock.lock()
if (event.actionType == ActionType.REFRESH) {
taskContinue(task = taskRecord!!, userId = event.userId)
} else if (event.actionType == ActionType.TERMINATE) {
} else if (event.actionType == ActionType.END) {
taskCancel(task = taskRecord!!, userId = event.userId)
}
// #3400 减少重复DETAIL事件转发, Cancel与Continue之后插件任务执行都会刷新DETAIL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ class DependOnControlTest {
fun `when dependOnContainerId2JobIds is null return success`() {
val dependContainerId = 2
val status2 = BuildStatus.RUNNING
val mockJob = TestTool.genVmBuildContainer(id = 1,
val mockJob = TestTool.genVmBuildContainer(vmSeqId = 1,
jobControlOption = JobControlOption(dependOnContainerId2JobIds = null)
)

val mockContainers = listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = status2)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = status2)
)
whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(mockContainers)
Assert.assertEquals(BuildStatus.SUCCEED, dependOnControl.dependOnJobStatus(container = mockJob))
Expand All @@ -76,14 +76,14 @@ class DependOnControlTest {
fun `when depend on job is running then return running`() {
val dependContainerId = 2
val status2 = BuildStatus.RUNNING
val mockJob = TestTool.genVmBuildContainer(id = 1,
val mockJob = TestTool.genVmBuildContainer(vmSeqId = 1,
jobControlOption = JobControlOption(
dependOnContainerId2JobIds = mapOf(dependContainerId.toString() to "jobId2")
)
)

val mockContainers = listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = status2)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = status2)
)
whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(mockContainers)
Assert.assertEquals(status2, dependOnControl.dependOnJobStatus(container = mockJob))
Expand All @@ -93,14 +93,14 @@ class DependOnControlTest {
fun `when depend on job is failed then return failed`() {
val dependContainerId = 2
val status2 = BuildStatus.FAILED
val mockJob = TestTool.genVmBuildContainer(id = 1,
val mockJob = TestTool.genVmBuildContainer(vmSeqId = 1,
jobControlOption = JobControlOption(
dependOnContainerId2JobIds = mapOf(dependContainerId.toString() to "jobId2")
)
)

val mockContainers = listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = status2)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = status2)
)
whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(mockContainers)
val dependOnJobStatus = dependOnControl.dependOnJobStatus(container = mockJob)
Expand All @@ -111,33 +111,33 @@ class DependOnControlTest {
fun `when depend on job is running or success then return running`() {
val dependContainerId = 2
val dependContainerId3 = 3
val mockJob = TestTool.genVmBuildContainer(id = 1,
val mockJob = TestTool.genVmBuildContainer(vmSeqId = 1,
jobControlOption = JobControlOption(
dependOnContainerId2JobIds = mapOf("2" to "jobId2").plus("3" to "jobId3")
), status = BuildStatus.RUNNING
)

whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(
listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = BuildStatus.RUNNING),
TestTool.genVmBuildContainer(id = dependContainerId3).copy(status = BuildStatus.SUCCEED)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = BuildStatus.RUNNING),
TestTool.genVmBuildContainer(vmSeqId = dependContainerId3).copy(status = BuildStatus.SUCCEED)
)
)
Assert.assertEquals(BuildStatus.RUNNING, dependOnControl.dependOnJobStatus(container = mockJob))

whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(
listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = BuildStatus.SUCCEED),
TestTool.genVmBuildContainer(id = dependContainerId3).copy(status = BuildStatus.SUCCEED)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = BuildStatus.SUCCEED),
TestTool.genVmBuildContainer(vmSeqId = dependContainerId3).copy(status = BuildStatus.SUCCEED)
)
)
Assert.assertEquals(BuildStatus.SUCCEED, dependOnControl.dependOnJobStatus(container = mockJob))

// when fail
whenever(pipelineRuntimeService.listContainers(TestTool.buildId, TestTool.stageId)).thenReturn(
listOf(
TestTool.genVmBuildContainer(id = dependContainerId).copy(status = BuildStatus.RUNNING),
TestTool.genVmBuildContainer(id = dependContainerId3).copy(status = BuildStatus.FAILED)
TestTool.genVmBuildContainer(vmSeqId = dependContainerId).copy(status = BuildStatus.RUNNING),
TestTool.genVmBuildContainer(vmSeqId = dependContainerId3).copy(status = BuildStatus.FAILED)
)
)
Assert.assertEquals(BuildStatus.FAILED, dependOnControl.dependOnJobStatus(container = mockJob))
Expand Down
Loading

0 comments on commit 4eff940

Please sign in to comment.