Commit 904bd700 by guo_minglei@163.com

Merge remote-tracking branch 'origin/developer' into developer

parents 038c20ef f4f25c72
package com.byit.api; package com.byit.api;
import com.byit.model.vo.RunRecordingVo;
import com.byit.service.ApiFlowService; import com.byit.service.ApiFlowService;
import com.byit.service.FlowService; import com.byit.service.FlowService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
...@@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.text.ParseException; import java.text.ParseException;
import java.util.List;
/** /**
* @description: 工作流操作的API接口 * @description: 工作流操作的API接口
...@@ -55,6 +57,7 @@ public class ApiFlowController { ...@@ -55,6 +57,7 @@ public class ApiFlowController {
return "SUCCESS"; return "SUCCESS";
} }
@PostMapping("killJob") @PostMapping("killJob")
@ApiOperation("杀死节点") @ApiOperation("杀死节点")
public Boolean killJob(String param) throws InterruptedException { public Boolean killJob(String param) throws InterruptedException {
...@@ -82,10 +85,17 @@ public class ApiFlowController { ...@@ -82,10 +85,17 @@ public class ApiFlowController {
return "SUCCESS"; return "SUCCESS";
} }
@PostMapping("reRun") @PostMapping("reRunJob")
@ApiOperation("重跑") @ApiOperation("重跑节点")
public String reRun(String param){ public String reRunJob(String param){
apiFlowService.reRun(param); apiFlowService.reRunJob(param);
return "SUCCESS";
}
@PostMapping("reRunFlow")
@ApiOperation("重跑工作流")
public String reRunFlow(String param){
apiFlowService.reRunFlow(param);
return "SUCCESS"; return "SUCCESS";
} }
...@@ -96,4 +106,50 @@ public class ApiFlowController { ...@@ -96,4 +106,50 @@ public class ApiFlowController {
return "SUCCESS"; return "SUCCESS";
} }
/**
*
* @param param startTime
* endTime
* flowName
* workspaceName
* @return
*/
@PostMapping("loadScheduleResult")
@ApiOperation("加载运行记录")
public List<RunRecordingVo> loadScheduleResult(String param){
List<RunRecordingVo> result = apiFlowService.loadScheduleResult(param);
return result;
}
@PostMapping("getLogUrl")
@ApiOperation("获取日志文件的url地址")
public String getLogUrl(String param){
String logUrl = apiFlowService.getLogUrl(param);
return logUrl;
}
/**
* 补批节点
* @param param
* @return
*/
@PostMapping("/repairJob")
@ApiOperation("补批")
public String repairJob(String param){
apiFlowService.repairJob(param);
return "SUCCESS";
}
/**
* 补批工作流
* @param param
* @return
*/
@PostMapping("/repairFlow")
@ApiOperation("补批工作流")
public String repairFlow(String param){
apiFlowService.repairFlow(param);
return "SUCCESS";
}
} }
package com.byit.service; package com.byit.service;
import com.byit.job.dto.plugin.PluginFlow; import com.byit.job.dto.plugin.PluginFlow;
import com.byit.model.vo.RunRecordingVo;
import java.text.ParseException; import java.text.ParseException;
import java.util.List;
/** /**
* @description: 工作流的api请求业务处理接口 * @description: 工作流的api请求业务处理接口
...@@ -37,11 +39,43 @@ public interface ApiFlowService { ...@@ -37,11 +39,43 @@ public interface ApiFlowService {
* 重跑任务 * 重跑任务
* @param param * @param param
*/ */
void reRun(String param); void reRunJob(String param);
/** /**
* 手动置为成功 * 手动置为成功
* @param param * @param param
*/ */
void madeSuccess(String param); void madeSuccess(String param);
/**
* 重跑工作流
* @param param
*/
void reRunFlow(String param);
/**
* 加载运行记录
* @param param
* @return
*/
List<RunRecordingVo> loadScheduleResult(String param);
/**
* 补批
* @param param
*/
void repairJob(String param);
/**
* 补批工作流
* @param param
*/
void repairFlow(String param);
/**
* 获取运行日志的存放地址
* @param param
* @return
*/
String getLogUrl(String param);
} }
...@@ -6,13 +6,13 @@ spring: ...@@ -6,13 +6,13 @@ spring:
password: 123456 password: 123456
mail: mail:
host: smtp.163.com #我自己的SMTP服务器地 host: smtp.163.com #���Լ���SMTP��������ַ
username: huangfusuper@163.com #登录用户名 username: huangfusuper@163.com #��¼�û���
password: huangfu0110 #授权密码 password: huangfu0110 #��Ȩ����
default-encoding: UTF-8 default-encoding: UTF-8
protocol: smtp #协 protocol: smtp ��
properties: properties:
from: huangfusuper@163.com #真实邮箱 from: huangfusuper@163.com #��ʵ����
mybatis: mybatis:
mapper-locations: /mapper/*.xml mapper-locations: /mapper/*.xml
...@@ -25,4 +25,12 @@ myth-rpc: ...@@ -25,4 +25,12 @@ myth-rpc:
port: 6665 port: 6665
logging: logging:
path: /data/mythjob path: /data/mythjob
file: myth_log_file file: myth_log_file
\ No newline at end of file
file:
system:
ip: 10.0.120.2
port: 88
myth-job:
filestystem: FASTDFS
\ No newline at end of file
...@@ -35,4 +35,11 @@ public interface FlowMapper { ...@@ -35,4 +35,11 @@ public interface FlowMapper {
* @return * @return
*/ */
Flow getByWorkSpaceAndName(@Param("workspaceId") Integer workspaceId, @Param("flowName") String flowName); Flow getByWorkSpaceAndName(@Param("workspaceId") Integer workspaceId, @Param("flowName") String flowName);
/**
* 根据workspace查找所属的工作流
* @param workspaceId
* @return
*/
List<Flow> findByWorkspace(Integer workspaceId);
} }
\ No newline at end of file
...@@ -78,4 +78,11 @@ public interface NodeMapper { ...@@ -78,4 +78,11 @@ public interface NodeMapper {
* @param flowId * @param flowId
*/ */
int deleteByFlowId(Integer flowId); int deleteByFlowId(Integer flowId);
/**
* 根据内嵌工作流的id来查找结点
* @param mapFlowId
* @return
*/
Node getByMapFlowId(Integer mapFlowId);
} }
\ No newline at end of file
...@@ -117,4 +117,6 @@ public interface RunRecordingMapper { ...@@ -117,4 +117,6 @@ public interface RunRecordingMapper {
* @return * @return
*/ */
List<RunRecording> findUnFinishByRunId(String runId); List<RunRecording> findUnFinishByRunId(String runId);
List<RunRecording> findByStartAndEndTime(@Param("startDate")long startDate, @Param("endDate")long endDate, @Param("flowIds")List<Integer> flowIds);
} }
\ No newline at end of file
package com.byit.model.vo;
import com.byit.model.JobTaskRunLog;
import com.byit.model.RunRecording;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @description: 运行实例记录VO类
* @author: gml
* @create: 2020/2/28
*/
@Data
public class RunRecordingVo extends RunRecording {
@ApiModelProperty("运行实例下的运行任务日志")
private List<JobTaskRunLog> jobTaskRunLogList;
}
...@@ -35,6 +35,7 @@ public class JobTaskRunLogAndJobTaskServiceImpl implements JobTaskRunLogAndJobTa ...@@ -35,6 +35,7 @@ public class JobTaskRunLogAndJobTaskServiceImpl implements JobTaskRunLogAndJobTa
log.debug("-------------【{}节点失败重试------------------】",jobTaskRunLog); log.debug("-------------【{}节点失败重试------------------】",jobTaskRunLog);
jobTaskRunLog.setFailedRemainingCount(jobTaskRunLog.getFailedRemainingCount()-1); jobTaskRunLog.setFailedRemainingCount(jobTaskRunLog.getFailedRemainingCount()-1);
jobTaskRunLog.setRunCount(jobTaskRunLog.getRunCount()+1); jobTaskRunLog.setRunCount(jobTaskRunLog.getRunCount()+1);
jobTaskRunLog.setRunCode("0");
jobTaskRunLogService.updateJobTaskRunLog(jobTaskRunLog); jobTaskRunLogService.updateJobTaskRunLog(jobTaskRunLog);
//查询节点 //查询节点
......
...@@ -8,6 +8,7 @@ import com.byit.job.enums.JobResultEnum; ...@@ -8,6 +8,7 @@ import com.byit.job.enums.JobResultEnum;
import com.byit.model.JobTaskRunLogWithBLOBs; import com.byit.model.JobTaskRunLogWithBLOBs;
import com.byit.model.JobTaskSchedule; import com.byit.model.JobTaskSchedule;
import com.byit.model.RunRecording; import com.byit.model.RunRecording;
import com.byit.rpc.util.RpcException;
import com.byit.service.RunScriptService; import com.byit.service.RunScriptService;
import com.byit.service.impl.JobTaskRunLogServiceImpl; import com.byit.service.impl.JobTaskRunLogServiceImpl;
import com.byit.service.impl.RunRecordingServiceImpl; import com.byit.service.impl.RunRecordingServiceImpl;
...@@ -77,6 +78,10 @@ public class ScriptExecutorJobTask implements TimerTask { ...@@ -77,6 +78,10 @@ public class ScriptExecutorJobTask implements TimerTask {
*/ */
private void runJob(JobTaskSchedule mythJobTaskSchedule) { private void runJob(JobTaskSchedule mythJobTaskSchedule) {
RunScriptService runScriptService = SpringUtil.getBean(RunScriptService.class); RunScriptService runScriptService = SpringUtil.getBean(RunScriptService.class);
JobTaskRunLogServiceImpl jobTaskRunLogService = SpringUtil.getBean(JobTaskRunLogServiceImpl.class);
JobTaskRunLogWithBLOBs jobTaskRunLogById = jobTaskRunLogService.findJobTaskRunLogById(mythJobTaskSchedule.getLogId());
ScriptDto scriptDto = new ScriptDto(); ScriptDto scriptDto = new ScriptDto();
scriptDto.setLogId(mythJobTaskSchedule.getLogId()); scriptDto.setLogId(mythJobTaskSchedule.getLogId());
scriptDto.setCommand(mythJobTaskSchedule.getRunCommand()); scriptDto.setCommand(mythJobTaskSchedule.getRunCommand());
...@@ -84,7 +89,17 @@ public class ScriptExecutorJobTask implements TimerTask { ...@@ -84,7 +89,17 @@ public class ScriptExecutorJobTask implements TimerTask {
scriptDto.setRunId(mythJobTaskSchedule.getRunId()); scriptDto.setRunId(mythJobTaskSchedule.getRunId());
scriptDto.setRemotePath(mythJobTaskSchedule.getScriptUrls()); scriptDto.setRemotePath(mythJobTaskSchedule.getScriptUrls());
scriptDto.setCallbackUrl("http://127.0.0.1:8998/job/callbackRes"); scriptDto.setCallbackUrl("http://127.0.0.1:8998/job/callbackRes");
DispatchResponseDto dispatchResponseDto = runScriptService.runScript(scriptDto); //二次执行的情况下 会有这个信息
scriptDto.setLogRemotePath(jobTaskRunLogById.getLogRemotelyPath());
DispatchResponseDto dispatchResponseDto = new DispatchResponseDto();
try{
dispatchResponseDto = runScriptService.runScript(scriptDto);
}catch (RpcException rpcException){
dispatchResponseDto.setMsg(rpcException.getMessage());
dispatchResponseDto.setCode(JobResultEnum.DISPATCH_FAIL.getRes());
log.error("--------------执行机不存在----------------");
}
saveLog(mythJobTaskSchedule,dispatchResponseDto); saveLog(mythJobTaskSchedule,dispatchResponseDto);
} }
...@@ -121,7 +136,7 @@ public class ScriptExecutorJobTask implements TimerTask { ...@@ -121,7 +136,7 @@ public class ScriptExecutorJobTask implements TimerTask {
if (jobTaskRunLogById.getRunCount()>1) { if (jobTaskRunLogById.getRunCount()>1) {
//上一次的执行日志 //上一次的执行日志
String runMsg = jobTaskRunLogById.getRunMsg(); String runMsg = jobTaskRunLogById.getRunMsg();
jobTaskRunLog.setRunMsg(runMsg+"|"+"调度失败"); jobTaskRunLog.setRunMsg(runMsg+"|"+dispatchResponseDto.getMsg());
} }
} }
//获取执行机地址 //获取执行机地址
......
...@@ -3,6 +3,7 @@ package com.byit.thread; ...@@ -3,6 +3,7 @@ package com.byit.thread;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.byit.enums.RunRecordingEnum; import com.byit.enums.RunRecordingEnum;
import com.byit.filesystem.FileSystem;
import com.byit.model.EmailAlarm; import com.byit.model.EmailAlarm;
import com.byit.model.JobTaskRunLogWithBLOBs; import com.byit.model.JobTaskRunLogWithBLOBs;
import com.byit.model.RunRecording; import com.byit.model.RunRecording;
...@@ -11,14 +12,17 @@ import com.byit.service.JobTaskRunLogService; ...@@ -11,14 +12,17 @@ import com.byit.service.JobTaskRunLogService;
import com.byit.service.RunRecordingService; import com.byit.service.RunRecordingService;
import com.byit.util.TimeFormatUtil; import com.byit.util.TimeFormatUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.csource.common.MyException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -45,20 +49,36 @@ public class RunRecordingScanHelper { ...@@ -45,20 +49,36 @@ public class RunRecordingScanHelper {
*/ */
public static final String SUCCESS_DONE = "3"; public static final String SUCCESS_DONE = "3";
/**
* 文件服务器ip
*/
@Value("${file.system.ip}")
private String fileSystemIp;
/**
* 文件服务器端口号
*/
@Value("${file.system.port}")
private String fileSystemPort;
private static final String FILE_SYSTEM_PRE="http://";
private DataSource dataSource; private DataSource dataSource;
private final EmailAlarmService emailAlarmService; private final EmailAlarmService emailAlarmService;
private final JobTaskRunLogService jobTaskRunLogService; private final JobTaskRunLogService jobTaskRunLogService;
private final RunRecordingService runRecordingService; private final RunRecordingService runRecordingService;
private final FileSystem fileSystem;
private volatile boolean runRecordingThreadStop = false; private volatile boolean runRecordingThreadStop = false;
private Thread runRecordingThread; private Thread runRecordingThread;
@Autowired @Autowired
public RunRecordingScanHelper(EmailAlarmService emailAlarmService, JobTaskRunLogService jobTaskRunLogService, RunRecordingService runRecordingService) { public RunRecordingScanHelper(EmailAlarmService emailAlarmService, JobTaskRunLogService jobTaskRunLogService, RunRecordingService runRecordingService, FileSystem fileSystem) {
this.emailAlarmService = emailAlarmService; this.emailAlarmService = emailAlarmService;
this.jobTaskRunLogService = jobTaskRunLogService; this.jobTaskRunLogService = jobTaskRunLogService;
this.runRecordingService = runRecordingService; this.runRecordingService = runRecordingService;
this.fileSystem = fileSystem;
} }
public void start() { public void start() {
...@@ -238,7 +258,19 @@ public class RunRecordingScanHelper { ...@@ -238,7 +258,19 @@ public class RunRecordingScanHelper {
if (CollectionUtil.isNotEmpty(jobTaskRunLogs)) { if (CollectionUtil.isNotEmpty(jobTaskRunLogs)) {
jobTaskRunLogs.forEach(jobTaskRunLog -> { jobTaskRunLogs.forEach(jobTaskRunLog -> {
long timeConsuming = jobTaskRunLog.getEndTime().getTime() - jobTaskRunLog.getStartTime().getTime(); long timeConsuming = jobTaskRunLog.getEndTime().getTime() - jobTaskRunLog.getStartTime().getTime();
log.info("######################{}#####################3",timeConsuming); /*
* String iframeHtml = "<iframe src='%s'></iframe>";
* String logFilePath = FILE_SYSTEM_PRE+fileSystemIp+":"+fileSystemPort+"/"+jobTaskRunLog.getLogRemotelyPath();
* String logFileUrl = String.format(iframeHtml,logFilePath);
*/
String logStr = null;
try {
if(null != jobTaskRunLog.getLogRemotelyPath()){
logStr = new String(fileSystem.downloaderFile(jobTaskRunLog.getLogRemotelyPath()), StandardCharsets.UTF_8);
}
} catch (IOException | MyException e) {
e.printStackTrace();
}
stringBuilder.append("<tr align='center'>") stringBuilder.append("<tr align='center'>")
.append(String.format("<td>%s</td>", jobTaskRunLog.getNodeName())) .append(String.format("<td>%s</td>", jobTaskRunLog.getNodeName()))
.append(String.format("<td>%s</td>", DateUtil.format(jobTaskRunLog.getStartTime(), DATE_FORMAT))) .append(String.format("<td>%s</td>", DateUtil.format(jobTaskRunLog.getStartTime(), DATE_FORMAT)))
...@@ -249,7 +281,7 @@ public class RunRecordingScanHelper { ...@@ -249,7 +281,7 @@ public class RunRecordingScanHelper {
: "4".equals(jobTaskRunLog.getRunCode()) ? "补批失败" : "失败")) : "4".equals(jobTaskRunLog.getRunCode()) ? "补批失败" : "失败"))
.append("<td>") .append("<td>")
.append("<div style='display:inline-block;width:100%;word-break:break-all;height: auto;overflow: auto;text-align: left;'>") .append("<div style='display:inline-block;width:100%;word-break:break-all;height: auto;overflow: auto;text-align: left;'>")
.append(String.format("%s", jobTaskRunLog.getRunMsg())) .append(String.format("%s", logStr==null?jobTaskRunLog.getRunMsg():logStr))
.append("</div>") .append("</div>")
.append("</td></tr>"); .append("</td></tr>");
......
package com.byit.util; package com.byit.util;
import java.util.concurrent.TimeUnit;
/** /**
* 对于时间的格式化 * 对于时间的格式化
* @author huangfu * @author huangfu
...@@ -13,23 +11,35 @@ public class TimeFormatUtil { ...@@ -13,23 +11,35 @@ public class TimeFormatUtil {
* @return * @return
*/ */
public static String timeFormat(long time) { public static String timeFormat(long time) {
//秒 StringBuffer sb=new StringBuffer();
long seconds = TimeUnit.MILLISECONDS.toSeconds(time); long millis=1;
long minutes = TimeUnit.MILLISECONDS.toMinutes(time); long seconds=1000*millis;
long hours = TimeUnit.MILLISECONDS.toHours(time); long minutes=60*seconds;
//小时 long hours=60*minutes;
if(hours > 0){ long days=24*hours;
return hours + "小时"; if(time/days>=1){
//分钟 sb.append((int)(time/days)+"天");
} if (minutes > 0) { }
return minutes + "分钟";
//秒 if(time%days/hours>=1){
} else if (seconds > 0) { sb.append((int)(time%days/hours)+"小时");
return seconds + "秒"; }
//毫秒
} else{ if(time%days%hours/minutes>=1){
return time+"毫秒"; sb.append((int)(time%days%hours/minutes)+"分钟");
}
if(time%days%hours%minutes/seconds>=1){
sb.append((int)(time%days%hours%minutes/seconds)+"秒");
}
if(time%days%hours%minutes%seconds/millis>=1){
sb.append((int)(time%days%hours%minutes%seconds/millis)+"毫秒");
} }
return sb.toString();
} }
} }
...@@ -67,7 +67,14 @@ ...@@ -67,7 +67,14 @@
where flow_id = #{id,jdbcType=INTEGER} where flow_id = #{id,jdbcType=INTEGER}
</select> </select>
<delete id="deleteById" parameterType="java.lang.Integer"> <select id="findByWorkspace" resultType="com.byit.model.Flow">
select
<include refid="Base_Column_List" />
from flow
where false = #{workspaceId,jdbcType=INTEGER}
</select>
<delete id="deleteById" parameterType="java.lang.Integer">
<!-- generated @mbg.generated date: 2019-12-31 --> <!-- generated @mbg.generated date: 2019-12-31 -->
delete from flow delete from flow
where flow_id = #{flowId,jdbcType=INTEGER} where flow_id = #{flowId,jdbcType=INTEGER}
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
<select id="findErrorNode" resultMap="BaseResultMap"> <select id="findErrorNode" resultMap="BaseResultMap">
select <include refid="Base_Column_List" /> select <include refid="Base_Column_List" />
from job_task_run_log from job_task_run_log
where run_code != '6' and (run_code = '2' || run_code = '4') and failed_remaining_count > 0 where (run_code != '6' || run_code != '5') and (run_code = '2' || run_code = '4') and failed_remaining_count > 0
and is_virtual = '1' and is_virtual = '1'
</select> </select>
......
...@@ -114,6 +114,15 @@ ...@@ -114,6 +114,15 @@
where flow_id = #{flowId,jdbcType=INTEGER} where flow_id = #{flowId,jdbcType=INTEGER}
</select> </select>
<select id="getByMapFlowId" parameterType="integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from node
where map_flow_id = #{mapFlowId,jdbcType=INTEGER}
</select>
<delete id="deleteVirtualNode"> <delete id="deleteVirtualNode">
delete from node delete from node
where flow_id = #{flowId,jdbcType=INTEGER} where flow_id = #{flowId,jdbcType=INTEGER}
......
...@@ -81,6 +81,21 @@ ...@@ -81,6 +81,21 @@
where run_id = #{runId,jdbcType=VARCHAR} where run_id = #{runId,jdbcType=VARCHAR}
and flow_status != '4' and flow_status != '4'
</select> </select>
<select id="findByStartAndEndTime" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from run_recording
where start_time &gt;= ${startDate}
and end_time &lt;= ${endDate}
<if test="flowIds != null">
and flow_id in (
<foreach collection="flowIds" item="flowId" separator=",">
flowId
</foreach>
)
</if>
</select>
<delete id="deleteById" parameterType="java.lang.Integer"> <delete id="deleteById" parameterType="java.lang.Integer">
<!-- generated @mbg.generated date: 2019-12-25 --> <!-- generated @mbg.generated date: 2019-12-25 -->
......
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
<artifactId>myth-core-common</artifactId> <artifactId>myth-core-common</artifactId>
<dependencies> <dependencies>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
</dependency>
<!-- slf4j --> <!-- slf4j -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
......
package com.byit.executor.filesystem; package com.byit.filesystem;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import org.csource.common.MyException; import org.csource.common.MyException;
import org.csource.common.NameValuePair; import org.csource.common.NameValuePair;
import org.csource.fastdfs.*; import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
......
package com.byit.executor.filesystem; package com.byit.filesystem;
import org.csource.common.MyException; import org.csource.common.MyException;
...@@ -19,7 +19,7 @@ public interface FileSystem { ...@@ -19,7 +19,7 @@ public interface FileSystem {
* @throws IOException * @throws IOException
* @throws MyException * @throws MyException
*/ */
String uploadFile(byte[] fileBuffer, String fileExtName, Map<String,String> mateDaTA) throws IOException, MyException; String uploadFile(byte[] fileBuffer, String fileExtName, Map<String, String> mateDaTA) throws IOException, MyException;
/** /**
* 文件下载接口 * 文件下载接口
......
...@@ -34,4 +34,8 @@ public class ScriptDto implements Serializable { ...@@ -34,4 +34,8 @@ public class ScriptDto implements Serializable {
* 回调URL * 回调URL
*/ */
private String callbackUrl; private String callbackUrl;
/**
* 已有的日志路径,不存在就为null
*/
private String logRemotePath;
} }
package com.byit.job.dto;
import com.sun.xml.internal.ws.developer.Serialization;
import lombok.*;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 参数和占位符的处理
* @author huangfu
*/
@Builder
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ScriptParamAndPlaceholderDto implements Serializable {
/**
* 参数的处理
*/
private Map<String,String> param;
/**
* 占位符的处理
*/
private Map<String,String> Placeholder;
}
package com.byit.job.dto.plugin; package com.byit.job.dto.plugin;
import com.alibaba.fastjson.JSON;
import com.byit.job.dto.ScriptParamAndPlaceholderDto;
import com.sun.istack.internal.NotNull;
import lombok.Data; import lombok.Data;
import lombok.NonNull;
import java.io.Serializable; import java.io.Serializable;
...@@ -56,5 +60,13 @@ public class PluginNode extends PluginBaseNode implements Serializable { ...@@ -56,5 +60,13 @@ public class PluginNode extends PluginBaseNode implements Serializable {
*/ */
private PluginNodeConfig config; private PluginNodeConfig config;
/**
* 脚本运行参数信息
* @param scriptParam 脚本
*/
public void setScriptParam(@NotNull ScriptParamAndPlaceholderDto scriptParam){
this.runParam = JSON.toJSONString(scriptParam);
}
private static final long serialVersionUID = 2L; private static final long serialVersionUID = 2L;
} }
package com.byit.job.utils;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* 占位符替换工具类
* @author huangfu
*/
@Slf4j
public class PlaceholderUtils {
/**
* 占位符前缀
*/
private static final String PLACEHOLDER_PREFIX = "${";
/**
* 占位符后缀
*/
private static final String PLACEHOLDER_SUFFIX = "}";
/**
* 占位符数据替换
* @param scriptData
* @param parameter
* @return
*/
public static byte[] resolvePlaceholders(byte[] scriptData, Map<String,String> parameter){
//替换为null 不做操作
if(parameter == null || parameter.isEmpty()){
log.warn("------------占位符数据为空--------");
return scriptData;
}
//读取脚本文件
String scriptContent = new String(scriptData, StandardCharsets.UTF_8);
StringBuilder sbt = new StringBuilder(scriptContent);
//找到第一个需要替换的位置
int startIndex = sbt.indexOf(PLACEHOLDER_PREFIX);
//开始循环遍历
while (startIndex != -1){
//寻找这个替换符 结束的位置
int endIndex = sbt.indexOf(PLACEHOLDER_SUFFIX, startIndex + PLACEHOLDER_PREFIX.length());
//确定是否存在后缀
if(endIndex != -1){
//截取变量值
String placeholder = sbt.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex);
//确定下一次查询的位置
int nextIndex = endIndex+PLACEHOLDER_SUFFIX.length();
//开始从 map中解析
if(parameter.containsKey(placeholder)){
String placeholderValue = parameter.get(placeholder);
//替换这个位置
sbt.replace(startIndex,endIndex+PLACEHOLDER_SUFFIX.length(),placeholderValue);
//再次计算替换后的查询开始位置
nextIndex = startIndex+placeholderValue.length();
}else{
throw new RuntimeException("站位解析异常");
}
startIndex = sbt.indexOf(PLACEHOLDER_PREFIX,nextIndex);
}
}
return sbt.toString().getBytes(StandardCharsets.UTF_8);
}
public static void main(String[] args) {
String text = "123${name},1232321${sex}123123";
Map<String,String> map = new HashMap<String,String>();
map.put("name","皇甫科星");
map.put("sex","'男'");
byte[] bytes = resolvePlaceholders(text.getBytes(StandardCharsets.UTF_8), map);
System.out.println(new String(bytes, StandardCharsets.UTF_8));
}
}
...@@ -47,10 +47,10 @@ ...@@ -47,10 +47,10 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency> <!--<dependency>
<groupId>net.oschina.zcx7878</groupId> <groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId> <artifactId>fastdfs-client-java</artifactId>
</dependency> </dependency>-->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
......
package com.test; package com.test;
import com.byit.executor.filesystem.FastDfsFileSystem;
import com.byit.filesystem.FastDfsFileSystem;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.csource.common.MyException; import org.csource.common.MyException;
...@@ -12,6 +13,7 @@ import java.util.Map; ...@@ -12,6 +13,7 @@ import java.util.Map;
public class Test1 { public class Test1 {
public static void main(String[] args) throws IOException, MyException { public static void main(String[] args) throws IOException, MyException {
FastDfsFileSystem fds = new FastDfsFileSystem(); FastDfsFileSystem fds = new FastDfsFileSystem();
fds.fileRemove("ddmp/M00/00/00/CgB4Al5XoBSAZg1qAAAAW4eTPeg3226.py");
byte[] bytes = FileUtils.readFileToByteArray(new File("D:\\2020project\\byit-myth-job\\byit-myth-core\\myth-executor-core\\src\\test\\java\\com\\test\\test-ex.py")); byte[] bytes = FileUtils.readFileToByteArray(new File("D:\\2020project\\byit-myth-job\\byit-myth-core\\myth-executor-core\\src\\test\\java\\com\\test\\test-ex.py"));
Map<String,String> map = new HashMap<>(); Map<String,String> map = new HashMap<>();
map.put("filename","test-ex.py"); map.put("filename","test-ex.py");
......
import time
i = 0 i = 0
while i<100: while i<100:
print("--------%d" %i) time.sleep(1)
print("-----${name}---%d" %i)
i+=1 i+=1
\ No newline at end of file
...@@ -2,13 +2,15 @@ package com.byit.service; ...@@ -2,13 +2,15 @@ package com.byit.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.byit.executor.api.ScriptExecutorService; import com.byit.executor.api.ScriptExecutorService;
import com.byit.executor.filesystem.FileSystem;
import com.byit.executor.jobExecutor.process.MythJobProcess; import com.byit.executor.jobExecutor.process.MythJobProcess;
import com.byit.executor.jobExecutor.process.ProcessFailureException; import com.byit.executor.jobExecutor.process.ProcessFailureException;
import com.byit.filesystem.FileSystem;
import com.byit.job.dto.DispatchResponseDto; import com.byit.job.dto.DispatchResponseDto;
import com.byit.job.dto.JobRunResultDto; import com.byit.job.dto.JobRunResultDto;
import com.byit.job.dto.ScriptDto; import com.byit.job.dto.ScriptDto;
import com.byit.job.dto.ScriptParamAndPlaceholderDto;
import com.byit.job.enums.JobResultEnum; import com.byit.job.enums.JobResultEnum;
import com.byit.job.utils.PlaceholderUtils;
import com.byit.job.vo.ReturnResult; import com.byit.job.vo.ReturnResult;
import com.byit.pool.RunThreadPool; import com.byit.pool.RunThreadPool;
import com.byit.rpc.remoting.provider.annotation.RpcService; import com.byit.rpc.remoting.provider.annotation.RpcService;
...@@ -62,19 +64,39 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService { ...@@ -62,19 +64,39 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService {
String remotePath = scriptDto.getRemotePath(); String remotePath = scriptDto.getRemotePath();
String command = scriptDto.getCommand(); String command = scriptDto.getCommand();
String scriptPath = byteArrayToFile(remotePath); String param = scriptDto.getParam();
ScriptParamAndPlaceholderDto scriptParamAndPlaceholderDto = null;
if(null != param){
scriptParamAndPlaceholderDto = JSON.parseObject(param, ScriptParamAndPlaceholderDto.class);
}
String scriptPath = byteArrayToFile(remotePath,scriptParamAndPlaceholderDto);
//开始执行脚本 //开始执行脚本
List<String> cmdList = Arrays.asList(command,scriptPath); List<String> cmdList = Arrays.asList(command,scriptPath);
MythJobProcess mythJobProcess = new MythJobProcess(cmdList, null, null, scriptDto.getLogId()); MythJobProcess mythJobProcess = new MythJobProcess(cmdList, null, null, scriptDto.getLogId());
//保存日志
String logData = mythJobProcess.call(); String logData = mythJobProcess.call();
byte[] logDataByte = stringToByteArray(logData); byte[] logDataByte = stringToByteArray(logData);
Map<String,String> fileMateData = new HashMap<String,String>(2); Map<String,String> fileMateData = new HashMap<String,String>(2);
fileMateData.put("filename",scriptDto.getRunId()+scriptDto.getRunId()+".log"); fileMateData.put("filename",scriptDto.getRunId()+scriptDto.getRunId()+".log");
String logPath = ""; String logPath = "";
try { try {
//上传日志文件 //不为空 则追加
logPath = fileSystem.uploadFile(logDataByte,"log",fileMateData); if(scriptDto.getLogRemotePath() != null){
jobRunResultDto.setReturnResult(ReturnResult.SUCCESS); byte[] sourceLogByte = fileSystem.downloaderFile(scriptDto.getLogRemotePath());
byte[] resultLogByte = mergeFile(sourceLogByte, logDataByte);
//上传日志文件
logPath = fileSystem.uploadFile(resultLogByte,"log",fileMateData);
//删除原有的日志文件
fileSystem.fileRemove(scriptDto.getLogRemotePath());
}else{
//上传日志文件
logPath = fileSystem.uploadFile(logDataByte,"log",fileMateData);
jobRunResultDto.setReturnResult(ReturnResult.SUCCESS);
}
} catch (ProcessFailureException ignored){ } catch (ProcessFailureException ignored){
jobRunResultDto.setReturnResult(ReturnResult.FAIL); jobRunResultDto.setReturnResult(ReturnResult.FAIL);
} catch (IOException | MyException e) { } catch (IOException | MyException e) {
...@@ -106,11 +128,25 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService { ...@@ -106,11 +128,25 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService {
return dispatchResponseDto; return dispatchResponseDto;
} }
/**
* 合并两个字节数组
* @param sourceByte
* @param targetByte
* @return
*/
private byte[] mergeFile(byte[] sourceByte, byte[] targetByte){
byte[] result = new byte[sourceByte.length+targetByte.length];
System.arraycopy(sourceByte,0,result,0,sourceByte.length);
System.arraycopy(targetByte,0,result,sourceByte.length,targetByte.length);
return result;
}
/** /**
* 将脚本字节转换成文件 * 将脚本字节转换成文件
* @return 生成文件的本地路径 * @return 生成文件的本地路径
*/ */
private String byteArrayToFile(String remotePath){ private String byteArrayToFile(String remotePath,ScriptParamAndPlaceholderDto scriptParamAndPlaceholderDto){
//创建目录 //创建目录
File rootPathMkdir = new File(rootScriptPath,formatDate()); File rootPathMkdir = new File(rootScriptPath,formatDate());
if(!rootPathMkdir.exists()){ if(!rootPathMkdir.exists()){
...@@ -123,6 +159,12 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService { ...@@ -123,6 +159,12 @@ public class ScriptExecutorServiceImpl implements ScriptExecutorService {
try { try {
//下载脚本文件 //下载脚本文件
byte[] scriptByteArray = fileSystem.downloaderFile(remotePath); byte[] scriptByteArray = fileSystem.downloaderFile(remotePath);
/**
* 替换脚本占位符
*/
if(scriptParamAndPlaceholderDto != null){
scriptByteArray = PlaceholderUtils.resolvePlaceholders(scriptByteArray,scriptParamAndPlaceholderDto.getPlaceholder());
}
//获取文件元信息 //获取文件元信息
Map<String, String> fileMate = fileSystem.getFileMate(remotePath); Map<String, String> fileMate = fileSystem.getFileMate(remotePath);
String fileName = fileMate.get("filename"); String fileName = fileMate.get("filename");
......
package com.byit.job; package com.byit.job;
import com.alibaba.fastjson.JSON;
import com.byit.job.dto.ScriptParamAndPlaceholderDto;
import com.byit.job.dto.plugin.*; import com.byit.job.dto.plugin.*;
import com.byit.rpc.remoting.invoker.route.LoadBalance; import com.byit.rpc.remoting.invoker.route.LoadBalance;
import com.byit.utils.JobUtils; import com.byit.utils.JobUtils;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class ScriptAddFlow { public class ScriptAddFlow {
...@@ -70,9 +70,15 @@ public class ScriptAddFlow { ...@@ -70,9 +70,15 @@ public class ScriptAddFlow {
pluginNode2.setType("node"); pluginNode2.setType("node");
pluginNode2.setAuthor("皇甫"); pluginNode2.setAuthor("皇甫");
pluginNode2.setJobType("SCRIPT"); pluginNode2.setJobType("SCRIPT");
pluginNode2.setScriptUrls("ddmp/M00/00/00/CgB4Al5T7xuACemOAAAAOeUjOqs3779.py"); pluginNode2.setScriptUrls("ddmp/M00/00/00/CgB4Al5d3xmAdhrwAAAAYsb__Ck6673.py");
ScriptParamAndPlaceholderDto scriptParamAndPlaceholderDto = new ScriptParamAndPlaceholderDto();
Map<String,String> map = new HashMap<>();
map.put("name","皇甫科星");
scriptParamAndPlaceholderDto.setPlaceholder(map);
pluginNode2.setScriptParam(scriptParamAndPlaceholderDto);
pluginNode2.setRunCommand("python"); pluginNode2.setRunCommand("python");
pluginNode2.setRunParam("test1");
pluginNodeConfig2.setFailedRetryCount(2); pluginNodeConfig2.setFailedRetryCount(2);
pluginNodeConfig2.setFailedRetryInterval(TimeUnit.MINUTES.toSeconds(2)); pluginNodeConfig2.setFailedRetryInterval(TimeUnit.MINUTES.toSeconds(2));
pluginNodeConfig2.setNodeCron("0 0/7 * * * ? *"); pluginNodeConfig2.setNodeCron("0 0/7 * * * ? *");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment