[Feature][api] schedule add timezone support #5259 (#5465)

* [Feature][api] schedule add timezone support #5259

* import moment-timezone

* fix code smell
This commit is contained in:
ruanwenjun 2021-05-17 21:08:20 +08:00 committed by GitHub
parent 68301db6b9
commit a925f64571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 443 additions and 299 deletions

View File

@ -94,7 +94,8 @@ public class SchedulerController extends BaseController {
@ApiOperation(value = "createSchedule", notes = "CREATE_SCHEDULE_NOTES")
@ApiImplicitParams({
@ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"),
@ApiImplicitParam(name = "schedule", value = "SCHEDULE", dataType = "String", example = "{'startTime':'2019-06-10 00:00:00','endTime':'2019-06-13 00:00:00','crontab':'0 0 3/6 * * ? *'}"),
@ApiImplicitParam(name = "schedule", value = "SCHEDULE", dataType = "String",
example = "{'startTime':'2019-06-10 00:00:00','endTime':'2019-06-13 00:00:00','timezoneId':'America/Phoenix','crontab':'0 0 3/6 * * ? *'}"),
@ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", type = "WarningType"),
@ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", dataType = "Int", example = "100"),
@ApiImplicitParam(name = "failureStrategy", value = "FAILURE_STRATEGY", type = "FailureStrategy"),

View File

@ -14,62 +14,74 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dolphinscheduler.api.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* schedule parameters
*/
public class ScheduleParam {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date endTime;
private String crontab;
public ScheduleParam() {
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date endTime;
private String crontab;
private String timezoneId;
public ScheduleParam(Date startTime, Date endTime, String crontab) {
this.startTime = startTime;
this.endTime = endTime;
this.crontab = crontab;
}
public ScheduleParam() {
}
public Date getStartTime() {
return startTime;
}
public ScheduleParam(Date startTime, Date endTime, String timezoneId, String crontab) {
this.startTime = startTime;
this.endTime = endTime;
this.timezoneId = timezoneId;
this.crontab = crontab;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getStartTime() {
return startTime;
}
public Date getEndTime() {
return endTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public Date getEndTime() {
return endTime;
}
public String getCrontab() {
return crontab;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public void setCrontab(String crontab) {
this.crontab = crontab;
}
public String getCrontab() {
return crontab;
}
public void setCrontab(String crontab) {
this.crontab = crontab;
}
@Override
public String toString() {
return "ScheduleParam{" +
"startTime=" + startTime +
", endTime=" + endTime +
", crontab='" + crontab + '\'' +
'}';
}
public String getTimezoneId() {
return timezoneId;
}
public void setTimezoneId(String timezoneId) {
this.timezoneId = timezoneId;
}
@Override
public String toString() {
return "ScheduleParam{"
+ "startTime=" + startTime
+ ", endTime=" + endTime
+ ", crontab='" + crontab + '\''
+ ", timezoneId='" + timezoneId + '\''
+ '}';
}
}

View File

@ -157,6 +157,7 @@ public class SchedulerServiceImpl extends BaseServiceImpl implements SchedulerSe
return result;
}
scheduleObj.setCrontab(scheduleParam.getCrontab());
scheduleObj.setTimezoneId(scheduleParam.getTimezoneId());
scheduleObj.setWarningType(warningType);
scheduleObj.setWarningGroupId(warningGroupId);
scheduleObj.setFailureStrategy(failureStrategy);
@ -258,6 +259,7 @@ public class SchedulerServiceImpl extends BaseServiceImpl implements SchedulerSe
return result;
}
schedule.setCrontab(scheduleParam.getCrontab());
schedule.setTimezoneId(scheduleParam.getTimezoneId());
}
if (warningType != null) {
@ -471,20 +473,9 @@ public class SchedulerServiceImpl extends BaseServiceImpl implements SchedulerSe
}
public void setSchedule(int projectId, Schedule schedule) {
int scheduleId = schedule.getId();
logger.info("set schedule, project id: {}, scheduleId: {}", projectId, scheduleId);
Date startDate = schedule.getStartTime();
Date endDate = schedule.getEndTime();
String jobName = QuartzExecutors.buildJobName(scheduleId);
String jobGroupName = QuartzExecutors.buildJobGroupName(projectId);
Map<String, Object> dataMap = QuartzExecutors.buildDataMap(projectId, scheduleId, schedule);
QuartzExecutors.getInstance().addJob(ProcessScheduleJob.class, jobName, jobGroupName, startDate, endDate,
schedule.getCrontab(), dataMap);
logger.info("set schedule, project id: {}, scheduleId: {}", projectId, schedule.getId());
QuartzExecutors.getInstance().addJob(ProcessScheduleJob.class, projectId, schedule);
}
/**

View File

@ -22,9 +22,11 @@ import org.apache.dolphinscheduler.common.Constants;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -492,6 +494,34 @@ public class DateUtils {
return getCurrentTime(Constants.YYYYMMDDHHMMSSSSS);
}
/**
* transform date to target timezone date
* <p>e.g.
* <p> if input date is 2020-01-01 00:00:00 current timezone is CST
* <p>targetTimezoneId is MST
* <p>this method will return 2020-01-01 15:00:00
*/
public static Date getTimezoneDate(Date date, String targetTimezoneId) {
if (StringUtils.isEmpty(targetTimezoneId)) {
return date;
}
String dateToString = dateToString(date);
LocalDateTime localDateTime = LocalDateTime.parse(dateToString, DateTimeFormatter.ofPattern(Constants.YYYY_MM_DD_HH_MM_SS));
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, TimeZone.getTimeZone(targetTimezoneId).toZoneId());
return Date.from(zonedDateTime.toInstant());
}
/**
* get timezone by timezoneId
*/
public static TimeZone getTimezone(String timezoneId) {
if (StringUtils.isEmpty(timezoneId)) {
return null;
}
return TimeZone.getTimeZone(timezoneId);
}
static final long C0 = 1L;
static final long C1 = C0 * 1000L;
static final long C2 = C1 * 1000L;

View File

@ -20,6 +20,7 @@ package org.apache.dolphinscheduler.common.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import org.junit.Assert;
import org.junit.Test;
@ -204,4 +205,16 @@ public class DateUtilsTest {
Assert.assertNull(DateUtils.format2Duration(d1, d2));
}
@Test
public void testTransformToTimezone() {
Date date = new Date();
Date mst = DateUtils.getTimezoneDate(date, TimeZone.getDefault().getID());
Assert.assertEquals(DateUtils.dateToString(date), DateUtils.dateToString(mst));
}
@Test
public void testGetTimezone() {
Assert.assertNull(DateUtils.getTimezone(null));
Assert.assertEquals(TimeZone.getTimeZone("MST"), DateUtils.getTimezone("MST"));
}
}

View File

@ -14,13 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dolphinscheduler.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.dolphinscheduler.common.enums.FailureStrategy;
import org.apache.dolphinscheduler.common.enums.Priority;
import org.apache.dolphinscheduler.common.enums.ReleaseState;
@ -28,6 +24,12 @@ import org.apache.dolphinscheduler.common.enums.WarningType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* schedule
*
@ -35,278 +37,285 @@ import java.util.Date;
@TableName("t_ds_schedules")
public class Schedule {
@TableId(value="id", type=IdType.AUTO)
private int id;
/**
* process definition id
*/
private int processDefinitionId;
@TableId(value = "id", type = IdType.AUTO)
private int id;
/**
* process definition id
*/
private int processDefinitionId;
/**
* process definition name
*/
@TableField(exist = false)
private String processDefinitionName;
/**
* process definition name
*/
@TableField(exist = false)
private String processDefinitionName;
/**
* project name
*/
@TableField(exist = false)
private String projectName;
/**
* project name
*/
@TableField(exist = false)
private String projectName;
/**
* schedule description
*/
@TableField(exist = false)
private String definitionDescription;
/**
* schedule description
*/
@TableField(exist = false)
private String definitionDescription;
/**
* schedule start time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date startTime;
/**
* schedule start time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date startTime;
/**
* schedule end time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date endTime;
/**
* schedule end time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date endTime;
/**
* crontab expression
*/
private String crontab;
/**
* timezoneId
* <p>see {@link java.util.TimeZone#getTimeZone(String)}
*/
private String timezoneId;
/**
* failure strategy
*/
private FailureStrategy failureStrategy;
/**
* crontab expression
*/
private String crontab;
/**
* warning type
*/
private WarningType warningType;
/**
* failure strategy
*/
private FailureStrategy failureStrategy;
/**
* create time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
/**
* warning type
*/
private WarningType warningType;
/**
* update time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;
/**
* create time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createTime;
/**
* created user id
*/
private int userId;
/**
* update time
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date updateTime;
/**
* created user name
*/
@TableField(exist = false)
private String userName;
/**
* created user id
*/
private int userId;
/**
* release state
*/
private ReleaseState releaseState;
/**
* created user name
*/
@TableField(exist = false)
private String userName;
/**
* warning group id
*/
private int warningGroupId;
/**
* release state
*/
private ReleaseState releaseState;
/**
* warning group id
*/
private int warningGroupId;
/**
* process instance priority
*/
private Priority processInstancePriority;
/**
* process instance priority
*/
private Priority processInstancePriority;
/**
* worker group
*/
private String workerGroup;
/**
* worker group
*/
private String workerGroup;
public int getWarningGroupId() {
return warningGroupId;
}
public int getWarningGroupId() {
return warningGroupId;
}
public void setWarningGroupId(int warningGroupId) {
this.warningGroupId = warningGroupId;
}
public void setWarningGroupId(int warningGroupId) {
this.warningGroupId = warningGroupId;
}
public Schedule() {
}
public String getProjectName() {
return projectName;
}
public Schedule() {
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getProjectName() {
return projectName;
}
public Date getStartTime() {
return startTime;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public Date getStartTime() {
public String getTimezoneId() {
return timezoneId;
}
return startTime;
}
public void setTimezoneId(String timezoneId) {
this.timezoneId = timezoneId;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public String getCrontab() {
return crontab;
}
public Date getEndTime() {
return endTime;
}
public void setCrontab(String crontab) {
this.crontab = crontab;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public FailureStrategy getFailureStrategy() {
return failureStrategy;
}
public String getCrontab() {
return crontab;
}
public void setFailureStrategy(FailureStrategy failureStrategy) {
this.failureStrategy = failureStrategy;
}
public void setCrontab(String crontab) {
this.crontab = crontab;
}
public WarningType getWarningType() {
return warningType;
}
public FailureStrategy getFailureStrategy() {
return failureStrategy;
}
public void setWarningType(WarningType warningType) {
this.warningType = warningType;
}
public void setFailureStrategy(FailureStrategy failureStrategy) {
this.failureStrategy = failureStrategy;
}
public Date getCreateTime() {
return createTime;
}
public WarningType getWarningType() {
return warningType;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public void setWarningType(WarningType warningType) {
this.warningType = warningType;
}
public ReleaseState getReleaseState() {
return releaseState;
}
public Date getCreateTime() {
return createTime;
}
public void setReleaseState(ReleaseState releaseState) {
this.releaseState = releaseState;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public int getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(int processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public ReleaseState getReleaseState() {
return releaseState;
}
public String getProcessDefinitionName() {
return processDefinitionName;
}
public void setReleaseState(ReleaseState releaseState) {
this.releaseState = releaseState;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public int getProcessDefinitionId() {
return processDefinitionId;
}
public int getUserId() {
return userId;
}
public void setProcessDefinitionId(int processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getProcessDefinitionName() {
return processDefinitionName;
}
public String getUserName() {
return userName;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUpdateTime() {
return updateTime;
}
public int getId() {
return id;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public Priority getProcessInstancePriority() {
return processInstancePriority;
}
public void setUserId(int userId) {
this.userId = userId;
}
public void setProcessInstancePriority(Priority processInstancePriority) {
this.processInstancePriority = processInstancePriority;
}
public String getUserName() {
return userName;
}
public String getWorkerGroup() {
return workerGroup;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setWorkerGroup(String workerGroup) {
this.workerGroup = workerGroup;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "Schedule{"
+ "id=" + id
+ ", processDefinitionId=" + processDefinitionId
+ ", processDefinitionName='" + processDefinitionName + '\''
+ ", projectName='" + projectName + '\''
+ ", description='" + definitionDescription + '\''
+ ", startTime=" + startTime
+ ", endTime=" + endTime
+ ", timezoneId='" + timezoneId + +'\''
+ ", crontab='" + crontab + '\''
+ ", failureStrategy=" + failureStrategy
+ ", warningType=" + warningType
+ ", createTime=" + createTime
+ ", updateTime=" + updateTime
+ ", userId=" + userId
+ ", userName='" + userName + '\''
+ ", releaseState=" + releaseState
+ ", warningGroupId=" + warningGroupId
+ ", processInstancePriority=" + processInstancePriority
+ ", workerGroup='" + workerGroup + '\''
+ '}';
}
public void setId(int id) {
this.id = id;
}
public String getDefinitionDescription() {
return definitionDescription;
}
public Priority getProcessInstancePriority() {
return processInstancePriority;
}
public void setProcessInstancePriority(Priority processInstancePriority) {
this.processInstancePriority = processInstancePriority;
}
public String getWorkerGroup() {
return workerGroup;
}
public void setWorkerGroup(String workerGroup) {
this.workerGroup = workerGroup;
}
@Override
public String toString() {
return "Schedule{" +
"id=" + id +
", processDefinitionId=" + processDefinitionId +
", processDefinitionName='" + processDefinitionName + '\'' +
", projectName='" + projectName + '\'' +
", description='" + definitionDescription + '\'' +
", startTime=" + startTime +
", endTime=" + endTime +
", crontab='" + crontab + '\'' +
", failureStrategy=" + failureStrategy +
", warningType=" + warningType +
", createTime=" + createTime +
", updateTime=" + updateTime +
", userId=" + userId +
", userName='" + userName + '\'' +
", releaseState=" + releaseState +
", warningGroupId=" + warningGroupId +
", processInstancePriority=" + processInstancePriority +
", workerGroup='" + workerGroup + '\'' +
'}';
}
public String getDefinitionDescription() {
return definitionDescription;
}
public void setDefinitionDescription(String definitionDescription) {
this.definitionDescription = definitionDescription;
}
public void setDefinitionDescription(String definitionDescription) {
this.definitionDescription = definitionDescription;
}
}

View File

@ -19,11 +19,11 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.apache.dolphinscheduler.dao.mapper.ScheduleMapper">
<sql id="baseSql">
id, process_definition_id, start_time, end_time, crontab, failure_strategy, user_id, release_state,
id, process_definition_id, start_time, end_time, timezone_id, crontab, failure_strategy, user_id, release_state,
warning_type, warning_group_id, process_instance_priority, worker_group, create_time, update_time
</sql>
<sql id="baseSqlV2">
${alias}.id, ${alias}.process_definition_id, ${alias}.start_time, ${alias}.end_time, ${alias}.crontab, ${alias}.failure_strategy, ${alias}.user_id, ${alias}.release_state,
${alias}.id, ${alias}.process_definition_id, ${alias}.start_time, ${alias}.end_time, ${alias}.timezone_id, ${alias}.crontab, ${alias}.failure_strategy, ${alias}.user_id, ${alias}.release_state,
${alias}.warning_type, ${alias}.warning_group_id, ${alias}.process_instance_priority, ${alias}.worker_group, ${alias}.create_time, ${alias}.update_time
</sql>
<select id="queryByProcessDefineIdPaging" resultType="org.apache.dolphinscheduler.dao.entity.Schedule">

View File

@ -539,6 +539,7 @@ MIT licenses
js-cookie 2.2.1: https://github.com/js-cookie/js-cookie MIT
jsplumb 2.8.6: https://github.com/jsplumb/jsplumb MIT and GPLv2
lodash 4.17.11: https://github.com/lodash/lodash MIT
moment-timezone 0.5.33: https://github.com/moment/moment-timezone MIT
vue-treeselect 0.4.0: https://github.com/riophae/vue-treeselect MIT
vue 2.5.17: https://github.com/vuejs/vue MIT
vue-router 2.7.0: https://github.com/vuejs/vue-router MIT

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -60,6 +60,7 @@ import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import org.apache.dolphinscheduler.common.utils.DateUtils;
import org.apache.dolphinscheduler.common.utils.JSONUtils;
import org.apache.dolphinscheduler.common.utils.PropertyUtils;
import org.apache.dolphinscheduler.common.utils.StringUtils;
@ -220,16 +221,18 @@ public class QuartzExecutors {
* add task trigger , if this task already exists, return this task with updated trigger
*
* @param clazz job class name
* @param jobName job name
* @param jobGroupName job group name
* @param startDate job start date
* @param endDate job end date
* @param cronExpression cron expression
* @param jobDataMap job parameters data map
* @param projectId projectId
* @param schedule schedule
*/
public void addJob(Class<? extends Job> clazz, String jobName, String jobGroupName, Date startDate, Date endDate,
String cronExpression,
Map<String, Object> jobDataMap) {
public void addJob(Class<? extends Job> clazz, int projectId, final Schedule schedule) {
String jobName = QuartzExecutors.buildJobName(schedule.getId());
String jobGroupName = QuartzExecutors.buildJobGroupName(projectId);
Date startDate = schedule.getStartTime();
Date endDate = schedule.getEndTime();
Map<String, Object> jobDataMap = QuartzExecutors.buildDataMap(projectId, schedule);
String cronExpression = schedule.getCrontab();
String timezoneId = schedule.getTimezoneId();
lock.writeLock().lock();
try {
@ -239,15 +242,11 @@ public class QuartzExecutors {
if (scheduler.checkExists(jobKey)) {
jobDetail = scheduler.getJobDetail(jobKey);
if (jobDataMap != null) {
jobDetail.getJobDataMap().putAll(jobDataMap);
}
jobDetail.getJobDataMap().putAll(jobDataMap);
} else {
jobDetail = newJob(clazz).withIdentity(jobKey).build();
if (jobDataMap != null) {
jobDetail.getJobDataMap().putAll(jobDataMap);
}
jobDetail.getJobDataMap().putAll(jobDataMap);
scheduler.addJob(jobDetail, false, true);
@ -263,8 +262,15 @@ public class QuartzExecutors {
* current time (taking into account any associated Calendar),
* but it does not want to be fired now.
*/
CronTrigger cronTrigger = newTrigger().withIdentity(triggerKey).startAt(startDate).endAt(endDate)
.withSchedule(cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing())
CronTrigger cronTrigger = newTrigger()
.withIdentity(triggerKey)
.startAt(DateUtils.getTimezoneDate(startDate, timezoneId))
.endAt(DateUtils.getTimezoneDate(endDate, timezoneId))
.withSchedule(
cronSchedule(cronExpression)
.withMisfireHandlingInstructionDoNothing()
.inTimeZone(DateUtils.getTimezone(timezoneId))
)
.forJob(jobDetail).build();
if (scheduler.checkExists(triggerKey)) {
@ -368,14 +374,13 @@ public class QuartzExecutors {
* add params to map
*
* @param projectId project id
* @param scheduleId schedule id
* @param schedule schedule
* @return data map
*/
public static Map<String, Object> buildDataMap(int projectId, int scheduleId, Schedule schedule) {
public static Map<String, Object> buildDataMap(int projectId, Schedule schedule) {
Map<String, Object> dataMap = new HashMap<>(8);
dataMap.put(PROJECT_ID, projectId);
dataMap.put(SCHEDULE_ID, scheduleId);
dataMap.put(SCHEDULE_ID, schedule.getId());
dataMap.put(SCHEDULE, JSONUtils.toJsonString(schedule));
return dataMap;

View File

@ -33,6 +33,7 @@
"js-cookie": "^2.2.1",
"jsplumb": "^2.8.6",
"lodash": "^4.17.11",
"moment-timezone": "^0.5.33",
"normalize.css": "^8.0.1",
"remixicon": "^2.5.0",
"vue": "^2.5.17",

View File

@ -61,6 +61,21 @@
</template>
</div>
</div>
<div class="clearfix list">
<div class="text">
{{$t('Timezone')}}
</div>
<div class="cont">
<el-select v-model=timezoneId filterable placeholder="Timezone">
<el-option
v-for="item in availableTimezoneIDList"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</div>
</div>
<div class="clearfix list">
<div style = "padding-left: 150px;">{{$t('Next five execution times')}}</div>
<ul style = "padding-left: 150px;">
@ -144,6 +159,7 @@
</div>
</template>
<script>
import moment from 'moment-timezone'
import i18n from '@/module/i18n'
import store from '@/conf/home/store'
import { warningTypeList } from './util'
@ -160,12 +176,14 @@
processDefinitionId: 0,
failureStrategy: 'CONTINUE',
warningTypeList: warningTypeList,
availableTimezoneIDList: moment.tz.names(),
warningType: 'NONE',
notifyGroupList: [],
warningGroupId: '',
spinnerLoading: false,
scheduleTime: '',
crontab: '0 0 * * * ? *',
timezoneId: moment.tz.guess(),
cronPopover: false,
i18n: i18n.globalScope.LOCALE,
processInstancePriority: 'MEDIUM',
@ -204,7 +222,8 @@
schedule: JSON.stringify({
startTime: this.scheduleTime[0],
endTime: this.scheduleTime[1],
crontab: this.crontab
crontab: this.crontab,
timezoneId: this.timezoneId
}),
failureStrategy: this.failureStrategy,
warningType: this.warningType,
@ -323,6 +342,7 @@
if (this.timingData.item.crontab) {
this.crontab = item.crontab
this.scheduleTime = [formatDate(item.startTime), formatDate(item.endTime)]
this.timezoneId = item.timezoneId === null ? moment.tz.guess() : item.timezoneId
this.failureStrategy = item.failureStrategy
this.warningType = item.warningType
this.processInstancePriority = item.processInstancePriority

View File

@ -399,6 +399,7 @@ export default {
'Import process': 'Import process',
'Timing state': 'Timing state',
Timing: 'Timing',
Timezone: 'Timezone',
TreeView: 'TreeView',
'Mailbox already exists! Recipients and copyers cannot repeat': 'Mailbox already exists! Recipients and copyers cannot repeat',
'Mailbox input is illegal': 'Mailbox input is illegal',

View File

@ -399,6 +399,7 @@ export default {
'Import process': '导入工作流',
'Timing state': '定时状态',
Timing: '定时',
Timezone: '时区',
TreeView: '树形图',
'Mailbox already exists! Recipients and copyers cannot repeat': '邮箱已存在收件人和抄送人不能重复',
'Mailbox input is illegal': '邮箱输入不合法',

View File

@ -750,6 +750,7 @@ CREATE TABLE `t_ds_schedules` (
`process_definition_id` int(11) NOT NULL COMMENT 'process definition id',
`start_time` datetime NOT NULL COMMENT 'start time',
`end_time` datetime NOT NULL COMMENT 'end time',
`timezone_id` varchar(40) DEFAULT NULL COMMENT 'timezoneId',
`crontab` varchar(256) NOT NULL COMMENT 'crontab description',
`failure_strategy` tinyint(4) NOT NULL COMMENT 'failure strategy. 0:end,1:continue',
`user_id` int(11) NOT NULL COMMENT 'user id',

View File

@ -614,6 +614,7 @@ CREATE TABLE t_ds_schedules (
process_definition_id int NOT NULL ,
start_time timestamp NOT NULL ,
end_time timestamp NOT NULL ,
timezone_id varchar(40) default NULL ,
crontab varchar(256) NOT NULL ,
failure_strategy int NOT NULL ,
user_id int NOT NULL ,

View File

@ -316,6 +316,26 @@ d//
delimiter ;
CALL uc_dolphin_T_t_ds_datasource_A_add_UN_datasourceName();
DROP PROCEDURE uc_dolphin_T_t_ds_datasource_A_add_UN_datasourceName;
-- uc_dolphin_T_t_ds_schedules_A_add_timezone
drop PROCEDURE if EXISTS uc_dolphin_T_t_ds_schedules_A_add_timezone;
delimiter d//
CREATE PROCEDURE uc_dolphin_T_t_ds_schedules_A_add_timezone()
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_NAME='t_ds_schedules'
AND TABLE_SCHEMA=(SELECT DATABASE())
AND COLUMN_NAME ='timezone_id')
THEN
ALTER TABLE t_ds_schedules ADD COLUMN `timezone_id` varchar(40) default NULL COMMENT 'schedule timezone id' AFTER `end_time`;
END IF;
END;
d//
delimiter ;
CALL uc_dolphin_T_t_ds_schedules_A_add_timezone();
DROP PROCEDURE uc_dolphin_T_t_ds_schedules_A_add_timezone;
-- ----------------------------
-- These columns will not be used in the new version,if you determine that the historical data is useless, you can delete it using the sql below
-- ----------------------------

View File

@ -304,6 +304,23 @@ delimiter ;
SELECT uc_dolphin_T_t_ds_datasource_A_add_UN_datasourceName();
DROP FUNCTION IF EXISTS uc_dolphin_T_t_ds_datasource_A_add_UN_datasourceName();
-- uc_dolphin_T_t_ds_schedules_A_add_timezone
delimiter d//
CREATE OR REPLACE FUNCTION uc_dolphin_T_t_ds_schedules_A_add_timezone() RETURNS void AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_NAME='t_ds_schedules'
AND COLUMN_NAME ='timezone_id')
THEN
ALTER TABLE t_ds_schedules ADD COLUMN timezone_id varchar(40) DEFAULT NULL;
END IF;
END;
$$ LANGUAGE plpgsql;
d//
delimiter ;
SELECT uc_dolphin_T_t_ds_schedules_A_add_timezone();
DROP FUNCTION IF EXISTS uc_dolphin_T_t_ds_schedules_A_add_timezone();
-- ----------------------------
-- These columns will not be used in the new version,if you determine that the historical data is useless, you can delete it using the sql below
-- ----------------------------