1、配置文件
gateway.taskjob.maxthread=3 线最线程数
gateway.taskjob.myid=kabalaweb1
gateway.taskjob.timeSeconds=60 定时调用时间
2、任务代码
package com.kass.gateway;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.kass.kabala.KDatabase;
import com.kass.kabala.kabalautils.CTimeTools;
import com.kass.kabala.utils.KJsonTools;
import com.kass.kabala.utils.KLog;
import com.kass.kabala.utils.KMapTools;
import com.kass.kabala.utils.KStringTools;
import com.kass.kabala.utils.KTimeTools;
public class TaskJob {
private static enum JobStatus{
waiting,
runing
}
public interface MyJob {
public boolean doing(String tenantid,String taskid) throws Exception;//返回 true 表示成功 false表示失败
public void ok(String tenantid,String taskid)throws Exception;//任务执行结束
public void retryFail(String tenantid,String taskid);//任务超出通知
}
private static ExecutorService executor = null;//暂时为无序任务,后续如果任务量大的话可以考虑换成队列任务
public static void init(){
int maxThread = KStringTools.toInt(System.getProperty("gateway.taskjob.maxthread"),10); //最大执行线程
String myid = System.getProperty("gateway.taskjob.myid");
if(myid.equalsIgnoreCase(System.getProperty("kabala.myid"))) { //任务服务只允许在一台机器上运行
executor = Executors.newScheduledThreadPool(maxThread);
//发起一个任务,将状态为等待的加入队列
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
String sql = "select tenantid,taskid,status,ctime,retrycount,maxretry,jointime,exectime,execmsg,myjobclass from k_task_job where status = ? ";
List<Map> datas = KDatabase.queryJSON(sql,new String[] {JobStatus.waiting.name()});
if(datas==null || datas.size()==0 ) {
return;
}
for(int i = 0;i<datas.size();i++) {
try {
String tenantid = KMapTools.getString(datas.get(i),"tenantid");
String taskid = KMapTools.getString(datas.get(i),"taskid");
int retrycount = KMapTools.getInt(datas.get(i),"retrycount");
int maxretry = KMapTools.getInt(datas.get(i),"maxretry");
String myjobclass = KMapTools.getString(datas.get(i),"myjobclass");
if(maxretry>0 && retrycount>=maxretry) {
KLog.info("关闭任务","任务超出最大执行次数",KJsonTools.map2json(datas.get(i)));
closeJob(tenantid,taskid);
try {
MyJob myjob = (MyJob)Class.forName(myjobclass).newInstance();
myjob.retryFail(tenantid,taskid);
}catch(Exception e) {
KLog.error(e);
}
}else {
KLog.info("任务加入队列",KJsonTools.map2json(datas.get(i)));
execJob(datas.get(i));
}
}catch(Exception e) {//一个任务调度出错,不影响其他的
KLog.error(e);
}
}
}catch(Exception e) {
KLog.error(e);
}
}
},1000L, KStringTools.toInt(System.getProperty("gateway.taskjob.timeSeconds"),60)*1000L);
}
}
//重置任务为等待状态
private static void restJob(String tenantid,String taskid,long exectime,String execmsg) throws Exception{
String sql = "update k_task_job set status = ? , exectime = ? , execmsg = ? where tenantid = ? and taskid = ? ";
KDatabase.execute(sql,new String[] {
JobStatus.waiting.name(),
String.valueOf(exectime),
execmsg,
tenantid,
taskid
});
KLog.info("任务状态重置",tenantid,taskid,String.valueOf(exectime),execmsg);
}
//关闭任务
private static void closeJob(String tenantid,String taskid) throws Exception{
String sql = "delete from k_task_job where tenantid = ? and taskid = ?";
KDatabase.execute(sql,new String[] {tenantid,taskid});
KLog.info("任务删除",tenantid,taskid);
}
private static void execJob(final Map jobdatas) throws Exception{
final String tenantid = KMapTools.getString(jobdatas,"tenantid");
final String taskid = KMapTools.getString(jobdatas,"taskid");
final int retrycount = KMapTools.getInt(jobdatas,"retrycount");
final int maxretry = KMapTools.getInt(jobdatas,"maxretry");
final String myjobclass = KMapTools.getString(jobdatas,"myjobclass");
if(maxretry>0 && retrycount>=maxretry) {
throw new Exception("任务超出最大限制次数");
}
//标记任务状态及加入时间
String sql = "update k_task_job set status = ? , jointime = ? , retrycount=? where tenantid = ? and taskid = ? ";
KDatabase.execute(sql,new String[] {
JobStatus.runing.name(),
String.valueOf(CTimeTools.getTimeNumber(System.currentTimeMillis())),
String.valueOf( (retrycount+1) ),
tenantid,
taskid
});
//加入队列
executor.execute(new Runnable() {
@Override
public void run() {
long exectime = KTimeTools.getTimeNumber(System.currentTimeMillis());
try {
KLog.info("任务执行开始",KJsonTools.map2json(jobdatas));
MyJob myjob = (MyJob)com.kass.kabala.utils.KReflectTools.createInstance(myjobclass);
if(myjob.doing(tenantid,taskid) ) { //执行成功
closeJob(tenantid,taskid);
myjob.ok(tenantid,taskid);//任务释放后进行通知
KLog.info("任务执行成功",KJsonTools.map2json(jobdatas));
}else {
throw new Exception("Doing Fail");
}
}catch(Exception e) {
KLog.error(e);
KLog.info("任务执行出错",KJsonTools.map2json(jobdatas),e.getMessage());
try {
restJob(tenantid,taskid,exectime,e.getMessage());
} catch (Exception e1) {
KLog.error(e1);
}
}
}
});
}
/***
* 添加一条任务
* @param tenantid 租户ID
* @param taskid 业务方ID
* @param myjobclass 执行任务class的位置,需实现TaskJob.myjob
* @param maxRetry 最大执行次数,0表示不限制次数
* @throws Exception
*/
public static void addJob(String tenantid,String taskid,String myjobclass,int maxRetry) throws Exception{
String sql = "select taskid from k_task_job where taskid = ? ";
String[][] datas = KDatabase.query(sql,new String[] {taskid});
if(datas!=null && datas.length>0) {
return;//之前已存在
}
sql = "insert into k_task_job(tenantid,taskid,status,ctime,retrycount,maxretry,myjobclass) values (?,?,?,?,?,?,?)";
KDatabase.execute(sql,new String[] {
tenantid,
taskid,
JobStatus.waiting.name(),
String.valueOf(CTimeTools.getTimeNumber(System.currentTimeMillis())),
String.valueOf(0),
String.valueOf(maxRetry),
myjobclass
});
}
}
3、重写方法
@Override
public boolean doing(String tenantid, String taskid) throws Exception {
String sql = "select gt.cuserid,gt.taskjson,gtf.cnum,gtf.filename from gateway_task gt\n" +
"INNER JOIN gateway_task_files gtf on gtf.taskid = gt.taskid\n" +
"where gt.tenantid = ? and gt.taskid = ?\n";
List<Map> datas = KDatabase.queryJSON(sql, new String[]{tenantid,taskid});
Boolean boo = null;
try {
//敏感词统计
boo = Task.setSensitiveCount(KMapTools.getString(datas.get(0), "cuserid"), KMapTools.getLong(datas.get(0), "cnum"), KMapTools.getString(datas.get(0), "filename"));
if (boo) {
return boo;
} else {
return false;
}
} catch (Exception e) {
sql = "update gateway_task set taskstatus=? where tenantid = ? and taskid = ?";
KDatabase.execute(sql, new String[]{Task.TaskStatus_ReadingFile, tenantid, taskid});
KLog.info("敏感词统计失败:" + KMapTools.getString(datas.get(0), "filename") + e);
KLog.error(e);
return false;
}
}
@Override
public void ok(String tenantid, String taskid) throws Exception {
String sql = "select gt.cuserid,gt.taskjson,gtf.cnum,gtf.filename from gateway_task gt\n" +
"INNER JOIN gateway_task_files gtf on gtf.taskid = gt.taskid\n" +
"where gt.tenantid = ? and gt.taskid = ?\n";
try {
List<Map> datas = KDatabase.queryJSON(sql, new String[]{tenantid,taskid});
//触发审批流
Task.sendFolws(tenantid, KMapTools.getString(datas.get(0), "cuserid"), KMapTools.getString(datas.get(0), "taskjson"), taskid);
} catch (Exception e) {
KLog.info("审批流触发失败:" + taskid + e.getMessage());
sql = "update gateway_task set taskstatus=? where tenantid = ? and taskid = ?";
KDatabase.execute(sql, new String[]{Task.TaskStatus_ReadingFile, tenantid, taskid});
}
}
@Override
public void retryFail(String tenantid, String taskid) {
KLog.info("敏感词统计失败:" +taskid);
try {
String sql = "update gateway_task set taskstatus=? where tenantid = ? and taskid = ?";
KDatabase.execute(sql, new String[]{Task.TaskStatus_ReadingFile, tenantid, taskid});
} catch (Exception e) {
e.printStackTrace();
KLog.error(e);
}
}
4、数据库表
CREATE TABLE `k_task_job` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tenantid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`taskid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`status` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`retrycount` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`maxretry` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`myjobclass` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`execmsg` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`ctime` bigint(20) DEFAULT NULL,
`jointime` bigint(20) DEFAULT NULL,
`exectime` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_k_task_job_1` (`tenantid`),
KEY `idx_k_task_job_2` (`taskid`),
KEY `idx_k_task_job_3` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=297 DEFAULT CHARSET=utf8;