From a925f645719edec4afdb994ef57029c45c55d27e Mon Sep 17 00:00:00 2001 From: ruanwenjun <861923274@qq.com> Date: Mon, 17 May 2021 21:08:20 +0800 Subject: [PATCH] [Feature][api] schedule add timezone support #5259 (#5465) * [Feature][api] schedule add timezone support #5259 * import moment-timezone * fix code smell --- .../api/controller/SchedulerController.java | 3 +- .../api/dto/ScheduleParam.java | 112 ++-- .../service/impl/SchedulerServiceImpl.java | 17 +- .../common/utils/DateUtils.java | 30 + .../common/utils/DateUtilsTest.java | 13 + .../dolphinscheduler/dao/entity/Schedule.java | 567 +++++++++--------- .../dao/mapper/ScheduleMapper.xml | 4 +- dolphinscheduler-dist/release-docs/LICENSE | 1 + .../ui-licenses/LICENSE-moment-timezone | 20 + .../service/quartz/QuartzExecutors.java | 45 +- dolphinscheduler-ui/package.json | 1 + .../definition/pages/list/_source/timing.vue | 22 +- .../src/js/module/i18n/locale/en_US.js | 1 + .../src/js/module/i18n/locale/zh_CN.js | 1 + sql/dolphinscheduler_mysql.sql | 1 + sql/dolphinscheduler_postgre.sql | 1 + .../mysql/dolphinscheduler_ddl.sql | 20 + .../postgresql/dolphinscheduler_ddl.sql | 17 + 18 files changed, 510 insertions(+), 366 deletions(-) create mode 100644 dolphinscheduler-dist/release-docs/licenses/ui-licenses/LICENSE-moment-timezone diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java index 772fdceda3..20b668a641 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java @@ -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"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ScheduleParam.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ScheduleParam.java index a7cdfcfe46..6d957bfd27 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ScheduleParam.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ScheduleParam.java @@ -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; +package org.apache.dolphinscheduler.api.dto; 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() { - } - - public ScheduleParam(Date startTime, Date endTime, String crontab) { - this.startTime = startTime; - this.endTime = endTime; - this.crontab = crontab; - } - - public Date getStartTime() { - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - public Date getEndTime() { - return endTime; - } - - public void setEndTime(Date endTime) { - this.endTime = endTime; - } - - 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 + '\'' + - '}'; - } + + @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() { + } + + public ScheduleParam(Date startTime, Date endTime, String timezoneId, String crontab) { + this.startTime = startTime; + this.endTime = endTime; + this.timezoneId = timezoneId; + this.crontab = crontab; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public String getCrontab() { + return crontab; + } + + public void setCrontab(String crontab) { + this.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 + '\'' + + '}'; + } } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java index 5955a447e9..5f17e800bc 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java @@ -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 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); } /** diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java index c484dc0442..6ea527a3a0 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java @@ -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 + *

e.g. + *

if input date is 2020-01-01 00:00:00 current timezone is CST + *

targetTimezoneId is MST + *

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; diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java index 4a88085d19..38ab720c48 100644 --- a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java @@ -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")); + } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Schedule.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Schedule.java index 5d2bc3811e..74ed5c1ee1 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Schedule.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Schedule.java @@ -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; - - /** - * process definition name - */ - @TableField(exist = false) - private String processDefinitionName; - - /** - * project name - */ - @TableField(exist = false) - private String projectName; - - /** - * 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 end time - */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") - private Date endTime; - - /** - * crontab expression - */ - private String crontab; - - /** - * failure strategy - */ - private FailureStrategy failureStrategy; - - /** - * warning type - */ - private WarningType warningType; - - /** - * create time - */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") - private Date createTime; - - /** - * update time - */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") - private Date updateTime; - - /** - * created user id - */ - private int userId; - - /** - * created user name - */ - @TableField(exist = false) - private String userName; - - /** - * release state - */ - private ReleaseState releaseState; - - /** - * warning group id - */ - private int warningGroupId; - - - /** - * process instance priority - */ - private Priority processInstancePriority; - - /** - * worker group - */ - private String workerGroup; - - public int getWarningGroupId() { - return warningGroupId; - } - - public void setWarningGroupId(int warningGroupId) { - this.warningGroupId = warningGroupId; - } - - - - public Schedule() { - } - - public String getProjectName() { - return projectName; - } - - public void setProjectName(String projectName) { - this.projectName = projectName; - } - - - - public Date getStartTime() { - - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - public Date getEndTime() { - return endTime; - } - - public void setEndTime(Date endTime) { - this.endTime = endTime; - } - - public String getCrontab() { - return crontab; - } - - public void setCrontab(String crontab) { - this.crontab = crontab; - } - - public FailureStrategy getFailureStrategy() { - return failureStrategy; - } - - public void setFailureStrategy(FailureStrategy failureStrategy) { - this.failureStrategy = failureStrategy; - } - - public WarningType getWarningType() { - return warningType; - } - - public void setWarningType(WarningType warningType) { - this.warningType = warningType; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - - public ReleaseState getReleaseState() { - return releaseState; - } - - public void setReleaseState(ReleaseState releaseState) { - this.releaseState = releaseState; - } - - - - public int getProcessDefinitionId() { - return processDefinitionId; - } - - public void setProcessDefinitionId(int processDefinitionId) { - this.processDefinitionId = processDefinitionId; - } - - public String getProcessDefinitionName() { - return processDefinitionName; - } - - public void setProcessDefinitionName(String processDefinitionName) { - this.processDefinitionName = processDefinitionName; - } - - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - 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; - } + @TableId(value = "id", type = IdType.AUTO) + private int id; + /** + * process definition id + */ + private int processDefinitionId; + + /** + * process definition name + */ + @TableField(exist = false) + private String processDefinitionName; + + /** + * project name + */ + @TableField(exist = false) + private String projectName; + + /** + * 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 end time + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date endTime; + + /** + * timezoneId + *

see {@link java.util.TimeZone#getTimeZone(String)} + */ + private String timezoneId; + + /** + * crontab expression + */ + private String crontab; + + /** + * failure strategy + */ + private FailureStrategy failureStrategy; + + /** + * warning type + */ + private WarningType warningType; + + /** + * create time + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * update time + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + + /** + * created user id + */ + private int userId; + + /** + * created user name + */ + @TableField(exist = false) + private String userName; + + /** + * release state + */ + private ReleaseState releaseState; + + /** + * warning group id + */ + private int warningGroupId; + + + /** + * process instance priority + */ + private Priority processInstancePriority; + + /** + * worker group + */ + private String workerGroup; + + public int getWarningGroupId() { + return warningGroupId; + } + + public void setWarningGroupId(int warningGroupId) { + this.warningGroupId = warningGroupId; + } + + public Schedule() { + } + + public String getProjectName() { + return projectName; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public String getTimezoneId() { + return timezoneId; + } + + public void setTimezoneId(String timezoneId) { + this.timezoneId = timezoneId; + } + + public String getCrontab() { + return crontab; + } + + public void setCrontab(String crontab) { + this.crontab = crontab; + } + + public FailureStrategy getFailureStrategy() { + return failureStrategy; + } + + public void setFailureStrategy(FailureStrategy failureStrategy) { + this.failureStrategy = failureStrategy; + } + + public WarningType getWarningType() { + return warningType; + } + + public void setWarningType(WarningType warningType) { + this.warningType = warningType; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public ReleaseState getReleaseState() { + return releaseState; + } + + public void setReleaseState(ReleaseState releaseState) { + this.releaseState = releaseState; + } + + public int getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(int processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public String getProcessDefinitionName() { + return processDefinitionName; + } + + public void setProcessDefinitionName(String processDefinitionName) { + this.processDefinitionName = processDefinitionName; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + 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 + + ", 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 String getDefinitionDescription() { + return definitionDescription; + } + + public void setDefinitionDescription(String definitionDescription) { + this.definitionDescription = definitionDescription; + } } diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ScheduleMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ScheduleMapper.xml index ae95655d5e..587680f0b5 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ScheduleMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ScheduleMapper.xml @@ -19,11 +19,11 @@ - 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 - ${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