BoYiZhang
4 years ago
committed by
GitHub
31 changed files with 1201 additions and 468 deletions
@ -0,0 +1,47 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.utils; |
||||
|
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/** |
||||
* This is Regex expression utils. |
||||
*/ |
||||
public class RegexUtils { |
||||
|
||||
/** |
||||
* check number regex expression |
||||
*/ |
||||
private static final String CHECK_NUMBER = "^-?\\d+(\\.\\d+)?$"; |
||||
|
||||
private RegexUtils() { |
||||
} |
||||
|
||||
/** |
||||
* check if the input is number |
||||
* |
||||
* @param str input |
||||
* @return |
||||
*/ |
||||
public static boolean isNumeric(String str) { |
||||
Pattern pattern = Pattern.compile(CHECK_NUMBER); |
||||
Matcher isNum = pattern.matcher(str); |
||||
return isNum.matches(); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.utils; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
|
||||
/** |
||||
* RegexUtils test case |
||||
*/ |
||||
public class RegexUtilsTest { |
||||
|
||||
@Test |
||||
public void testIsNumeric() { |
||||
String num1 = "123467854678"; |
||||
boolean numeric = RegexUtils.isNumeric(num1); |
||||
Assert.assertTrue(numeric); |
||||
|
||||
String num2 = "0.0.01"; |
||||
boolean numeric2 = RegexUtils.isNumeric(num2); |
||||
Assert.assertFalse(numeric2); |
||||
} |
||||
|
||||
} |
@ -1 +1,105 @@
|
||||
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dolphinscheduler.remote.command;
public enum CommandType {
/**
* remove task log request,
*/
REMOVE_TAK_LOG_REQUEST,
/**
* remove task log response
*/
REMOVE_TAK_LOG_RESPONSE,
/**
* roll view log request
*/
ROLL_VIEW_LOG_REQUEST,
/**
* roll view log response
*/
ROLL_VIEW_LOG_RESPONSE,
/**
* view whole log request
*/
VIEW_WHOLE_LOG_REQUEST,
/**
* view whole log response
*/
VIEW_WHOLE_LOG_RESPONSE,
/**
* get log bytes request
*/
GET_LOG_BYTES_REQUEST,
/**
* get log bytes response
*/
GET_LOG_BYTES_RESPONSE,
WORKER_REQUEST,
MASTER_RESPONSE,
/**
* execute task request
*/
TASK_EXECUTE_REQUEST,
/**
* execute task ack
*/
TASK_EXECUTE_ACK,
/**
* execute task response
*/
TASK_EXECUTE_RESPONSE,
/**
* kill task
*/
TASK_KILL_REQUEST,
/**
* kill task response
*/
TASK_KILL_RESPONSE,
/**
* ping
*/
PING,
/**
* pong
*/
PONG;
} |
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.remote.command; |
||||
|
||||
public enum CommandType { |
||||
|
||||
/** |
||||
* remove task log request, |
||||
*/ |
||||
REMOVE_TAK_LOG_REQUEST, |
||||
|
||||
/** |
||||
* remove task log response |
||||
*/ |
||||
REMOVE_TAK_LOG_RESPONSE, |
||||
|
||||
/** |
||||
* roll view log request |
||||
*/ |
||||
ROLL_VIEW_LOG_REQUEST, |
||||
|
||||
/** |
||||
* roll view log response |
||||
*/ |
||||
ROLL_VIEW_LOG_RESPONSE, |
||||
|
||||
/** |
||||
* view whole log request |
||||
*/ |
||||
VIEW_WHOLE_LOG_REQUEST, |
||||
|
||||
/** |
||||
* view whole log response |
||||
*/ |
||||
VIEW_WHOLE_LOG_RESPONSE, |
||||
|
||||
/** |
||||
* get log bytes request |
||||
*/ |
||||
GET_LOG_BYTES_REQUEST, |
||||
|
||||
/** |
||||
* get log bytes response |
||||
*/ |
||||
GET_LOG_BYTES_RESPONSE, |
||||
|
||||
|
||||
WORKER_REQUEST, |
||||
MASTER_RESPONSE, |
||||
|
||||
/** |
||||
* execute task request |
||||
*/ |
||||
TASK_EXECUTE_REQUEST, |
||||
|
||||
/** |
||||
* execute task ack |
||||
*/ |
||||
TASK_EXECUTE_ACK, |
||||
|
||||
/** |
||||
* execute task response |
||||
*/ |
||||
TASK_EXECUTE_RESPONSE, |
||||
|
||||
/** |
||||
* kill task |
||||
*/ |
||||
TASK_KILL_REQUEST, |
||||
|
||||
/** |
||||
* kill task response |
||||
*/ |
||||
TASK_KILL_RESPONSE, |
||||
|
||||
/** |
||||
* HEART_BEAT |
||||
*/ |
||||
HEART_BEAT, |
||||
|
||||
/** |
||||
* ping |
||||
*/ |
||||
PING, |
||||
|
||||
/** |
||||
* pong |
||||
*/ |
||||
PONG; |
||||
} |
||||
|
@ -0,0 +1,116 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.service.process; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.CommandType; |
||||
import org.apache.dolphinscheduler.common.enums.WarningType; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Command; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstanceMap; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
|
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
||||
/** |
||||
* process service test |
||||
*/ |
||||
public class ProcessServiceTest { |
||||
|
||||
@Test |
||||
public void testCreateSubCommand() { |
||||
ProcessService processService = new ProcessService(); |
||||
ProcessInstance parentInstance = new ProcessInstance(); |
||||
parentInstance.setProcessDefinitionId(1); |
||||
parentInstance.setWarningType(WarningType.SUCCESS); |
||||
parentInstance.setWarningGroupId(0); |
||||
|
||||
TaskInstance task = new TaskInstance(); |
||||
task.setTaskJson("{\"params\":{\"processDefinitionId\":100}}"); |
||||
task.setId(10); |
||||
|
||||
ProcessInstance childInstance = null; |
||||
ProcessInstanceMap instanceMap = new ProcessInstanceMap(); |
||||
instanceMap.setParentProcessInstanceId(1); |
||||
instanceMap.setParentTaskInstanceId(10); |
||||
Command command = null; |
||||
|
||||
//father history: start; child null == command type: start
|
||||
parentInstance.setHistoryCmd("START_PROCESS"); |
||||
parentInstance.setCommandType(CommandType.START_PROCESS); |
||||
command = processService.createSubProcessCommand( |
||||
parentInstance, childInstance, instanceMap, task |
||||
); |
||||
Assert.assertEquals(CommandType.START_PROCESS, command.getCommandType()); |
||||
|
||||
//father history: start,start failure; child null == command type: start
|
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("START_PROCESS,START_FAILURE_TASK_PROCESS"); |
||||
command = processService.createSubProcessCommand( |
||||
parentInstance, childInstance, instanceMap, task |
||||
); |
||||
Assert.assertEquals(CommandType.START_PROCESS, command.getCommandType()); |
||||
|
||||
//father history: scheduler,start failure; child null == command type: scheduler
|
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("SCHEDULER,START_FAILURE_TASK_PROCESS"); |
||||
command = processService.createSubProcessCommand( |
||||
parentInstance, childInstance, instanceMap, task |
||||
); |
||||
Assert.assertEquals(CommandType.SCHEDULER, command.getCommandType()); |
||||
|
||||
//father history: complement,start failure; child null == command type: complement
|
||||
|
||||
String startString = "2020-01-01 00:00:00"; |
||||
String endString = "2020-01-10 00:00:00"; |
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("COMPLEMENT_DATA,START_FAILURE_TASK_PROCESS"); |
||||
Map<String,String> complementMap = new HashMap<>(); |
||||
complementMap.put(Constants.CMDPARAM_COMPLEMENT_DATA_START_DATE, startString); |
||||
complementMap.put(Constants.CMDPARAM_COMPLEMENT_DATA_END_DATE, endString); |
||||
parentInstance.setCommandParam(JSONUtils.toJsonString(complementMap)); |
||||
command = processService.createSubProcessCommand( |
||||
parentInstance, childInstance, instanceMap, task |
||||
); |
||||
Assert.assertEquals(CommandType.COMPLEMENT_DATA, command.getCommandType()); |
||||
|
||||
JsonNode complementDate = JSONUtils.parseObject(command.getCommandParam()); |
||||
Date start = DateUtils.stringToDate(complementDate.get(Constants.CMDPARAM_COMPLEMENT_DATA_START_DATE).asText()); |
||||
Date end = DateUtils.stringToDate(complementDate.get(Constants.CMDPARAM_COMPLEMENT_DATA_END_DATE).asText()); |
||||
Assert.assertEquals(startString, DateUtils.dateToString(start)); |
||||
Assert.assertEquals(endString, DateUtils.dateToString(end)); |
||||
|
||||
//father history: start,failure,start failure; child not null == command type: start failure
|
||||
childInstance = new ProcessInstance(); |
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("START_PROCESS,START_FAILURE_TASK_PROCESS"); |
||||
command = processService.createSubProcessCommand( |
||||
parentInstance, childInstance, instanceMap, task |
||||
); |
||||
Assert.assertEquals(CommandType.START_FAILURE_TASK_PROCESS, command.getCommandType()); |
||||
} |
||||
} |
@ -0,0 +1,218 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
<template> |
||||
<div class="timeout-alarm-model"> |
||||
<div class="clearfix list"> |
||||
<div class="text-box"> |
||||
<span>{{$t('Timeout alarm')}}</span> |
||||
</div> |
||||
<div class="cont-box"> |
||||
<label class="label-box"> |
||||
<div style="padding-top: 5px;"> |
||||
<x-switch v-model="enable" @on-click="_onSwitch(0, $event)" :disabled="isDetails"></x-switch> |
||||
</div> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
<div class="clearfix list" v-if="enable"> |
||||
<div class="text-box"> |
||||
<span>{{$t('Waiting Dependent start')}}</span> |
||||
</div> |
||||
<div class="cont-box"> |
||||
<label class="label-box"> |
||||
<div style="padding: 5px 0;"> |
||||
<x-switch v-model="waitStartTimeout.enable" @on-click="_onSwitch(1, $event)" :disabled="isDetails"></x-switch> |
||||
</div> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
<div class="clearfix list" v-if="enable && waitStartTimeout.enable"> |
||||
<div class="cont-box"> |
||||
<label class="label-box"> |
||||
<span class="text-box"> |
||||
<span>{{$t('Timeout period')}}</span> |
||||
</span> |
||||
<x-input v-model="waitStartTimeout.interval" style="width: 100px;" :disabled="isDetails" maxlength="9"> |
||||
<span slot="append">{{$t('Minute')}}</span> |
||||
</x-input> |
||||
<span class="text-box"> |
||||
<span>{{$t('Check interval')}}</span> |
||||
</span> |
||||
<x-input v-model="waitStartTimeout.checkInterval" style="width: 100px;" :disabled="isDetails" maxlength="9"> |
||||
<span slot="append">{{$t('Minute')}}</span> |
||||
</x-input> |
||||
<span class="text-box"> |
||||
<span>{{$t('Timeout strategy')}}</span> |
||||
</span> |
||||
<div style="padding-top: 6px;"> |
||||
<x-checkbox-group v-model="waitStartTimeout.strategy"> |
||||
<x-checkbox label="FAILED" :disabled="true">{{$t('Timeout failure')}}</x-checkbox> |
||||
</x-checkbox-group> |
||||
</div> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
<div class="clearfix list" v-if="enable"> |
||||
<div class="text-box"> |
||||
<span>{{$t('Waiting Dependent complete')}}</span> |
||||
</div> |
||||
<div class="cont-box"> |
||||
<label class="label-box"> |
||||
<div style="padding: 5px 0;"> |
||||
<x-switch v-model="waitCompleteTimeout.enable" @on-click="_onSwitch(2, $event)" :disabled="isDetails"></x-switch> |
||||
</div> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
<div class="clearfix list" v-if="enable && waitCompleteTimeout.enable"> |
||||
<div class="cont-box"> |
||||
<label class="label-box"> |
||||
<span class="text-box"> |
||||
<span>{{$t('Timeout period')}}</span> |
||||
</span> |
||||
<x-input v-model="waitCompleteTimeout.interval" style="width: 100px;" :disabled="isDetails" maxlength="9"> |
||||
<span slot="append">{{$t('Minute')}}</span> |
||||
</x-input> |
||||
<span class="text-box"> |
||||
<span>{{$t('Timeout strategy')}}</span> |
||||
</span> |
||||
<div style="padding-top: 6px;"> |
||||
<x-checkbox-group v-model="waitCompleteTimeout.strategy"> |
||||
<x-checkbox label="WARN" :disabled="isDetails">{{$t('Timeout alarm')}}</x-checkbox> |
||||
<x-checkbox label="FAILED" :disabled="isDetails">{{$t('Timeout failure')}}</x-checkbox> |
||||
</x-checkbox-group> |
||||
</div> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import _ from 'lodash' |
||||
import disabledState from '@/module/mixin/disabledState' |
||||
|
||||
export default { |
||||
name: 'form-dependent-timeout', |
||||
data () { |
||||
return { |
||||
// Timeout display hiding |
||||
enable: false, |
||||
waitStartTimeout: { |
||||
enable: false, |
||||
// Timeout strategy |
||||
strategy: ['FAILED'], |
||||
// Timeout period |
||||
interval: null, |
||||
checkInterval: null |
||||
}, |
||||
waitCompleteTimeout: { |
||||
enable: false, |
||||
// Timeout strategy |
||||
strategy: [], |
||||
// Timeout period |
||||
interval: null |
||||
} |
||||
} |
||||
}, |
||||
mixins: [disabledState], |
||||
props: { |
||||
backfillItem: Object |
||||
}, |
||||
methods: { |
||||
_onSwitch (p, is) { |
||||
// reset timeout setting when switch timeout on/off. |
||||
// p = 0 for timeout switch; p = 1 for wait start timeout switch; p = 2 for wait complete timeout switch. |
||||
if (p === 1 || p === 0) { |
||||
this.waitStartTimeout.interval = is ? 30 : null |
||||
this.waitStartTimeout.checkInterval = is ? 1 : null |
||||
} |
||||
if (p === 2 || p === 0) { |
||||
this.waitCompleteTimeout.strategy = is ? ['WARN'] : [] |
||||
this.waitCompleteTimeout.interval = is ? 30 : null |
||||
} |
||||
}, |
||||
_verification () { |
||||
// Verification timeout policy |
||||
if (this.enable |
||||
&& (this.waitCompleteTimeout.enable && !this.waitCompleteTimeout.strategy.length) |
||||
|| (this.waitStartTimeout.enable && !this.waitStartTimeout.strategy.length)) { |
||||
this.$message.warning(`${this.$t('Timeout strategy must be selected')}`) |
||||
return false |
||||
} |
||||
// Verify timeout duration Non 0 positive integer |
||||
const reg = /^[1-9]\d*$/ |
||||
if (this.enable |
||||
&& (this.waitCompleteTimeout.enable && !reg.test(this.waitCompleteTimeout.interval)) |
||||
|| (this.waitStartTimeout.enable && (!reg.test(this.waitStartTimeout.interval || !reg.test(this.waitStartTimeout.checkInterval))))) { |
||||
this.$message.warning(`${this.$t('Timeout must be a positive integer')}`) |
||||
return false |
||||
} |
||||
// Verify timeout duration longer than check interval |
||||
if (this.enable && this.waitStartTimeout.enable && this.waitStartTimeout.checkInterval >= this.waitStartTimeout.interval) { |
||||
this.$message.warning(`${this.$t('Timeout must be longer than check interval')}`) |
||||
return false |
||||
} |
||||
this.$emit('on-timeout', { |
||||
waitStartTimeout: { |
||||
strategy: 'FAILED', |
||||
interval: parseInt(this.waitStartTimeout.interval), |
||||
checkInterval: parseInt(this.waitStartTimeout.checkInterval), |
||||
enable: this.waitStartTimeout.enable |
||||
}, |
||||
waitCompleteTimeout: { |
||||
strategy: (() => { |
||||
// Handling checkout sequence |
||||
let strategy = this.waitCompleteTimeout.strategy |
||||
if (strategy.length === 2 && strategy[0] === 'FAILED') { |
||||
return [strategy[1], strategy[0]].join(',') |
||||
} else { |
||||
return strategy.join(',') |
||||
} |
||||
})(), |
||||
interval: parseInt(this.waitCompleteTimeout.interval), |
||||
enable: this.waitCompleteTimeout.enable |
||||
} |
||||
}) |
||||
return true |
||||
} |
||||
}, |
||||
watch: { |
||||
}, |
||||
created () { |
||||
let o = this.backfillItem |
||||
// Non-null objects represent backfill |
||||
if (!_.isEmpty(o)) { |
||||
if (o.timeout) { |
||||
this.enable = true |
||||
this.waitCompleteTimeout.enable = o.timeout.enable || false |
||||
this.waitCompleteTimeout.strategy = _.split(o.timeout.strategy, ',') || ['WARN'] |
||||
this.waitCompleteTimeout.interval = o.timeout.interval || null |
||||
} |
||||
if (o.waitStartTimeout) { |
||||
this.enable = true |
||||
this.waitStartTimeout.enable = o.waitStartTimeout.enable || false |
||||
this.waitStartTimeout.strategy = ['FAILED'] |
||||
this.waitStartTimeout.interval = o.waitStartTimeout.interval || null |
||||
this.waitStartTimeout.checkInterval = o.waitStartTimeout.checkInterval || null |
||||
} |
||||
} |
||||
}, |
||||
mounted () { |
||||
}, |
||||
components: {} |
||||
} |
||||
</script> |
Loading…
Reference in new issue