fix: ASW-164 playbook 添加 cancel 接口
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package net.geedge.api.controller;
|
||||
|
||||
import cn.hutool.core.codec.Base32Codec;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.log.Log;
|
||||
@@ -29,6 +30,8 @@ public class APIController {
|
||||
|
||||
private final AdbUtil adbUtil;
|
||||
|
||||
static final List<Thread> ACTIVE_TASKS = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
@Autowired
|
||||
public APIController(EnvApiYml envApiYml) {
|
||||
this.adbUtil = AdbUtil.getInstance(envApiYml.getAdb(), new CommandExec(null));
|
||||
@@ -305,6 +308,7 @@ public class APIController {
|
||||
T.FileUtil.del(destination);
|
||||
}
|
||||
PlaybookRunnable playbookRunnable = new PlaybookRunnable(apiYml, apkFile, playbookAirDir, id, packageName);
|
||||
playbookRunnable.setName(T.StrUtil.concat(true, id, "-", apkFile.getName()));
|
||||
ThreadUtil.execAsync(playbookRunnable);
|
||||
return R.ok();
|
||||
}
|
||||
@@ -319,6 +323,20 @@ public class APIController {
|
||||
return R.ok().putData(status);
|
||||
}
|
||||
|
||||
@DeleteMapping("/playbook/{id}")
|
||||
public R cancel(@PathVariable("id") String id){
|
||||
if (T.StrUtil.isEmpty(id)) {
|
||||
throw new APIException(RCode.BAD_REQUEST);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(ACTIVE_TASKS)) {
|
||||
ACTIVE_TASKS.stream().filter(thread -> T.StrUtil.startWith(thread.getName(), id)).forEach(thread -> {
|
||||
log.info(String.format("playbook thread: %s has been canceled", thread.getName()));
|
||||
thread.interrupt();
|
||||
});
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/playbook/{id}/log")
|
||||
public R getJobResultLog(@PathVariable("id") String id,
|
||||
@@ -388,6 +406,7 @@ public class APIController {
|
||||
private File apkFile;
|
||||
private String packageName;
|
||||
private File playbookDir;
|
||||
private boolean interrupt;
|
||||
|
||||
public PlaybookRunnable(EnvApiYml envApiYml, File apkFile, File playbookDir, String tid, String packageName) {
|
||||
this.envApiYml = envApiYml;
|
||||
@@ -395,10 +414,12 @@ public class APIController {
|
||||
this.apkFile = apkFile;
|
||||
this.packageName = packageName;
|
||||
this.playbookDir = playbookDir;
|
||||
this.interrupt = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ACTIVE_TASKS.add(this);
|
||||
File logFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.log");
|
||||
File statusFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.json");
|
||||
AdbUtil.CommandResult tcpdumpPackage = null;
|
||||
@@ -414,6 +435,7 @@ public class APIController {
|
||||
T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8");
|
||||
|
||||
// install apk
|
||||
if (interrupt) return;
|
||||
AdbUtil.CommandResult install = adbUtil.install(apkFile.getAbsolutePath(), true, true);
|
||||
if (0 != install.exitCode()) {
|
||||
T.FileUtil.appendString(String.format("ERROR: Install apk failed: exit code %s \n", install.exitCode()), logFile, "UTF-8");
|
||||
@@ -421,6 +443,7 @@ public class APIController {
|
||||
}
|
||||
|
||||
// clear app data
|
||||
if (interrupt) return;
|
||||
AdbUtil.CommandResult clearData = adbUtil.clearAppData(packageName);
|
||||
if (0 != clearData.exitCode()) {
|
||||
T.FileUtil.appendString(String.format("ERROR: Clear %s data error: exit code %s \n", packageName, install.exitCode()), logFile, "UTF-8");
|
||||
@@ -428,6 +451,7 @@ public class APIController {
|
||||
}
|
||||
|
||||
// star tcpdump: package name
|
||||
if (interrupt) return;
|
||||
tcpdumpPackage = adbUtil.startTcpdump(packageName);
|
||||
if (0 != tcpdumpPackage.exitCode()) {
|
||||
T.FileUtil.appendString(String.format("ERROR: Start tcpdump %s failed: exit code %s \n", packageName, tcpdumpPackage.exitCode()), logFile, "UTF-8");
|
||||
@@ -435,6 +459,7 @@ public class APIController {
|
||||
}
|
||||
|
||||
// star tcpdump: all
|
||||
if (interrupt) return;
|
||||
tcpdumpAll = adbUtil.startTcpdump(T.StrUtil.EMPTY);
|
||||
if (0 != tcpdumpAll.exitCode()) {
|
||||
T.FileUtil.appendString(String.format("ERROR: Start tcpdump all failed: exit code %s \n", tcpdumpAll.exitCode()), logFile, "UTF-8");
|
||||
@@ -442,6 +467,7 @@ public class APIController {
|
||||
}
|
||||
|
||||
// exec playbook
|
||||
if (interrupt) return;
|
||||
AdbUtil.CommandResult airtestResult = adbUtil.execPlaybook(playbookDir.getPath(), logFile);
|
||||
if (0 != airtestResult.exitCode()) {
|
||||
T.FileUtil.appendString(String.format("ERROR: Exec playbook failed: exit code %s \n", airtestResult.exitCode()), logFile, "UTF-8");
|
||||
@@ -449,9 +475,11 @@ public class APIController {
|
||||
}
|
||||
|
||||
// stop package tcpdump
|
||||
if (interrupt) return;
|
||||
stopTcpdump(tcpdumpPackage, logFile, packageName);
|
||||
|
||||
// stop all tcpdump
|
||||
if (interrupt) return;
|
||||
stopTcpdump(tcpdumpAll, logFile, T.StrUtil.EMPTY);
|
||||
|
||||
resultMap = T.MapUtil.builder()
|
||||
@@ -464,17 +492,28 @@ public class APIController {
|
||||
.put("status", "error")
|
||||
.build();
|
||||
T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8");
|
||||
|
||||
AdbUtil.CommandResult packageTcpdump = adbUtil.stopTcpdump(tcpdumpPackage.output());
|
||||
adbUtil.execShellCommand(String.format("shell rm -rf %s", packageTcpdump.output()));
|
||||
AdbUtil.CommandResult allTcpdump = adbUtil.stopTcpdump(tcpdumpAll.output());
|
||||
adbUtil.execShellCommand(String.format("shell rm -rf %s", allTcpdump.output()));
|
||||
} finally {
|
||||
if (T.StrUtil.isNotEmpty(tcpdumpPackage.output())){
|
||||
AdbUtil.CommandResult packageTcpdump = adbUtil.stopTcpdump(tcpdumpPackage.output());
|
||||
adbUtil.execShellCommand(String.format("shell rm -rf %s", packageTcpdump.output()));
|
||||
}
|
||||
if (T.StrUtil.isNotEmpty(tcpdumpAll.output())){
|
||||
AdbUtil.CommandResult allTcpdump = adbUtil.stopTcpdump(tcpdumpAll.output());
|
||||
adbUtil.execShellCommand(String.format("shell rm -rf %s", allTcpdump.output()));
|
||||
}
|
||||
adbUtil.stopApp(packageName);
|
||||
T.FileUtil.appendString(String.format("Job succeeded"), logFile, "UTF-8");
|
||||
ACTIVE_TASKS.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupt() {
|
||||
super.interrupt();
|
||||
this.interrupt = true;
|
||||
adbUtil.setInterrupt(true);
|
||||
}
|
||||
|
||||
private void stopTcpdump(AdbUtil.CommandResult tcpdump, File logFile, String packageName) {
|
||||
// stop tcpdump
|
||||
AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(tcpdump.output());
|
||||
|
||||
@@ -9,9 +9,7 @@ import net.geedge.common.Constant;
|
||||
import net.geedge.common.RCode;
|
||||
import net.geedge.common.T;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.*;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
@@ -37,6 +35,8 @@ public class AdbUtil {
|
||||
|
||||
private CommandExec commandExec;
|
||||
|
||||
private boolean interrupt;
|
||||
|
||||
private ExecutorService threadPool;
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ public class AdbUtil {
|
||||
return T.StrUtil.isNotEmpty(this.serial) ? serial : String.format("%s:%s", this.host, this.port);
|
||||
}
|
||||
|
||||
public void setInterrupt(boolean interrupt) {
|
||||
this.interrupt = interrupt;
|
||||
}
|
||||
|
||||
public record CommandResult(Integer exitCode, String output) {
|
||||
}
|
||||
|
||||
@@ -870,6 +874,10 @@ public class AdbUtil {
|
||||
bufferedReader = new BufferedReader(inputStreamReader);
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (T.ObjectUtil.isNotNull(interrupt) && interrupt){
|
||||
log.info("[PlaybookRunnable] [execPlaybook] [stop exec playbook]");
|
||||
process.destroyForcibly();
|
||||
}
|
||||
// 处理每一行输出
|
||||
T.FileUtil.appendString(T.StrUtil.concat(true, line, "\n"), logFile, "UTF-8");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user