use of com.vip.saturn.job.console.exception.SaturnJobConsoleException in project Saturn by vipshop.
the class JobOperationRestApiControllerTest method testCreateFailAsJobAlreadyExisted.
@Test
public void testCreateFailAsJobAlreadyExisted() throws Exception {
JobEntity jobEntity = constructJobEntity("job2");
String errMsg = "该作业(job2)已经存在";
willThrow(new SaturnJobConsoleException(SaturnJobConsoleException.ERROR_CODE_BAD_REQUEST, errMsg)).given(restApiService).createJob(any(String.class), any(JobConfig.class));
MvcResult result = mvc.perform(post("/rest/v1/domain/jobs").contentType(MediaType.APPLICATION_JSON).content(jobEntity.toJSON())).andExpect(status().isBadRequest()).andReturn();
String message = fetchErrorMessage(result);
assertEquals("error message not equal", "该作业(job2)已经存在", message);
}
use of com.vip.saturn.job.console.exception.SaturnJobConsoleException in project Saturn by vipshop.
the class SaturnConsoleUtils method exportFile.
public static void exportFile(HttpServletResponse response, InputStream inputStream, String exportFileName) throws SaturnJobConsoleException {
try {
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment; filename=" + new String(exportFileName.getBytes("UTF-8"), "ISO8859-1"));
try (BufferedInputStream bis = new BufferedInputStream(inputStream);
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
}
} catch (Exception e) {
throw new SaturnJobConsoleException(e);
}
}
use of com.vip.saturn.job.console.exception.SaturnJobConsoleException in project Saturn by vipshop.
the class JobServiceImpl method updateJobCron.
@Transactional(rollbackFor = Exception.class)
@Override
public void updateJobCron(String namespace, String jobName, String cron, Map<String, String> customContext, String updatedBy) throws SaturnJobConsoleException {
String cron0 = cron;
if (cron0 != null && !cron0.trim().isEmpty()) {
try {
cron0 = cron0.trim();
CronExpression.validateExpression(cron0);
} catch (ParseException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, "The cron expression is invalid: " + cron);
}
} else {
cron0 = "";
}
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = registryCenterService.getCuratorFrameworkOp(namespace);
if (curatorFrameworkOp.checkExists(JobNodePath.getConfigNodePath(jobName))) {
String newCustomContextStr = null;
String oldCustomContextStr = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, CONFIG_ITEM_CUSTOM_CONTEXT));
Map<String, String> oldCustomContextMap = toCustomContext(oldCustomContextStr);
if (customContext != null && !customContext.isEmpty()) {
oldCustomContextMap.putAll(customContext);
newCustomContextStr = toCustomContext(oldCustomContextMap);
if (newCustomContextStr.length() > 8000) {
throw new SaturnJobConsoleException("The all customContext is out of db limit (Varchar[8000])");
}
if (newCustomContextStr.getBytes().length > 1024 * 1024) {
throw new SaturnJobConsoleException("The all customContext is out of zk limit memory(1M)");
}
}
String newCron = null;
String oldCron = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, CONFIG_ITEM_CRON));
if (cron0 != null && oldCron != null && !cron0.equals(oldCron.trim())) {
newCron = cron0;
}
if (newCustomContextStr != null || newCron != null) {
saveCronToDb(jobName, curatorFrameworkOp, newCustomContextStr, newCron, updatedBy);
}
if (newCustomContextStr != null) {
curatorFrameworkOp.update(JobNodePath.getConfigNodePath(jobName, CONFIG_ITEM_CUSTOM_CONTEXT), newCustomContextStr);
}
if (newCron != null) {
curatorFrameworkOp.update(JobNodePath.getConfigNodePath(jobName, CONFIG_ITEM_CRON), newCron);
}
} else {
throw new SaturnJobConsoleException(ERROR_CODE_NOT_EXISTED, "The job does not exists: " + jobName);
}
}
use of com.vip.saturn.job.console.exception.SaturnJobConsoleException in project Saturn by vipshop.
the class JobServiceImpl method batchSetGroups.
/**
* 批量设置作业的分组
*
* @param namespace
* @param jobNames 待设置分组的作业名集合
* @param oldGroupNames 修改前的分组名集合
* @param newGroupNames 修改后的分组名集合
* @param userName 操作者
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void batchSetGroups(String namespace, List<String> jobNames, List<String> oldGroupNames, List<String> newGroupNames, String userName) throws SaturnJobConsoleException {
if (CollectionUtils.isEmpty(jobNames)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, "请选择要分组的作业");
}
if (CollectionUtils.isEmpty(oldGroupNames) && CollectionUtils.isEmpty(newGroupNames)) {
return;
}
List<String> oldGroupNamesTemp = null;
List<String> newGroupNamesTemp = null;
Pattern pattern = Pattern.compile("[`!@#$%^!@#¥%……&*()|{}【】‘;:”“’。,、? ]");
if (!CollectionUtils.isEmpty(oldGroupNames)) {
for (String groupName : oldGroupNames) {
validateGroupName(groupName, pattern);
}
oldGroupNamesTemp = new ArrayList<>(oldGroupNames);
}
if (!CollectionUtils.isEmpty(newGroupNames)) {
for (String groupName : newGroupNames) {
validateGroupName(groupName, pattern);
}
newGroupNamesTemp = new ArrayList<>(newGroupNames);
}
// 新旧分组集合元素相同,无需处理
if (!CollectionUtils.isEmpty(oldGroupNames) && !CollectionUtils.isEmpty(newGroupNames)) {
Collections.sort(oldGroupNames);
Collections.sort(newGroupNames);
if (oldGroupNames.toString().equals(newGroupNames.toString())) {
return;
}
}
// 中存在,newGroupNamesTemp 中不存在的元素),即删除的分组
if (!CollectionUtils.isEmpty(oldGroupNamesTemp) && !CollectionUtils.isEmpty(newGroupNamesTemp)) {
oldGroupNamesTemp.removeAll(newGroupNamesTemp);
}
// 前端操作有删除分组,则将删除的分组从数据库中删除
if (!CollectionUtils.isEmpty(oldGroupNamesTemp)) {
for (String groupName : oldGroupNamesTemp) {
currentJobConfigService.batchSetGroups(namespace, jobNames, groupName, userName);
}
}
// 中不存在的元素),即新增的分组
if (!CollectionUtils.isEmpty(newGroupNames) && !CollectionUtils.isEmpty(oldGroupNames)) {
newGroupNames.removeAll(oldGroupNames);
}
// 前端操作有新增分组,则将新增的分组追加到原有分组后面,用英文逗号连接
if (!CollectionUtils.isEmpty(newGroupNames)) {
for (String groupName : newGroupNames) {
currentJobConfigService.addToGroups(namespace, jobNames, groupName, userName);
}
}
}
use of com.vip.saturn.job.console.exception.SaturnJobConsoleException in project Saturn by vipshop.
the class JobServiceImpl method convertJobConfig.
private JobConfig convertJobConfig(int sheetNumber, int rowNumber, Cell[] rowCells) throws SaturnJobConsoleException {
String jobName = getContents(rowCells, 0);
if (jobName == null || jobName.trim().isEmpty()) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 1, "作业名必填。"));
}
if (!jobName.matches("[0-9a-zA-Z_]*")) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 1, "作业名只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_。"));
}
JobConfig jobConfig = new JobConfig();
jobConfig.setJobName(jobName);
String jobType = getContents(rowCells, 1);
if (jobType == null || jobType.trim().isEmpty()) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 2, "作业类型必填。"));
}
JobType jobTypeObj = JobType.getJobType(jobType);
if (jobTypeObj == JobType.UNKNOWN_JOB) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 2, "作业类型未知。"));
}
jobConfig.setJobType(jobType);
String jobClass = getContents(rowCells, 2);
if (JobType.isJava(jobTypeObj) && (jobClass == null || jobClass.trim().isEmpty())) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 3, "对于java作业,作业实现类必填。"));
}
jobConfig.setJobClass(jobClass);
String cron = getContents(rowCells, 3);
if (JobType.isCron(jobTypeObj)) {
if (cron == null || cron.trim().isEmpty()) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 4, "对于cron作业,cron表达式必填。"));
}
cron = cron.trim();
try {
CronExpression.validateExpression(cron);
} catch (ParseException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 4, "cron表达式语法有误," + e));
}
} else {
// 其他类型的不需要持久化保存cron表达式
cron = "";
}
jobConfig.setCron(cron);
jobConfig.setDescription(getContents(rowCells, 4));
jobConfig.setLocalMode(Boolean.valueOf(getContents(rowCells, 5)));
int shardingTotalCount = 1;
if (jobConfig.getLocalMode()) {
jobConfig.setShardingTotalCount(shardingTotalCount);
} else {
String tmp = getContents(rowCells, 6);
if (tmp != null && !tmp.trim().isEmpty()) {
try {
shardingTotalCount = Integer.parseInt(tmp);
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 7, "分片数有误," + e));
}
} else {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 7, "分片数必填"));
}
if (shardingTotalCount < 1) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 7, "分片数不能小于1"));
}
jobConfig.setShardingTotalCount(shardingTotalCount);
}
int timeoutSeconds = 0;
try {
String tmp = getContents(rowCells, 7);
if (tmp != null && !tmp.trim().isEmpty()) {
timeoutSeconds = Integer.parseInt(tmp.trim());
}
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 8, "超时(Kill线程/进程)时间有误," + e));
}
jobConfig.setTimeoutSeconds(timeoutSeconds);
jobConfig.setJobParameter(getContents(rowCells, 8));
String shardingItemParameters = getContents(rowCells, 9);
if (jobConfig.getLocalMode()) {
if (shardingItemParameters == null || shardingItemParameters.trim().isEmpty()) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 10, "对于本地模式作业,分片参数必填。"));
} else {
String[] split = shardingItemParameters.split(",");
boolean includeXing = false;
for (String tmp : split) {
String[] split2 = tmp.split("=");
if ("*".equalsIgnoreCase(split2[0].trim())) {
includeXing = true;
break;
}
}
if (!includeXing) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 10, "对于本地模式作业,分片参数必须包含如*=xx。"));
}
}
} else if ((shardingTotalCount > 0) && (shardingItemParameters == null || shardingItemParameters.trim().isEmpty() || shardingItemParameters.split(",").length < shardingTotalCount)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 10, "分片参数不能小于分片总数。"));
}
jobConfig.setShardingItemParameters(shardingItemParameters);
jobConfig.setQueueName(getContents(rowCells, 10));
jobConfig.setChannelName(getContents(rowCells, 11));
jobConfig.setPreferList(getContents(rowCells, 12));
jobConfig.setUseDispreferList(!Boolean.parseBoolean(getContents(rowCells, 13)));
int processCountIntervalSeconds = 300;
try {
String tmp = getContents(rowCells, 14);
if (tmp != null && !tmp.trim().isEmpty()) {
processCountIntervalSeconds = Integer.parseInt(tmp.trim());
}
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 15, "统计处理数据量的间隔秒数有误," + e));
}
jobConfig.setProcessCountIntervalSeconds(processCountIntervalSeconds);
int loadLevel = 1;
try {
String tmp = getContents(rowCells, 15);
if (tmp != null && !tmp.trim().isEmpty()) {
loadLevel = Integer.parseInt(tmp.trim());
}
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 16, "负荷有误," + e));
}
jobConfig.setLoadLevel(loadLevel);
jobConfig.setShowNormalLog(Boolean.valueOf(getContents(rowCells, 16)));
jobConfig.setPausePeriodDate(getContents(rowCells, 17));
jobConfig.setPausePeriodTime(getContents(rowCells, 18));
jobConfig.setUseSerial(Boolean.valueOf(getContents(rowCells, 19)));
int jobDegree = 0;
try {
String tmp = getContents(rowCells, 20);
if (tmp != null && !tmp.trim().isEmpty()) {
jobDegree = Integer.parseInt(tmp.trim());
}
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(createExceptionMessage(sheetNumber, rowNumber, 21, "作业重要等级有误," + e));
}
jobConfig.setJobDegree(jobDegree);
// 第21列,上报运行状态失效,由算法决定是否上报,看下面setEnabledReport时的逻辑,看addJob
String jobMode = getContents(rowCells, 22);
if (jobMode != null && jobMode.startsWith(com.vip.saturn.job.console.domain.JobMode.SYSTEM_PREFIX)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 23, "作业模式有误,不能添加系统作业"));
}
jobConfig.setJobMode(jobMode);
String dependencies = getContents(rowCells, 23);
if (dependencies != null && !dependencies.matches("[0-9a-zA-Z_,]*")) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 24, "依赖的作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,"));
}
jobConfig.setDependencies(dependencies);
jobConfig.setGroups(getContents(rowCells, 24));
int timeout4AlarmSeconds = 0;
try {
String tmp = getContents(rowCells, 25);
if (tmp != null && !tmp.trim().isEmpty()) {
timeout4AlarmSeconds = Integer.parseInt(tmp.trim());
}
} catch (NumberFormatException e) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 26, "超时(告警)时间有误," + e));
}
jobConfig.setTimeout4AlarmSeconds(timeout4AlarmSeconds);
String timeZone = getContents(rowCells, 26);
if (timeZone == null || timeZone.trim().length() == 0) {
timeZone = SaturnConstants.TIME_ZONE_ID_DEFAULT;
} else {
timeZone = timeZone.trim();
if (!SaturnConstants.TIME_ZONE_IDS.contains(timeZone)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 27, "时区有误"));
}
}
jobConfig.setTimeZone(timeZone);
Boolean failover = null;
String failoverStr = getContents(rowCells, 27);
if (StringUtils.isNotBlank(failoverStr)) {
failover = Boolean.valueOf(failoverStr.trim());
if (failover) {
if (jobConfig.getLocalMode()) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 28, "本地模式不支持failover"));
}
if (JobType.isMsg(jobTypeObj)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 28, "消息作业不支持failover"));
}
// 如果不上报运行状态,则强制设置为false
// 上报运行状态失效,由算法决定是否上报,看下面setEnabledReport时的逻辑,看addJob
}
}
jobConfig.setFailover(failover);
Boolean rerun = null;
String rerunStr = getContents(rowCells, 28);
if (StringUtils.isNotBlank(rerunStr)) {
rerun = Boolean.valueOf(rerunStr.trim());
if (rerun) {
if (JobType.isMsg(jobTypeObj)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 29, "消息作业不支持rerun"));
}
if (JobType.isPassive(jobTypeObj)) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 29, "被动作业不支持rerun"));
}
// 如果不上报运行状态,则强制设置为false
// 上报运行状态失效,由算法决定是否上报,看下面setEnabledReport时的逻辑,看addJob
}
}
jobConfig.setRerun(rerun);
String upStream = getContents(rowCells, 29);
if (upStream != null && !upStream.matches("[0-9a-zA-Z_,]*")) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 30, "上游作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,"));
}
jobConfig.setUpStream(upStream);
String downStream = getContents(rowCells, 30);
if (downStream != null && !downStream.matches("[0-9a-zA-Z_,]*")) {
throw new SaturnJobConsoleException(ERROR_CODE_BAD_REQUEST, createExceptionMessage(sheetNumber, rowNumber, 31, "下游作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,"));
}
jobConfig.setDownStream(downStream);
return jobConfig;
}
Aggregations