Browse Source
* [Improvement][dao]When I search for the keyword description, the web UI shows empty (#5952) * [Bug][WorkerServer] SqlTask NullPointerException #5549 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword description, the web UI shows empty #5428 * fix the readme typing issue (#5998) * Fix unchecked type conversions * Use indentation level reported by checkstyle * Reorganize CI workflows to fasten the wasted time and resources (#6011) * Add standalone server module to make it easier to develop (#6022) * Task node of SWITCH (#5939) * [Feature-#5273][server-master] Task node of SWITCH (#5922) Co-authored-by: wangxj <wangxj31> * remove description of bonecp (#6030) Co-authored-by: shaojwu <shaojwu@ebay.com> * [Improvement][Api Module]split alert group list-paging interface (#5941) * [Improvement][Api Module]split alert group list-paging interface * [FIX-#6007]Wrong complement date (#6026) * [FIX-#6007]Wrong complement date * [style]Wrong complement date * [Improvement-6024][dist] Remove useless packaging commands (#6029) ·Remove useless packaging commands in dolphinscheduler-bin.xml This closes #6024 Co-authored-by: mask <liuhu@zhiyoutec.com> * [FIX-5908][MasterServer] When executing an compensation task, the execution thread would have a NPE (#5909) * fix the npe in MasterExec * fix the compile error * Add `.asf.yaml` to easily set the GitHub metadata (#6035) * fix dead server cannot stop (#6046) * Enhancement Translation (#6042) * replaced Loading... with i18n * modified Edit zh_CN translation * Delete zh_CN.js Co-authored-by: David <dailidong66@gmail.com> * fix bug #6053 zh_CN.js is lost * [Fix-6038][ui] width of "SQL Statement" in Dag FormLineModal will be shrunk if sql line is too long (#6040) This closes #6038 * [Improvement] Fix inefficient map iterator (#6004) * Fix inefficient map iterator * Use forEach and remove call to valueOf * Modify AbstractParameters * Enhance `StandaloneServer` so that we don't need to update the version number manually (#6074) * Remove invalid character in `.asf.yaml` (#6075) * Remove invalid character `\n` in `.asf.yaml` (#6077) It turns out that the invalid character is `\n` * Add alert server into standalone-server as well and some minor polish (#6087) * Support starting standalone server in Docker image (#6102) Also remove unused class * [Feature-4355][Master-Worker-API] improvements of master and scheduler module (#6095) * [Feature-4355][Master-Worker-API] improvements of master and scheduler module (#6085) * master refactor: 1. spi for task submit and other actions(pause, kill) 2. remove threads for process instance and task instance. 3. add events for process instance and task instance * ut npe * add try catch * code style * fix critical bugs * fix critical bugs * fix critical bugs * fix critical bugs * Remove unused params in SwitchTaskTest (#6109) * [Feature-5987][Server] Support to set multiple environment configs for a certain worker. (#6082) * support multi environments * add some test cases * add an environment vue component * improve environment form * improve environment form * add environment worker group relation * add environment worker group relation * add the environment choice for formModel * set an environment for the task * modify the modal form of starting process * add the environment config to TaskExecutionContext * add the environment config to the timing form * fix conflicts * fix issues of the code style * fix some issues of the code style * fix some issues of the code style * fix some issues of the code style * fix some issues of the code style * fix some issues of the code style * fix some bugs in the code review * add the same table and columns to support H2 * fix some bugs * [Plugin][Task]Task Spi * [Plugin][Task]Task Spi * [Plugin][Task]Task Spi * [Plugin][Task]Task Spi * [Plugin][Task]Task Spi * [Plugin][Task]Task Spi Co-authored-by: didiaode18 <563646039@qq.com> Co-authored-by: Roy <yongjuncao1213@gmail.com> Co-authored-by: lyxell <alyxell@kth.se> Co-authored-by: Wenjun Ruan <wenjun@apache.org> Co-authored-by: kezhenxu94 <kezhenxu94@apache.org> Co-authored-by: myangle1120 <942542838@qq.com> Co-authored-by: wangxj3 <857234426@qq.com> Co-authored-by: gabry.wu <gabrywu@apache.org> Co-authored-by: shaojwu <shaojwu@ebay.com> Co-authored-by: Shukun Zhang <60541766+andream7@users.noreply.github.com> Co-authored-by: linquan <1175687813@qq.com> Co-authored-by: mask <39329477+Narcasserun@users.noreply.github.com> Co-authored-by: mask <liuhu@zhiyoutec.com> Co-authored-by: kyoty <echohlne@gmail.com> Co-authored-by: RichardStark <49977764+RichardStark@users.noreply.github.com> Co-authored-by: David <dailidong66@gmail.com> Co-authored-by: lenboo <baoliang.leon@gmail.com> Co-authored-by: lilyzhou <lj_zhou@outlook.com> Co-authored-by: OS <29528966+lenboo@users.noreply.github.com> Co-authored-by: junfan.zhang <zuston.shacha@gmail.com> Co-authored-by: Hua Jiang <jianghuachinacom@163.com>2.0.7-release
Kirs
3 years ago
committed by
GitHub
169 changed files with 8494 additions and 2194 deletions
@ -1,60 +0,0 @@
|
||||
/* |
||||
* 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.alert.utils; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNull; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
import org.junit.Test; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class FuncUtilsTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FuncUtilsTest.class); |
||||
|
||||
/** |
||||
* Test mkString |
||||
*/ |
||||
@Test |
||||
public void testMKString() { |
||||
|
||||
//Define users list
|
||||
Iterable<String> users = Arrays.asList("user1", "user2", "user3"); |
||||
//Define split
|
||||
String split = "|"; |
||||
|
||||
//Invoke mkString with correctParams
|
||||
String result = FuncUtils.mkString(users, split); |
||||
logger.info(result); |
||||
|
||||
//Expected result string
|
||||
assertEquals("user1|user2|user3", result); |
||||
|
||||
//Null list expected return null
|
||||
result = FuncUtils.mkString(null, split); |
||||
assertNull(result); |
||||
|
||||
//Null split expected return null
|
||||
result = FuncUtils.mkString(users, null); |
||||
assertNull(result); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,240 @@
|
||||
/* |
||||
* 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.controller; |
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ENVIRONMENT_ERROR; |
||||
import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ENVIRONMENT_ERROR; |
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ENVIRONMENT_BY_CODE_ERROR; |
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ENVIRONMENT_ERROR; |
||||
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ENVIRONMENT_ERROR; |
||||
import static org.apache.dolphinscheduler.api.enums.Status.VERIFY_ENVIRONMENT_ERROR; |
||||
|
||||
import org.apache.dolphinscheduler.api.aspect.AccessLogAnnotation; |
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException; |
||||
import org.apache.dolphinscheduler.api.service.EnvironmentService; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestAttribute; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiImplicitParam; |
||||
import io.swagger.annotations.ApiImplicitParams; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import springfox.documentation.annotations.ApiIgnore; |
||||
|
||||
/** |
||||
* environment controller |
||||
*/ |
||||
@Api(tags = "ENVIRONMENT_TAG") |
||||
@RestController |
||||
@RequestMapping("environment") |
||||
public class EnvironmentController extends BaseController { |
||||
|
||||
@Autowired |
||||
private EnvironmentService environmentService; |
||||
|
||||
/** |
||||
* create environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param name environment name |
||||
* @param config config |
||||
* @param description description |
||||
* @return returns an error if it exists |
||||
*/ |
||||
@ApiOperation(value = "createEnvironment", notes = "CREATE_ENVIRONMENT_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "name", value = "ENVIRONMENT_NAME", required = true, dataType = "String"), |
||||
@ApiImplicitParam(name = "config", value = "CONFIG", required = true, dataType = "String"), |
||||
@ApiImplicitParam(name = "description", value = "ENVIRONMENT_DESC", dataType = "String"), |
||||
@ApiImplicitParam(name = "workerGroups", value = "WORKER_GROUP_LIST", dataType = "String") |
||||
}) |
||||
@PostMapping(value = "/create") |
||||
@ResponseStatus(HttpStatus.CREATED) |
||||
@ApiException(CREATE_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result createProject(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam("name") String name, |
||||
@RequestParam("config") String config, |
||||
@RequestParam(value = "description", required = false) String description, |
||||
@RequestParam(value = "workerGroups", required = false) String workerGroups) { |
||||
|
||||
Map<String, Object> result = environmentService.createEnvironment(loginUser, name, config, description, workerGroups); |
||||
return returnDataList(result); |
||||
} |
||||
|
||||
/** |
||||
* update environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param code environment code |
||||
* @param name environment name |
||||
* @param config environment config |
||||
* @param description description |
||||
* @return update result code |
||||
*/ |
||||
@ApiOperation(value = "updateEnvironment", notes = "UPDATE_ENVIRONMENT_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "code", value = "ENVIRONMENT_CODE", required = true, dataType = "Long", example = "100"), |
||||
@ApiImplicitParam(name = "name", value = "ENVIRONMENT_NAME", required = true, dataType = "String"), |
||||
@ApiImplicitParam(name = "config", value = "ENVIRONMENT_CONFIG", required = true, dataType = "String"), |
||||
@ApiImplicitParam(name = "description", value = "ENVIRONMENT_DESC", dataType = "String"), |
||||
@ApiImplicitParam(name = "workerGroups", value = "WORKER_GROUP_LIST", dataType = "String") |
||||
}) |
||||
@PostMapping(value = "/update") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(UPDATE_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result updateEnvironment(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam("code") Long code, |
||||
@RequestParam("name") String name, |
||||
@RequestParam("config") String config, |
||||
@RequestParam(value = "description", required = false) String description, |
||||
@RequestParam(value = "workerGroups", required = false) String workerGroups) { |
||||
Map<String, Object> result = environmentService.updateEnvironmentByCode(loginUser, code, name, config, description, workerGroups); |
||||
return returnDataList(result); |
||||
} |
||||
|
||||
/** |
||||
* query environment details by code |
||||
* |
||||
* @param environmentCode environment code |
||||
* @return environment detail information |
||||
*/ |
||||
@ApiOperation(value = "queryEnvironmentByCode", notes = "QUERY_ENVIRONMENT_BY_CODE_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "environmentCode", value = "ENVIRONMENT_CODE", required = true, dataType = "Long", example = "100") |
||||
}) |
||||
@GetMapping(value = "/query-by-code") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(QUERY_ENVIRONMENT_BY_CODE_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result queryEnvironmentByCode(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam("environmentCode") Long environmentCode) { |
||||
|
||||
Map<String, Object> result = environmentService.queryEnvironmentByCode(environmentCode); |
||||
return returnDataList(result); |
||||
} |
||||
|
||||
/** |
||||
* query environment list paging |
||||
* |
||||
* @param searchVal search value |
||||
* @param pageSize page size |
||||
* @param pageNo page number |
||||
* @return environment list which the login user have permission to see |
||||
*/ |
||||
@ApiOperation(value = "queryEnvironmentListPaging", notes = "QUERY_ENVIRONMENT_LIST_PAGING_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", dataType = "String"), |
||||
@ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "20"), |
||||
@ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "1") |
||||
}) |
||||
@GetMapping(value = "/list-paging") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(QUERY_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result queryEnvironmentListPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam(value = "searchVal", required = false) String searchVal, |
||||
@RequestParam("pageSize") Integer pageSize, |
||||
@RequestParam("pageNo") Integer pageNo |
||||
) { |
||||
|
||||
Result result = checkPageParams(pageNo, pageSize); |
||||
if (!result.checkResult()) { |
||||
return result; |
||||
} |
||||
searchVal = ParameterUtils.handleEscapes(searchVal); |
||||
result = environmentService.queryEnvironmentListPaging(pageNo, pageSize, searchVal); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* delete environment by code |
||||
* |
||||
* @param loginUser login user |
||||
* @param environmentCode environment code |
||||
* @return delete result code |
||||
*/ |
||||
@ApiOperation(value = "deleteEnvironmentByCode", notes = "DELETE_ENVIRONMENT_BY_CODE_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "environmentCode", value = "ENVIRONMENT_CODE", required = true, dataType = "Long", example = "100") |
||||
}) |
||||
@PostMapping(value = "/delete") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(DELETE_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result deleteEnvironment(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam("environmentCode") Long environmentCode |
||||
) { |
||||
|
||||
Map<String, Object> result = environmentService.deleteEnvironmentByCode(loginUser, environmentCode); |
||||
return returnDataList(result); |
||||
} |
||||
|
||||
/** |
||||
* query all environment list |
||||
* |
||||
* @param loginUser login user |
||||
* @return all environment list |
||||
*/ |
||||
@ApiOperation(value = "queryAllEnvironmentList", notes = "QUERY_ALL_ENVIRONMENT_LIST_NOTES") |
||||
@GetMapping(value = "/query-environment-list") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(QUERY_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result queryAllEnvironmentList(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { |
||||
Map<String, Object> result = environmentService.queryAllEnvironmentList(); |
||||
return returnDataList(result); |
||||
} |
||||
|
||||
/** |
||||
* verify environment and environment name |
||||
* |
||||
* @param loginUser login user |
||||
* @param environmentName environment name |
||||
* @return true if the environment name not exists, otherwise return false |
||||
*/ |
||||
@ApiOperation(value = "verifyEnvironment", notes = "VERIFY_ENVIRONMENT_NOTES") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "environmentName", value = "ENVIRONMENT_NAME", required = true, dataType = "String") |
||||
}) |
||||
@PostMapping(value = "/verify-environment") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(VERIFY_ENVIRONMENT_ERROR) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result verifyEnvironment(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam(value = "environmentName") String environmentName |
||||
) { |
||||
Map<String, Object> result = environmentService.verifyEnvironment(environmentName); |
||||
return returnDataList(result); |
||||
} |
||||
} |
@ -0,0 +1,129 @@
|
||||
/* |
||||
* 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.dto; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* EnvironmentDto |
||||
*/ |
||||
public class EnvironmentDto { |
||||
|
||||
private int id; |
||||
|
||||
/** |
||||
* environment code |
||||
*/ |
||||
private Long code; |
||||
|
||||
/** |
||||
* environment name |
||||
*/ |
||||
private String name; |
||||
|
||||
/** |
||||
* config content |
||||
*/ |
||||
private String config; |
||||
|
||||
private String description; |
||||
|
||||
private List<String> workerGroups; |
||||
|
||||
/** |
||||
* operator user id |
||||
*/ |
||||
private Integer operator; |
||||
|
||||
private Date createTime; |
||||
|
||||
private Date updateTime; |
||||
|
||||
public int getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(int id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public Long getCode() { |
||||
return this.code; |
||||
} |
||||
|
||||
public void setCode(Long code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getConfig() { |
||||
return this.config; |
||||
} |
||||
|
||||
public void setConfig(String config) { |
||||
this.config = config; |
||||
} |
||||
|
||||
public String getDescription() { |
||||
return this.description; |
||||
} |
||||
|
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
public Integer getOperator() { |
||||
return this.operator; |
||||
} |
||||
|
||||
public void setOperator(Integer operator) { |
||||
this.operator = operator; |
||||
} |
||||
|
||||
public Date getCreateTime() { |
||||
return createTime; |
||||
} |
||||
|
||||
public void setCreateTime(Date createTime) { |
||||
this.createTime = createTime; |
||||
} |
||||
|
||||
public Date getUpdateTime() { |
||||
return updateTime; |
||||
} |
||||
|
||||
public void setUpdateTime(Date updateTime) { |
||||
this.updateTime = updateTime; |
||||
} |
||||
|
||||
public List<String> getWorkerGroups() { |
||||
return workerGroups; |
||||
} |
||||
|
||||
public void setWorkerGroups(List<String> workerGroups) { |
||||
this.workerGroups = workerGroups; |
||||
} |
||||
} |
@ -0,0 +1,102 @@
|
||||
/* |
||||
* 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.service; |
||||
|
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* environment service |
||||
*/ |
||||
public interface EnvironmentService { |
||||
|
||||
/** |
||||
* create environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param name environment name |
||||
* @param config environment config |
||||
* @param desc environment desc |
||||
* @param workerGroups worker groups |
||||
*/ |
||||
Map<String, Object> createEnvironment(User loginUser, String name, String config, String desc, String workerGroups); |
||||
|
||||
/** |
||||
* query environment |
||||
* |
||||
* @param name environment name |
||||
*/ |
||||
Map<String, Object> queryEnvironmentByName(String name); |
||||
|
||||
/** |
||||
* query environment |
||||
* |
||||
* @param code environment code |
||||
*/ |
||||
Map<String, Object> queryEnvironmentByCode(Long code); |
||||
|
||||
|
||||
/** |
||||
* delete environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param code environment code |
||||
*/ |
||||
Map<String, Object> deleteEnvironmentByCode(User loginUser, Long code); |
||||
|
||||
/** |
||||
* update environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param code environment code |
||||
* @param name environment name |
||||
* @param config environment config |
||||
* @param desc environment desc |
||||
* @param workerGroups worker groups |
||||
*/ |
||||
Map<String, Object> updateEnvironmentByCode(User loginUser, Long code, String name, String config, String desc, String workerGroups); |
||||
|
||||
/** |
||||
* query environment paging |
||||
* |
||||
* @param pageNo page number |
||||
* @param searchVal search value |
||||
* @param pageSize page size |
||||
* @return environment list page |
||||
*/ |
||||
Result queryEnvironmentListPaging(Integer pageNo, Integer pageSize, String searchVal); |
||||
|
||||
/** |
||||
* query all environment |
||||
* |
||||
* @return all environment list |
||||
*/ |
||||
Map<String, Object> queryAllEnvironmentList(); |
||||
|
||||
/** |
||||
* verify environment name |
||||
* |
||||
* @param environmentName environment name |
||||
* @return true if the environment name not exists, otherwise return false |
||||
*/ |
||||
Map<String, Object> verifyEnvironment(String environmentName); |
||||
|
||||
} |
||||
|
@ -0,0 +1,41 @@
|
||||
/* |
||||
* 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.service; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* environment worker group relation service |
||||
*/ |
||||
public interface EnvironmentWorkerGroupRelationService { |
||||
|
||||
/** |
||||
* query environment worker group relation |
||||
* |
||||
* @param environmentCode environment code |
||||
*/ |
||||
Map<String, Object> queryEnvironmentWorkerGroupRelation(Long environmentCode); |
||||
|
||||
/** |
||||
* query all environment worker group relation |
||||
* |
||||
* @return all relation list |
||||
*/ |
||||
Map<String, Object> queryAllEnvironmentWorkerGroupRelationList(); |
||||
} |
||||
|
@ -0,0 +1,463 @@
|
||||
/* |
||||
* 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.service.impl; |
||||
|
||||
import org.apache.dolphinscheduler.api.dto.EnvironmentDto; |
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.EnvironmentService; |
||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.SnowFlakeUtils; |
||||
import org.apache.dolphinscheduler.common.utils.SnowFlakeUtils.SnowFlakeException; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Environment; |
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentWorkerGroupRelationMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionMapper; |
||||
|
||||
import org.apache.commons.collections4.SetUtils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
import java.util.Set; |
||||
import java.util.TreeSet; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
||||
/** |
||||
* task definition service impl |
||||
*/ |
||||
@Service |
||||
public class EnvironmentServiceImpl extends BaseServiceImpl implements EnvironmentService { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EnvironmentServiceImpl.class); |
||||
|
||||
@Autowired |
||||
private EnvironmentMapper environmentMapper; |
||||
|
||||
@Autowired |
||||
private EnvironmentWorkerGroupRelationMapper relationMapper; |
||||
|
||||
@Autowired |
||||
private TaskDefinitionMapper taskDefinitionMapper; |
||||
|
||||
/** |
||||
* create environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param name environment name |
||||
* @param config environment config |
||||
* @param desc environment desc |
||||
* @param workerGroups worker groups |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
@Override |
||||
public Map<String, Object> createEnvironment(User loginUser, String name, String config, String desc, String workerGroups) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
if (isNotAdmin(loginUser, result)) { |
||||
return result; |
||||
} |
||||
|
||||
Map<String, Object> checkResult = checkParams(name,config,workerGroups); |
||||
if (checkResult.get(Constants.STATUS) != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
Environment environment = environmentMapper.queryByEnvironmentName(name); |
||||
if (environment != null) { |
||||
putMsg(result, Status.ENVIRONMENT_NAME_EXISTS, name); |
||||
return result; |
||||
} |
||||
|
||||
Environment env = new Environment(); |
||||
env.setName(name); |
||||
env.setConfig(config); |
||||
env.setDescription(desc); |
||||
env.setOperator(loginUser.getId()); |
||||
env.setCreateTime(new Date()); |
||||
env.setUpdateTime(new Date()); |
||||
long code = 0L; |
||||
try { |
||||
code = SnowFlakeUtils.getInstance().nextId(); |
||||
env.setCode(code); |
||||
} catch (SnowFlakeException e) { |
||||
logger.error("Environment code get error, ", e); |
||||
} |
||||
if (code == 0L) { |
||||
putMsg(result, Status.INTERNAL_SERVER_ERROR_ARGS, "Error generating environment code"); |
||||
return result; |
||||
} |
||||
|
||||
if (environmentMapper.insert(env) > 0) { |
||||
if (StringUtils.isNotEmpty(workerGroups)) { |
||||
List<String> workerGroupList = JSONUtils.parseObject(workerGroups, new TypeReference<List<String>>(){}); |
||||
if (CollectionUtils.isNotEmpty(workerGroupList)) { |
||||
workerGroupList.stream().forEach(workerGroup -> { |
||||
if (StringUtils.isNotEmpty(workerGroup)) { |
||||
EnvironmentWorkerGroupRelation relation = new EnvironmentWorkerGroupRelation(); |
||||
relation.setEnvironmentCode(env.getCode()); |
||||
relation.setWorkerGroup(workerGroup); |
||||
relation.setOperator(loginUser.getId()); |
||||
relation.setCreateTime(new Date()); |
||||
relation.setUpdateTime(new Date()); |
||||
relationMapper.insert(relation); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
result.put(Constants.DATA_LIST, env.getCode()); |
||||
putMsg(result, Status.SUCCESS); |
||||
} else { |
||||
putMsg(result, Status.CREATE_ENVIRONMENT_ERROR); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query environment paging |
||||
* |
||||
* @param pageNo page number |
||||
* @param searchVal search value |
||||
* @param pageSize page size |
||||
* @return environment list page |
||||
*/ |
||||
@Override |
||||
public Result queryEnvironmentListPaging(Integer pageNo, Integer pageSize, String searchVal) { |
||||
Result result = new Result(); |
||||
|
||||
Page<Environment> page = new Page<>(pageNo, pageSize); |
||||
|
||||
IPage<Environment> environmentIPage = environmentMapper.queryEnvironmentListPaging(page, searchVal); |
||||
|
||||
PageInfo<EnvironmentDto> pageInfo = new PageInfo<>(pageNo, pageSize); |
||||
pageInfo.setTotal((int) environmentIPage.getTotal()); |
||||
|
||||
if (CollectionUtils.isNotEmpty(environmentIPage.getRecords())) { |
||||
Map<Long, List<String>> relationMap = relationMapper.selectList(null).stream() |
||||
.collect(Collectors.groupingBy(EnvironmentWorkerGroupRelation::getEnvironmentCode,Collectors.mapping(EnvironmentWorkerGroupRelation::getWorkerGroup,Collectors.toList()))); |
||||
|
||||
List<EnvironmentDto> dtoList = environmentIPage.getRecords().stream().map(environment -> { |
||||
EnvironmentDto dto = new EnvironmentDto(); |
||||
BeanUtils.copyProperties(environment,dto); |
||||
List<String> workerGroups = relationMap.getOrDefault(environment.getCode(),new ArrayList<String>()); |
||||
dto.setWorkerGroups(workerGroups); |
||||
return dto; |
||||
}).collect(Collectors.toList()); |
||||
|
||||
pageInfo.setTotalList(dtoList); |
||||
} else { |
||||
pageInfo.setTotalList(new ArrayList<>()); |
||||
} |
||||
|
||||
result.setData(pageInfo); |
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query all environment |
||||
* |
||||
* @return all environment list |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> queryAllEnvironmentList() { |
||||
Map<String,Object> result = new HashMap<>(); |
||||
List<Environment> environmentList = environmentMapper.queryAllEnvironmentList(); |
||||
|
||||
if (CollectionUtils.isNotEmpty(environmentList)) { |
||||
Map<Long, List<String>> relationMap = relationMapper.selectList(null).stream() |
||||
.collect(Collectors.groupingBy(EnvironmentWorkerGroupRelation::getEnvironmentCode,Collectors.mapping(EnvironmentWorkerGroupRelation::getWorkerGroup,Collectors.toList()))); |
||||
|
||||
List<EnvironmentDto> dtoList = environmentList.stream().map(environment -> { |
||||
EnvironmentDto dto = new EnvironmentDto(); |
||||
BeanUtils.copyProperties(environment,dto); |
||||
List<String> workerGroups = relationMap.getOrDefault(environment.getCode(),new ArrayList<String>()); |
||||
dto.setWorkerGroups(workerGroups); |
||||
return dto; |
||||
}).collect(Collectors.toList()); |
||||
result.put(Constants.DATA_LIST,dtoList); |
||||
} else { |
||||
result.put(Constants.DATA_LIST, new ArrayList<>()); |
||||
} |
||||
|
||||
putMsg(result,Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query environment |
||||
* |
||||
* @param code environment code |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> queryEnvironmentByCode(Long code) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
Environment env = environmentMapper.queryByEnvironmentCode(code); |
||||
|
||||
if (env == null) { |
||||
putMsg(result, Status.QUERY_ENVIRONMENT_BY_CODE_ERROR, code); |
||||
} else { |
||||
List<String> workerGroups = relationMapper.queryByEnvironmentCode(env.getCode()).stream() |
||||
.map(item -> item.getWorkerGroup()) |
||||
.collect(Collectors.toList()); |
||||
|
||||
EnvironmentDto dto = new EnvironmentDto(); |
||||
BeanUtils.copyProperties(env,dto); |
||||
dto.setWorkerGroups(workerGroups); |
||||
result.put(Constants.DATA_LIST, dto); |
||||
putMsg(result, Status.SUCCESS); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query environment |
||||
* |
||||
* @param name environment name |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> queryEnvironmentByName(String name) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
Environment env = environmentMapper.queryByEnvironmentName(name); |
||||
if (env == null) { |
||||
putMsg(result, Status.QUERY_ENVIRONMENT_BY_NAME_ERROR, name); |
||||
} else { |
||||
List<String> workerGroups = relationMapper.queryByEnvironmentCode(env.getCode()).stream() |
||||
.map(item -> item.getWorkerGroup()) |
||||
.collect(Collectors.toList()); |
||||
|
||||
EnvironmentDto dto = new EnvironmentDto(); |
||||
BeanUtils.copyProperties(env,dto); |
||||
dto.setWorkerGroups(workerGroups); |
||||
result.put(Constants.DATA_LIST, dto); |
||||
putMsg(result, Status.SUCCESS); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* delete environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param code environment code |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
@Override |
||||
public Map<String, Object> deleteEnvironmentByCode(User loginUser, Long code) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
if (isNotAdmin(loginUser, result)) { |
||||
return result; |
||||
} |
||||
|
||||
Integer relatedTaskNumber = taskDefinitionMapper |
||||
.selectCount(new QueryWrapper<TaskDefinition>().lambda().eq(TaskDefinition::getEnvironmentCode,code)); |
||||
|
||||
if (relatedTaskNumber > 0) { |
||||
putMsg(result, Status.DELETE_ENVIRONMENT_RELATED_TASK_EXISTS); |
||||
return result; |
||||
} |
||||
|
||||
int delete = environmentMapper.deleteByCode(code); |
||||
if (delete > 0) { |
||||
relationMapper.delete(new QueryWrapper<EnvironmentWorkerGroupRelation>() |
||||
.lambda() |
||||
.eq(EnvironmentWorkerGroupRelation::getEnvironmentCode,code)); |
||||
putMsg(result, Status.SUCCESS); |
||||
} else { |
||||
putMsg(result, Status.DELETE_ENVIRONMENT_ERROR); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* update environment |
||||
* |
||||
* @param loginUser login user |
||||
* @param code environment code |
||||
* @param name environment name |
||||
* @param config environment config |
||||
* @param desc environment desc |
||||
* @param workerGroups worker groups |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
@Override |
||||
public Map<String, Object> updateEnvironmentByCode(User loginUser, Long code, String name, String config, String desc, String workerGroups) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
if (isNotAdmin(loginUser, result)) { |
||||
return result; |
||||
} |
||||
|
||||
Map<String, Object> checkResult = checkParams(name,config,workerGroups); |
||||
if (checkResult.get(Constants.STATUS) != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
Environment environment = environmentMapper.queryByEnvironmentName(name); |
||||
if (environment != null && !environment.getCode().equals(code)) { |
||||
putMsg(result, Status.ENVIRONMENT_NAME_EXISTS, name); |
||||
return result; |
||||
} |
||||
|
||||
Set<String> workerGroupSet; |
||||
if (StringUtils.isNotEmpty(workerGroups)) { |
||||
workerGroupSet = JSONUtils.parseObject(workerGroups, new TypeReference<Set<String>>() {}); |
||||
} else { |
||||
workerGroupSet = new TreeSet<>(); |
||||
} |
||||
|
||||
Set<String> existWorkerGroupSet = relationMapper |
||||
.queryByEnvironmentCode(code) |
||||
.stream() |
||||
.map(item -> item.getWorkerGroup()) |
||||
.collect(Collectors.toSet()); |
||||
|
||||
Set<String> deleteWorkerGroupSet = SetUtils.difference(existWorkerGroupSet,workerGroupSet).toSet(); |
||||
Set<String> addWorkerGroupSet = SetUtils.difference(workerGroupSet,existWorkerGroupSet).toSet(); |
||||
|
||||
// verify whether the relation of this environment and worker groups can be adjusted
|
||||
checkResult = checkUsedEnvironmentWorkerGroupRelation(deleteWorkerGroupSet, name, code); |
||||
if (checkResult.get(Constants.STATUS) != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
Environment env = new Environment(); |
||||
env.setCode(code); |
||||
env.setName(name); |
||||
env.setConfig(config); |
||||
env.setDescription(desc); |
||||
env.setOperator(loginUser.getId()); |
||||
env.setUpdateTime(new Date()); |
||||
|
||||
int update = environmentMapper.update(env, new UpdateWrapper<Environment>().lambda().eq(Environment::getCode,code)); |
||||
if (update > 0) { |
||||
deleteWorkerGroupSet.stream().forEach(key -> { |
||||
if (StringUtils.isNotEmpty(key)) { |
||||
relationMapper.delete(new QueryWrapper<EnvironmentWorkerGroupRelation>() |
||||
.lambda() |
||||
.eq(EnvironmentWorkerGroupRelation::getEnvironmentCode,code)); |
||||
} |
||||
}); |
||||
addWorkerGroupSet.stream().forEach(key -> { |
||||
if (StringUtils.isNotEmpty(key)) { |
||||
EnvironmentWorkerGroupRelation relation = new EnvironmentWorkerGroupRelation(); |
||||
relation.setEnvironmentCode(code); |
||||
relation.setWorkerGroup(key); |
||||
relation.setUpdateTime(new Date()); |
||||
relation.setCreateTime(new Date()); |
||||
relation.setOperator(loginUser.getId()); |
||||
relationMapper.insert(relation); |
||||
} |
||||
}); |
||||
putMsg(result, Status.SUCCESS); |
||||
} else { |
||||
putMsg(result, Status.UPDATE_ENVIRONMENT_ERROR, name); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* verify environment name |
||||
* |
||||
* @param environmentName environment name |
||||
* @return true if the environment name not exists, otherwise return false |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> verifyEnvironment(String environmentName) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
if (StringUtils.isEmpty(environmentName)) { |
||||
putMsg(result, Status.ENVIRONMENT_NAME_IS_NULL); |
||||
return result; |
||||
} |
||||
|
||||
Environment environment = environmentMapper.queryByEnvironmentName(environmentName); |
||||
if (environment != null) { |
||||
putMsg(result, Status.ENVIRONMENT_NAME_EXISTS, environmentName); |
||||
return result; |
||||
} |
||||
|
||||
result.put(Constants.STATUS, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
private Map<String, Object> checkUsedEnvironmentWorkerGroupRelation(Set<String> deleteKeySet,String environmentName, Long environmentCode) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
for (String workerGroup : deleteKeySet) { |
||||
TaskDefinition taskDefinition = taskDefinitionMapper |
||||
.selectOne(new QueryWrapper<TaskDefinition>().lambda() |
||||
.eq(TaskDefinition::getEnvironmentCode,environmentCode) |
||||
.eq(TaskDefinition::getWorkerGroup,workerGroup)); |
||||
|
||||
if (Objects.nonNull(taskDefinition)) { |
||||
putMsg(result, Status.UPDATE_ENVIRONMENT_WORKER_GROUP_RELATION_ERROR,workerGroup,environmentName,taskDefinition.getName()); |
||||
return result; |
||||
} |
||||
} |
||||
result.put(Constants.STATUS, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
public Map<String, Object> checkParams(String name, String config, String workerGroups) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
if (StringUtils.isEmpty(name)) { |
||||
putMsg(result, Status.ENVIRONMENT_NAME_IS_NULL); |
||||
return result; |
||||
} |
||||
if (StringUtils.isEmpty(config)) { |
||||
putMsg(result, Status.ENVIRONMENT_CONFIG_IS_NULL); |
||||
return result; |
||||
} |
||||
if (StringUtils.isNotEmpty(workerGroups)) { |
||||
List<String> workerGroupList = JSONUtils.parseObject(workerGroups, new TypeReference<List<String>>(){}); |
||||
if (Objects.isNull(workerGroupList)) { |
||||
putMsg(result, Status.ENVIRONMENT_WORKER_GROUPS_IS_INVALID); |
||||
return result; |
||||
} |
||||
} |
||||
result.put(Constants.STATUS, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,76 @@
|
||||
/* |
||||
* 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.service.impl; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.EnvironmentWorkerGroupRelationService; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentWorkerGroupRelationMapper; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
/** |
||||
* task definition service impl |
||||
*/ |
||||
@Service |
||||
public class EnvironmentWorkerGroupRelationServiceImpl extends BaseServiceImpl implements |
||||
EnvironmentWorkerGroupRelationService { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EnvironmentWorkerGroupRelationServiceImpl.class); |
||||
|
||||
@Autowired |
||||
private EnvironmentWorkerGroupRelationMapper environmentWorkerGroupRelationMapper; |
||||
|
||||
/** |
||||
* query environment worker group relation |
||||
* |
||||
* @param environmentCode environment code |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> queryEnvironmentWorkerGroupRelation(Long environmentCode) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
List<EnvironmentWorkerGroupRelation> relations = environmentWorkerGroupRelationMapper.queryByEnvironmentCode(environmentCode); |
||||
result.put(Constants.DATA_LIST, relations); |
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query all environment worker group relation |
||||
* |
||||
* @return all relation list |
||||
*/ |
||||
@Override |
||||
public Map<String, Object> queryAllEnvironmentWorkerGroupRelationList() { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
List<EnvironmentWorkerGroupRelation> relations = environmentWorkerGroupRelationMapper.selectList(null); |
||||
|
||||
result.put(Constants.DATA_LIST,relations); |
||||
putMsg(result,Status.SUCCESS); |
||||
return result; |
||||
} |
||||
} |
@ -0,0 +1,208 @@
|
||||
/* |
||||
* 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.controller; |
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.Preconditions; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.test.web.servlet.MvcResult; |
||||
import org.springframework.util.LinkedMultiValueMap; |
||||
import org.springframework.util.MultiValueMap; |
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
||||
/** |
||||
* environment controller test |
||||
*/ |
||||
public class EnvironmentControllerTest extends AbstractControllerTest { |
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(EnvironmentControllerTest.class); |
||||
|
||||
private String environmentCode; |
||||
|
||||
public static final String environmentName = "Env1"; |
||||
|
||||
public static final String config = "this is config content"; |
||||
|
||||
public static final String desc = "this is environment description"; |
||||
|
||||
@Before |
||||
public void before() throws Exception { |
||||
testCreateEnvironment(); |
||||
} |
||||
|
||||
@After |
||||
public void after() throws Exception { |
||||
testDeleteEnvironment(); |
||||
} |
||||
|
||||
public void testCreateEnvironment() throws Exception { |
||||
|
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("name",environmentName); |
||||
paramsMap.add("config",config); |
||||
paramsMap.add("description",desc); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(post("/environment/create") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isCreated()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference<Result<String>>() {}); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
Assert.assertNotNull(result.getData()); |
||||
logger.info("create environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
|
||||
environmentCode = (String)result.getData(); |
||||
} |
||||
|
||||
@Test |
||||
public void testUpdateEnvironment() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("code", environmentCode); |
||||
paramsMap.add("name","environment_test_update"); |
||||
paramsMap.add("config","this is config content"); |
||||
paramsMap.add("desc","the test environment update"); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(post("/environment/update") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
logger.info("update environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentByCode() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("environmentCode", environmentCode); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(get("/environment/query-by-code") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
logger.info(mvcResult.getResponse().getContentAsString()); |
||||
logger.info("query environment by id :{}, return result:{}", environmentCode, mvcResult.getResponse().getContentAsString()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentListPaging() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("searchVal","test"); |
||||
paramsMap.add("pageSize","2"); |
||||
paramsMap.add("pageNo","2"); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(get("/environment/list-paging") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
logger.info("query list-paging environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryAllEnvironmentList() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(get("/environment/query-environment-list") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
logger.info("query all environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testVerifyEnvironment() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("environmentName",environmentName); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(post("/environment/verify-environment") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result.isStatus(Status.ENVIRONMENT_NAME_EXISTS)); |
||||
logger.info("verify environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
|
||||
} |
||||
|
||||
private void testDeleteEnvironment() throws Exception { |
||||
Preconditions.checkNotNull(environmentCode); |
||||
|
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("environmentCode", environmentCode); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(post("/environment/delete") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
logger.info(result.toString()); |
||||
Assert.assertTrue(result != null && result.isSuccess()); |
||||
logger.info("delete environment return result:{}", mvcResult.getResponse().getContentAsString()); |
||||
} |
||||
} |
@ -0,0 +1,310 @@
|
||||
/* |
||||
* 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.service; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.impl.EnvironmentServiceImpl; |
||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.UserType; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Environment; |
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentWorkerGroupRelationMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionMapper; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.assertj.core.util.Lists; |
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper; |
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
/** |
||||
* environment service test |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class EnvironmentServiceTest { |
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(EnvironmentServiceTest.class); |
||||
|
||||
@InjectMocks |
||||
private EnvironmentServiceImpl environmentService; |
||||
|
||||
@Mock |
||||
private EnvironmentMapper environmentMapper; |
||||
|
||||
@Mock |
||||
private EnvironmentWorkerGroupRelationMapper relationMapper; |
||||
|
||||
@Mock |
||||
private TaskDefinitionMapper taskDefinitionMapper; |
||||
|
||||
public static final String testUserName = "environmentServerTest"; |
||||
|
||||
public static final String environmentName = "Env1"; |
||||
|
||||
public static final String workerGroups = "[\"default\"]"; |
||||
|
||||
@Before |
||||
public void setUp(){ |
||||
} |
||||
|
||||
@After |
||||
public void after(){ |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateEnvironment() { |
||||
User loginUser = getGeneralUser(); |
||||
Map<String, Object> result = environmentService.createEnvironment(loginUser,environmentName,getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); |
||||
|
||||
loginUser = getAdminUser(); |
||||
result = environmentService.createEnvironment(loginUser,environmentName,"",getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_CONFIG_IS_NULL, result.get(Constants.STATUS)); |
||||
|
||||
result = environmentService.createEnvironment(loginUser,"",getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_IS_NULL, result.get(Constants.STATUS)); |
||||
|
||||
result = environmentService.createEnvironment(loginUser,environmentName,getConfig(),getDesc(),"test"); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_WORKER_GROUPS_IS_INVALID, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.queryByEnvironmentName(environmentName)).thenReturn(getEnvironment()); |
||||
result = environmentService.createEnvironment(loginUser,environmentName,getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_EXISTS, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.insert(Mockito.any(Environment.class))).thenReturn(1); |
||||
Mockito.when(relationMapper.insert(Mockito.any(EnvironmentWorkerGroupRelation.class))).thenReturn(1); |
||||
result = environmentService.createEnvironment(loginUser,"testName","test","test",workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testCheckParams() { |
||||
Map<String, Object> result = environmentService.checkParams(environmentName,getConfig(),"test"); |
||||
Assert.assertEquals(Status.ENVIRONMENT_WORKER_GROUPS_IS_INVALID, result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
@Test |
||||
public void testUpdateEnvironmentByCode() { |
||||
User loginUser = getGeneralUser(); |
||||
Map<String, Object> result = environmentService.updateEnvironmentByCode(loginUser,1L,environmentName,getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); |
||||
|
||||
loginUser = getAdminUser(); |
||||
result = environmentService.updateEnvironmentByCode(loginUser,1L,environmentName,"",getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_CONFIG_IS_NULL, result.get(Constants.STATUS)); |
||||
|
||||
result = environmentService.updateEnvironmentByCode(loginUser,1L,"",getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_IS_NULL, result.get(Constants.STATUS)); |
||||
|
||||
result = environmentService.updateEnvironmentByCode(loginUser,1L,environmentName,getConfig(),getDesc(),"test"); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_WORKER_GROUPS_IS_INVALID, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.queryByEnvironmentName(environmentName)).thenReturn(getEnvironment()); |
||||
result = environmentService.updateEnvironmentByCode(loginUser,2L,environmentName,getConfig(),getDesc(),workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_EXISTS, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.update(Mockito.any(Environment.class),Mockito.any(Wrapper.class))).thenReturn(1); |
||||
result = environmentService.updateEnvironmentByCode(loginUser,1L,"testName","test","test",workerGroups); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testQueryAllEnvironmentList() { |
||||
Mockito.when(environmentMapper.queryAllEnvironmentList()).thenReturn(Lists.newArrayList(getEnvironment())); |
||||
Map<String, Object> result = environmentService.queryAllEnvironmentList(); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); |
||||
|
||||
List<Environment> list = (List<Environment>)(result.get(Constants.DATA_LIST)); |
||||
Assert.assertEquals(1,list.size()); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentListPaging() { |
||||
IPage<Environment> page = new Page<>(1, 10); |
||||
page.setRecords(getList()); |
||||
page.setTotal(1L); |
||||
Mockito.when(environmentMapper.queryEnvironmentListPaging(Mockito.any(Page.class), Mockito.eq(environmentName))).thenReturn(page); |
||||
|
||||
Result result = environmentService.queryEnvironmentListPaging(1, 10, environmentName); |
||||
logger.info(result.toString()); |
||||
PageInfo<Environment> pageInfo = (PageInfo<Environment>) result.getData(); |
||||
Assert.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getTotalList())); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentByName() { |
||||
Mockito.when(environmentMapper.queryByEnvironmentName(environmentName)).thenReturn(null); |
||||
Map<String, Object> result = environmentService.queryEnvironmentByName(environmentName); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.QUERY_ENVIRONMENT_BY_NAME_ERROR,result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.queryByEnvironmentName(environmentName)).thenReturn(getEnvironment()); |
||||
result = environmentService.queryEnvironmentByName(environmentName); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentByCode() { |
||||
Mockito.when(environmentMapper.queryByEnvironmentCode(1L)).thenReturn(null); |
||||
Map<String, Object> result = environmentService.queryEnvironmentByCode(1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.QUERY_ENVIRONMENT_BY_CODE_ERROR,result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.queryByEnvironmentCode(1L)).thenReturn(getEnvironment()); |
||||
result = environmentService.queryEnvironmentByCode(1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
@Test |
||||
public void testDeleteEnvironmentByCode() { |
||||
User loginUser = getGeneralUser(); |
||||
Map<String, Object> result = environmentService.deleteEnvironmentByCode(loginUser,1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); |
||||
|
||||
loginUser = getAdminUser(); |
||||
Mockito.when(taskDefinitionMapper.selectCount(Mockito.any(LambdaQueryWrapper.class))).thenReturn(1); |
||||
result = environmentService.deleteEnvironmentByCode(loginUser,1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.DELETE_ENVIRONMENT_RELATED_TASK_EXISTS, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(taskDefinitionMapper.selectCount(Mockito.any(LambdaQueryWrapper.class))).thenReturn(0); |
||||
Mockito.when(environmentMapper.deleteByCode(1L)).thenReturn(1); |
||||
result = environmentService.deleteEnvironmentByCode(loginUser,1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
@Test |
||||
public void testVerifyEnvironment() { |
||||
Map<String, Object> result = environmentService.verifyEnvironment(""); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_IS_NULL, result.get(Constants.STATUS)); |
||||
|
||||
Mockito.when(environmentMapper.queryByEnvironmentName(environmentName)).thenReturn(getEnvironment()); |
||||
result = environmentService.verifyEnvironment(environmentName); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.ENVIRONMENT_NAME_EXISTS, result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
private Environment getEnvironment() { |
||||
Environment environment = new Environment(); |
||||
environment.setId(1); |
||||
environment.setCode(1L); |
||||
environment.setName(environmentName); |
||||
environment.setConfig(getConfig()); |
||||
environment.setDescription(getDesc()); |
||||
environment.setOperator(1); |
||||
return environment; |
||||
} |
||||
|
||||
/** |
||||
* create an environment description |
||||
*/ |
||||
private String getDesc() { |
||||
return "create an environment to test "; |
||||
} |
||||
|
||||
/** |
||||
* create an environment config |
||||
*/ |
||||
private String getConfig() { |
||||
return "export HADOOP_HOME=/opt/hadoop-2.6.5\n" |
||||
+ "export HADOOP_CONF_DIR=/etc/hadoop/conf\n" |
||||
+ "export SPARK_HOME1=/opt/soft/spark1\n" |
||||
+ "export SPARK_HOME2=/opt/soft/spark2\n" |
||||
+ "export PYTHON_HOME=/opt/soft/python\n" |
||||
+ "export JAVA_HOME=/opt/java/jdk1.8.0_181-amd64\n" |
||||
+ "export HIVE_HOME=/opt/soft/hive\n" |
||||
+ "export FLINK_HOME=/opt/soft/flink\n" |
||||
+ "export DATAX_HOME=/opt/soft/datax\n" |
||||
+ "export YARN_CONF_DIR=\"/etc/hadoop/conf\"\n" |
||||
+ "\n" |
||||
+ "export PATH=$HADOOP_HOME/bin:$SPARK_HOME1/bin:$SPARK_HOME2/bin:$PYTHON_HOME/bin:$JAVA_HOME/bin:$HIVE_HOME/bin:$FLINK_HOME/bin:$DATAX_HOME/bin:$PATH\n" |
||||
+ "\n" |
||||
+ "export HADOOP_CLASSPATH=`hadoop classpath`\n" |
||||
+ "\n" |
||||
+ "#echo \"HADOOP_CLASSPATH=\"$HADOOP_CLASSPATH"; |
||||
} |
||||
|
||||
/** |
||||
* create general user |
||||
*/ |
||||
private User getGeneralUser() { |
||||
User loginUser = new User(); |
||||
loginUser.setUserType(UserType.GENERAL_USER); |
||||
loginUser.setUserName(testUserName); |
||||
loginUser.setId(1); |
||||
return loginUser; |
||||
} |
||||
|
||||
/** |
||||
* create admin user |
||||
*/ |
||||
private User getAdminUser() { |
||||
User loginUser = new User(); |
||||
loginUser.setUserType(UserType.ADMIN_USER); |
||||
loginUser.setUserName(testUserName); |
||||
loginUser.setId(1); |
||||
return loginUser; |
||||
} |
||||
|
||||
private List<Environment> getList() { |
||||
List<Environment> list = new ArrayList<>(); |
||||
list.add(getEnvironment()); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,69 @@
|
||||
/* |
||||
* 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.service; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.impl.EnvironmentWorkerGroupRelationServiceImpl; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
import org.apache.dolphinscheduler.dao.mapper.EnvironmentWorkerGroupRelationMapper; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.assertj.core.util.Lists; |
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* environment service test |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class EnvironmentWorkerGroupRelationServiceTest { |
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(EnvironmentWorkerGroupRelationServiceTest.class); |
||||
|
||||
@InjectMocks |
||||
private EnvironmentWorkerGroupRelationServiceImpl relationService; |
||||
|
||||
@Mock |
||||
private EnvironmentWorkerGroupRelationMapper relationMapper; |
||||
|
||||
@Test |
||||
public void testQueryEnvironmentWorkerGroupRelation() { |
||||
Mockito.when(relationMapper.queryByEnvironmentCode(1L)).thenReturn(Lists.newArrayList(new EnvironmentWorkerGroupRelation())); |
||||
Map<String, Object> result = relationService.queryEnvironmentWorkerGroupRelation(1L); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryAllEnvironmentWorkerGroupRelationList() { |
||||
Mockito.when(relationMapper.selectList(Mockito.any())).thenReturn(Lists.newArrayList(new EnvironmentWorkerGroupRelation())); |
||||
Map<String, Object> result = relationService.queryAllEnvironmentWorkerGroupRelationList(); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,111 @@
|
||||
/* |
||||
* 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.common.enums; |
||||
|
||||
import io.netty.channel.Channel; |
||||
|
||||
/** |
||||
* state event |
||||
*/ |
||||
public class StateEvent { |
||||
|
||||
/** |
||||
* origin_pid-origin_task_id-process_instance_id-task_instance_id |
||||
*/ |
||||
private String key; |
||||
|
||||
private StateEventType type; |
||||
|
||||
private ExecutionStatus executionStatus; |
||||
|
||||
private int taskInstanceId; |
||||
|
||||
private int processInstanceId; |
||||
|
||||
private String context; |
||||
|
||||
private Channel channel; |
||||
|
||||
public ExecutionStatus getExecutionStatus() { |
||||
return executionStatus; |
||||
} |
||||
|
||||
public void setExecutionStatus(ExecutionStatus executionStatus) { |
||||
this.executionStatus = executionStatus; |
||||
} |
||||
|
||||
public int getTaskInstanceId() { |
||||
return taskInstanceId; |
||||
} |
||||
|
||||
public int getProcessInstanceId() { |
||||
return processInstanceId; |
||||
} |
||||
|
||||
public void setProcessInstanceId(int processInstanceId) { |
||||
this.processInstanceId = processInstanceId; |
||||
} |
||||
|
||||
public String getContext() { |
||||
return context; |
||||
} |
||||
|
||||
public void setContext(String context) { |
||||
this.context = context; |
||||
} |
||||
|
||||
public void setTaskInstanceId(int taskInstanceId) { |
||||
this.taskInstanceId = taskInstanceId; |
||||
} |
||||
|
||||
public Channel getChannel() { |
||||
return channel; |
||||
} |
||||
|
||||
public void setChannel(Channel channel) { |
||||
this.channel = channel; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "State Event :" |
||||
+ "key: " + key |
||||
+ " type: " + type.toString() |
||||
+ " executeStatus: " + executionStatus |
||||
+ " task instance id: " + taskInstanceId |
||||
+ " process instance id: " + processInstanceId |
||||
+ " context: " + context |
||||
; |
||||
} |
||||
|
||||
public String getKey() { |
||||
return key; |
||||
} |
||||
|
||||
public void setKey(String key) { |
||||
this.key = key; |
||||
} |
||||
|
||||
public void setType(StateEventType type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public StateEventType getType() { |
||||
return this.type; |
||||
} |
||||
} |
@ -0,0 +1,142 @@
|
||||
/* |
||||
* 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.dao.entity; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
||||
/** |
||||
* Environment |
||||
*/ |
||||
@TableName("t_ds_environment") |
||||
public class Environment { |
||||
|
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private int id; |
||||
|
||||
/** |
||||
* environment code |
||||
*/ |
||||
private Long code; |
||||
|
||||
/** |
||||
* environment name |
||||
*/ |
||||
private String name; |
||||
|
||||
/** |
||||
* config content |
||||
*/ |
||||
private String config; |
||||
|
||||
private String description; |
||||
|
||||
/** |
||||
* operator user id |
||||
*/ |
||||
private Integer operator; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
private Date createTime; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
private Date updateTime; |
||||
|
||||
public int getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(int id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public Long getCode() { |
||||
return this.code; |
||||
} |
||||
|
||||
public void setCode(Long code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getConfig() { |
||||
return this.config; |
||||
} |
||||
|
||||
public void setConfig(String config) { |
||||
this.config = config; |
||||
} |
||||
|
||||
public String getDescription() { |
||||
return this.description; |
||||
} |
||||
|
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
public Integer getOperator() { |
||||
return this.operator; |
||||
} |
||||
|
||||
public void setOperator(Integer operator) { |
||||
this.operator = operator; |
||||
} |
||||
|
||||
public Date getCreateTime() { |
||||
return createTime; |
||||
} |
||||
|
||||
public void setCreateTime(Date createTime) { |
||||
this.createTime = createTime; |
||||
} |
||||
|
||||
public Date getUpdateTime() { |
||||
return updateTime; |
||||
} |
||||
|
||||
public void setUpdateTime(Date updateTime) { |
||||
this.updateTime = updateTime; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Environment{" |
||||
+ "id= " + id |
||||
+ ", code= " + code |
||||
+ ", name= " + name |
||||
+ ", config= " + config |
||||
+ ", description= " + description |
||||
+ ", operator= " + operator |
||||
+ ", createTime= " + createTime |
||||
+ ", updateTime= " + updateTime |
||||
+ "}"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,117 @@
|
||||
/* |
||||
* 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.dao.entity; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
||||
/** |
||||
* EnvironmentWorkerGroupRelation |
||||
*/ |
||||
@TableName("t_ds_environment_worker_group_relation") |
||||
public class EnvironmentWorkerGroupRelation { |
||||
|
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private int id; |
||||
|
||||
/** |
||||
* environment code |
||||
*/ |
||||
private Long environmentCode; |
||||
|
||||
/** |
||||
* worker group id |
||||
*/ |
||||
private String workerGroup; |
||||
|
||||
/** |
||||
* operator user id |
||||
*/ |
||||
private Integer operator; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
private Date createTime; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
private Date updateTime; |
||||
|
||||
public int getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(int id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getWorkerGroup() { |
||||
return workerGroup; |
||||
} |
||||
|
||||
public void setWorkerGroup(String workerGroup) { |
||||
this.workerGroup = workerGroup; |
||||
} |
||||
|
||||
public Long getEnvironmentCode() { |
||||
return this.environmentCode; |
||||
} |
||||
|
||||
public void setEnvironmentCode(Long environmentCode) { |
||||
this.environmentCode = environmentCode; |
||||
} |
||||
|
||||
public Integer getOperator() { |
||||
return this.operator; |
||||
} |
||||
|
||||
public void setOperator(Integer operator) { |
||||
this.operator = operator; |
||||
} |
||||
|
||||
public Date getCreateTime() { |
||||
return createTime; |
||||
} |
||||
|
||||
public void setCreateTime(Date createTime) { |
||||
this.createTime = createTime; |
||||
} |
||||
|
||||
public Date getUpdateTime() { |
||||
return updateTime; |
||||
} |
||||
|
||||
public void setUpdateTime(Date updateTime) { |
||||
this.updateTime = updateTime; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "EnvironmentWorkerGroupRelation{" |
||||
+ "id= " + id |
||||
+ ", environmentCode= " + environmentCode |
||||
+ ", workerGroup= " + workerGroup |
||||
+ ", operator= " + operator |
||||
+ ", createTime= " + createTime |
||||
+ ", updateTime= " + updateTime |
||||
+ "}"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,71 @@
|
||||
/* |
||||
* 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.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.Environment; |
||||
|
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
|
||||
/** |
||||
* environment mapper interface
|
||||
*/ |
||||
public interface EnvironmentMapper extends BaseMapper<Environment> { |
||||
|
||||
/** |
||||
* query environment by name |
||||
* |
||||
* @param name name |
||||
* @return environment |
||||
*/ |
||||
Environment queryByEnvironmentName(@Param("environmentName") String name); |
||||
|
||||
/** |
||||
* query environment by code |
||||
* |
||||
* @param environmentCode environmentCode |
||||
* @return environment |
||||
*/ |
||||
Environment queryByEnvironmentCode(@Param("environmentCode") Long environmentCode); |
||||
|
||||
/** |
||||
* query all environment list |
||||
* @return environment list |
||||
*/ |
||||
List<Environment> queryAllEnvironmentList(); |
||||
|
||||
/** |
||||
* environment page |
||||
* @param page page |
||||
* @param searchName searchName |
||||
* @return environment IPage |
||||
*/ |
||||
IPage<Environment> queryEnvironmentListPaging(IPage<Environment> page, @Param("searchName") String searchName); |
||||
|
||||
/** |
||||
* delete environment by code |
||||
* |
||||
* @param code code |
||||
* @return int |
||||
*/ |
||||
int deleteByCode(@Param("code") Long code); |
||||
} |
@ -0,0 +1,57 @@
|
||||
/* |
||||
* 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.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
|
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
||||
/** |
||||
* environment worker group relation mapper interface
|
||||
*/ |
||||
public interface EnvironmentWorkerGroupRelationMapper extends BaseMapper<EnvironmentWorkerGroupRelation> { |
||||
|
||||
/** |
||||
* environment worker group relation by environmentCode |
||||
* |
||||
* @param environmentCode environmentCode |
||||
* @return EnvironmentWorkerGroupRelation list |
||||
*/ |
||||
List<EnvironmentWorkerGroupRelation> queryByEnvironmentCode(@Param("environmentCode") Long environmentCode); |
||||
|
||||
/** |
||||
* environment worker group relation by workerGroupName |
||||
* |
||||
* @param workerGroupName workerGroupName |
||||
* @return EnvironmentWorkerGroupRelation list |
||||
*/ |
||||
List<EnvironmentWorkerGroupRelation> queryByWorkerGroupName(@Param("workerGroupName") String workerGroupName); |
||||
|
||||
/** |
||||
* delete environment worker group relation by processCode |
||||
* |
||||
* @param environmentCode environmentCode |
||||
* @param workerGroupName workerGroupName |
||||
* @return int |
||||
*/ |
||||
int deleteByCode(@Param("environmentCode") Long environmentCode, @Param("workerGroupName") String workerGroupName); |
||||
} |
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!-- |
||||
~ 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. |
||||
--> |
||||
|
||||
<!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.EnvironmentMapper"> |
||||
<sql id="baseSql"> |
||||
id, code, name, config, description, operator, create_time, update_time |
||||
</sql> |
||||
<select id="queryByEnvironmentName" resultType="org.apache.dolphinscheduler.dao.entity.Environment"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment |
||||
WHERE name = #{environmentName} |
||||
</select> |
||||
<select id="queryAllEnvironmentList" resultType="org.apache.dolphinscheduler.dao.entity.Environment"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment |
||||
order by create_time desc |
||||
</select> |
||||
<select id="queryEnvironmentListPaging" resultType="org.apache.dolphinscheduler.dao.entity.Environment"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment |
||||
where 1=1 |
||||
<if test="searchName!=null and searchName != ''"> |
||||
and name like concat('%', #{searchName}, '%') |
||||
</if> |
||||
order by create_time desc |
||||
</select> |
||||
<select id="queryByEnvironmentCode" resultType="org.apache.dolphinscheduler.dao.entity.Environment"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment |
||||
where code = #{environmentCode} |
||||
</select> |
||||
<delete id="deleteByCode"> |
||||
delete from t_ds_environment where code = #{code} |
||||
</delete> |
||||
</mapper> |
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!-- |
||||
~ 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. |
||||
--> |
||||
|
||||
<!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.EnvironmentWorkerGroupRelationMapper"> |
||||
<sql id="baseSql"> |
||||
id, environment_code, worker_group, operator, create_time, update_time |
||||
</sql> |
||||
<select id="queryByEnvironmentCode" resultType="org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment_worker_group_relation |
||||
WHERE environment_code = #{environmentCode} |
||||
</select> |
||||
<select id="queryByWorkerGroupName" resultType="org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation"> |
||||
select |
||||
<include refid="baseSql"/> |
||||
from t_ds_environment_worker_group_relation |
||||
WHERE worker_group = #{workerGroupName} |
||||
</select> |
||||
<delete id="deleteByCode"> |
||||
delete from t_ds_environment_worker_group_relation |
||||
WHERE environment_code = #{environmentCode} and worker_group = #{workerGroupName} |
||||
</delete> |
||||
</mapper> |
@ -0,0 +1,199 @@
|
||||
/* |
||||
* 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.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.Environment; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.test.annotation.Rollback; |
||||
import org.springframework.test.context.junit4.SpringRunner; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
@RunWith(SpringRunner.class) |
||||
@SpringBootTest |
||||
@Transactional |
||||
@Rollback(false) |
||||
public class EnvironmentMapperTest { |
||||
|
||||
@Autowired |
||||
EnvironmentMapper environmentMapper; |
||||
|
||||
/** |
||||
* insert |
||||
* |
||||
* @return Environment |
||||
*/ |
||||
private Environment insertOne() { |
||||
//insertOne
|
||||
Environment environment = new Environment(); |
||||
environment.setName("testEnv"); |
||||
environment.setCode(1L); |
||||
environment.setOperator(1); |
||||
environment.setConfig(getConfig()); |
||||
environment.setDescription(getDesc()); |
||||
environment.setCreateTime(new Date()); |
||||
environment.setUpdateTime(new Date()); |
||||
environmentMapper.insert(environment); |
||||
return environment; |
||||
} |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
clearTestData(); |
||||
} |
||||
|
||||
@After |
||||
public void after() { |
||||
clearTestData(); |
||||
} |
||||
|
||||
public void clearTestData() { |
||||
environmentMapper.queryAllEnvironmentList().stream().forEach(environment -> { |
||||
environmentMapper.deleteByCode(environment.getCode()); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* test update |
||||
*/ |
||||
@Test |
||||
public void testUpdate() { |
||||
//insertOne
|
||||
Environment environment = insertOne(); |
||||
environment.setDescription("new description info"); |
||||
//update
|
||||
int update = environmentMapper.updateById(environment); |
||||
Assert.assertEquals(update, 1); |
||||
} |
||||
|
||||
/** |
||||
* test delete |
||||
*/ |
||||
@Test |
||||
public void testDelete() { |
||||
Environment environment = insertOne(); |
||||
int delete = environmentMapper.deleteById(environment.getId()); |
||||
Assert.assertEquals(delete, 1); |
||||
} |
||||
|
||||
/** |
||||
* test query |
||||
*/ |
||||
@Test |
||||
public void testQuery() { |
||||
insertOne(); |
||||
//query
|
||||
List<Environment> environments = environmentMapper.selectList(null); |
||||
Assert.assertEquals(environments.size(), 1); |
||||
} |
||||
|
||||
/** |
||||
* test query environment by name |
||||
*/ |
||||
@Test |
||||
public void testQueryByEnvironmentName() { |
||||
Environment entity = insertOne(); |
||||
Environment environment = environmentMapper.queryByEnvironmentName(entity.getName()); |
||||
Assert.assertEquals(entity.toString(),environment.toString()); |
||||
} |
||||
|
||||
/** |
||||
* test query environment by code |
||||
*/ |
||||
@Test |
||||
public void testQueryByEnvironmentCode() { |
||||
Environment entity = insertOne(); |
||||
Environment environment = environmentMapper.queryByEnvironmentCode(entity.getCode()); |
||||
Assert.assertEquals(entity.toString(),environment.toString()); |
||||
} |
||||
|
||||
/** |
||||
* test query all environments |
||||
*/ |
||||
@Test |
||||
public void testQueryAllEnvironmentList() { |
||||
Environment entity = insertOne(); |
||||
List<Environment> environments = environmentMapper.queryAllEnvironmentList(); |
||||
Assert.assertEquals(environments.size(), 1); |
||||
Assert.assertEquals(entity.toString(),environments.get(0).toString()); |
||||
} |
||||
|
||||
/** |
||||
* test query environment list paging |
||||
*/ |
||||
@Test |
||||
public void testQueryEnvironmentListPaging() { |
||||
Environment entity = insertOne(); |
||||
Page<Environment> page = new Page<>(1, 10); |
||||
IPage<Environment> environmentIPage = environmentMapper.queryEnvironmentListPaging(page,""); |
||||
List<Environment> environmentList = environmentIPage.getRecords(); |
||||
Assert.assertEquals(environmentList.size(), 1); |
||||
|
||||
environmentIPage = environmentMapper.queryEnvironmentListPaging(page,"abc"); |
||||
environmentList = environmentIPage.getRecords(); |
||||
Assert.assertEquals(environmentList.size(), 0); |
||||
} |
||||
|
||||
/** |
||||
* test query all environments |
||||
*/ |
||||
@Test |
||||
public void testDeleteByCode() { |
||||
Environment entity = insertOne(); |
||||
int delete = environmentMapper.deleteByCode(entity.getCode()); |
||||
Assert.assertEquals(delete, 1); |
||||
} |
||||
|
||||
private String getDesc() { |
||||
return "create an environment to test "; |
||||
} |
||||
|
||||
/** |
||||
* create an environment config |
||||
*/ |
||||
private String getConfig() { |
||||
return "export HADOOP_HOME=/opt/hadoop-2.6.5\n" |
||||
+ "export HADOOP_CONF_DIR=/etc/hadoop/conf\n" |
||||
+ "export SPARK_HOME1=/opt/soft/spark1\n" |
||||
+ "export SPARK_HOME2=/opt/soft/spark2\n" |
||||
+ "export PYTHON_HOME=/opt/soft/python\n" |
||||
+ "export JAVA_HOME=/opt/java/jdk1.8.0_181-amd64\n" |
||||
+ "export HIVE_HOME=/opt/soft/hive\n" |
||||
+ "export FLINK_HOME=/opt/soft/flink\n" |
||||
+ "export DATAX_HOME=/opt/soft/datax\n" |
||||
+ "export YARN_CONF_DIR=\"/etc/hadoop/conf\"\n" |
||||
+ "\n" |
||||
+ "export PATH=$HADOOP_HOME/bin:$SPARK_HOME1/bin:$SPARK_HOME2/bin:$PYTHON_HOME/bin:$JAVA_HOME/bin:$HIVE_HOME/bin:$FLINK_HOME/bin:$DATAX_HOME/bin:$PATH\n" |
||||
+ "\n" |
||||
+ "export HADOOP_CLASSPATH=`hadoop classpath`\n" |
||||
+ "\n" |
||||
+ "#echo \"HADOOP_CLASSPATH=\"$HADOOP_CLASSPATH"; |
||||
} |
||||
} |
@ -0,0 +1,109 @@
|
||||
/* |
||||
* 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.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.EnvironmentWorkerGroupRelation; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.test.annotation.Rollback; |
||||
import org.springframework.test.context.junit4.SpringRunner; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
@RunWith(SpringRunner.class) |
||||
@SpringBootTest |
||||
@Transactional |
||||
@Rollback(true) |
||||
public class EnvironmentWorkerGroupRelationMapperTest { |
||||
|
||||
@Autowired |
||||
EnvironmentWorkerGroupRelationMapper environmentWorkerGroupRelationMapper; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
clearTestData(); |
||||
} |
||||
|
||||
@After |
||||
public void after() { |
||||
clearTestData(); |
||||
} |
||||
|
||||
public void clearTestData() { |
||||
environmentWorkerGroupRelationMapper.selectList(null).stream().forEach(environment -> { |
||||
environmentWorkerGroupRelationMapper.deleteById(environment.getId()); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* insert |
||||
* |
||||
* @return ProcessDefinition |
||||
*/ |
||||
private EnvironmentWorkerGroupRelation insertOne() { |
||||
//insertOne
|
||||
EnvironmentWorkerGroupRelation relation = new EnvironmentWorkerGroupRelation(); |
||||
relation.setEnvironmentCode(1L); |
||||
relation.setWorkerGroup("default"); |
||||
relation.setOperator(1); |
||||
relation.setUpdateTime(new Date()); |
||||
relation.setCreateTime(new Date()); |
||||
environmentWorkerGroupRelationMapper.insert(relation); |
||||
return relation; |
||||
} |
||||
|
||||
/** |
||||
* test query |
||||
*/ |
||||
@Test |
||||
public void testQuery() { |
||||
insertOne(); |
||||
//query
|
||||
List<EnvironmentWorkerGroupRelation> relations = environmentWorkerGroupRelationMapper.selectList(null); |
||||
Assert.assertEquals(relations.size(), 1); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryByEnvironmentCode() { |
||||
EnvironmentWorkerGroupRelation relation = insertOne(); |
||||
List<EnvironmentWorkerGroupRelation> environmentWorkerGroupRelations = environmentWorkerGroupRelationMapper.queryByEnvironmentCode(1L); |
||||
Assert.assertNotEquals(environmentWorkerGroupRelations.size(), 0); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryByWorkerGroupName() { |
||||
EnvironmentWorkerGroupRelation relation = insertOne(); |
||||
List<EnvironmentWorkerGroupRelation> environmentWorkerGroupRelations = environmentWorkerGroupRelationMapper.queryByWorkerGroupName("default"); |
||||
Assert.assertNotEquals(environmentWorkerGroupRelations.size(), 0); |
||||
} |
||||
|
||||
@Test |
||||
public void testDeleteByCode() { |
||||
EnvironmentWorkerGroupRelation relation = insertOne(); |
||||
int i = environmentWorkerGroupRelationMapper.deleteByCode(1L, "default"); |
||||
Assert.assertNotEquals(i, 0); |
||||
} |
||||
} |
@ -0,0 +1,72 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* process host update |
||||
*/ |
||||
public class HostUpdateCommand implements Serializable { |
||||
|
||||
/** |
||||
* task id |
||||
*/ |
||||
private int taskInstanceId; |
||||
|
||||
private String processHost; |
||||
|
||||
public int getTaskInstanceId() { |
||||
return taskInstanceId; |
||||
} |
||||
|
||||
public void setTaskInstanceId(int taskInstanceId) { |
||||
this.taskInstanceId = taskInstanceId; |
||||
} |
||||
|
||||
public String getProcessHost() { |
||||
return processHost; |
||||
} |
||||
|
||||
public void setProcessHost(String processHost) { |
||||
this.processHost = processHost; |
||||
} |
||||
|
||||
/** |
||||
* package request command |
||||
* |
||||
* @return command |
||||
*/ |
||||
public Command convert2Command() { |
||||
Command command = new Command(); |
||||
command.setType(CommandType.PROCESS_HOST_UPDATE_REQUST); |
||||
byte[] body = JSONUtils.toJsonByteArray(this); |
||||
command.setBody(body); |
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "HostUpdateCommand{" |
||||
+ "taskInstanceId=" + taskInstanceId |
||||
+ "host=" + processHost |
||||
+ '}'; |
||||
} |
||||
} |
@ -0,0 +1,83 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
public class HostUpdateResponseCommand implements Serializable { |
||||
|
||||
private int taskInstanceId; |
||||
|
||||
private String processHost; |
||||
|
||||
private int status; |
||||
|
||||
public HostUpdateResponseCommand(int taskInstanceId, String processHost, int code) { |
||||
this.taskInstanceId = taskInstanceId; |
||||
this.processHost = processHost; |
||||
this.status = code; |
||||
} |
||||
|
||||
public int getTaskInstanceId() { |
||||
return this.taskInstanceId; |
||||
} |
||||
|
||||
public void setTaskInstanceId(int taskInstanceId) { |
||||
this.taskInstanceId = taskInstanceId; |
||||
} |
||||
|
||||
public String getProcessHost() { |
||||
return this.processHost; |
||||
} |
||||
|
||||
public void setProcessHost(String processHost) { |
||||
this.processHost = processHost; |
||||
} |
||||
|
||||
public int getStatus() { |
||||
return status; |
||||
} |
||||
|
||||
public void setStatus(int status) { |
||||
this.status = status; |
||||
} |
||||
|
||||
/** |
||||
* package request command |
||||
* |
||||
* @return command |
||||
*/ |
||||
public Command convert2Command() { |
||||
Command command = new Command(); |
||||
command.setType(CommandType.PROCESS_HOST_UPDATE_REQUST); |
||||
byte[] body = JSONUtils.toJsonByteArray(this); |
||||
command.setBody(body); |
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "HostUpdateResponseCommand{" |
||||
+ "taskInstanceId=" + taskInstanceId |
||||
+ "host=" + processHost |
||||
+ '}'; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,131 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* db task final result response command |
||||
*/ |
||||
public class StateEventChangeCommand implements Serializable { |
||||
|
||||
private String key; |
||||
|
||||
private ExecutionStatus sourceStatus; |
||||
|
||||
private int sourceProcessInstanceId; |
||||
|
||||
private int sourceTaskInstanceId; |
||||
|
||||
private int destProcessInstanceId; |
||||
|
||||
private int destTaskInstanceId; |
||||
|
||||
public StateEventChangeCommand() { |
||||
super(); |
||||
} |
||||
|
||||
public StateEventChangeCommand(int sourceProcessInstanceId, int sourceTaskInstanceId, |
||||
ExecutionStatus sourceStatus, |
||||
int destProcessInstanceId, |
||||
int destTaskInstanceId |
||||
) { |
||||
this.key = String.format("%d-%d-%d-%d", |
||||
sourceProcessInstanceId, |
||||
sourceTaskInstanceId, |
||||
destProcessInstanceId, |
||||
destTaskInstanceId); |
||||
|
||||
this.sourceStatus = sourceStatus; |
||||
this.sourceProcessInstanceId = sourceProcessInstanceId; |
||||
this.sourceTaskInstanceId = sourceTaskInstanceId; |
||||
this.destProcessInstanceId = destProcessInstanceId; |
||||
this.destTaskInstanceId = destTaskInstanceId; |
||||
} |
||||
|
||||
public String getKey() { |
||||
return key; |
||||
} |
||||
|
||||
public void setKey(String key) { |
||||
this.key = key; |
||||
} |
||||
|
||||
/** |
||||
* package response command |
||||
* |
||||
* @return command |
||||
*/ |
||||
public Command convert2Command() { |
||||
Command command = new Command(); |
||||
command.setType(CommandType.STATE_EVENT_REQUEST); |
||||
byte[] body = JSONUtils.toJsonByteArray(this); |
||||
command.setBody(body); |
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "StateEventResponseCommand{" |
||||
+ "key=" + key |
||||
+ '}'; |
||||
} |
||||
|
||||
public ExecutionStatus getSourceStatus() { |
||||
return sourceStatus; |
||||
} |
||||
|
||||
public void setSourceStatus(ExecutionStatus sourceStatus) { |
||||
this.sourceStatus = sourceStatus; |
||||
} |
||||
|
||||
public int getSourceProcessInstanceId() { |
||||
return sourceProcessInstanceId; |
||||
} |
||||
|
||||
public void setSourceProcessInstanceId(int sourceProcessInstanceId) { |
||||
this.sourceProcessInstanceId = sourceProcessInstanceId; |
||||
} |
||||
|
||||
public int getSourceTaskInstanceId() { |
||||
return sourceTaskInstanceId; |
||||
} |
||||
|
||||
public void setSourceTaskInstanceId(int sourceTaskInstanceId) { |
||||
this.sourceTaskInstanceId = sourceTaskInstanceId; |
||||
} |
||||
|
||||
public int getDestProcessInstanceId() { |
||||
return destProcessInstanceId; |
||||
} |
||||
|
||||
public void setDestProcessInstanceId(int destProcessInstanceId) { |
||||
this.destProcessInstanceId = destProcessInstanceId; |
||||
} |
||||
|
||||
public int getDestTaskInstanceId() { |
||||
return destTaskInstanceId; |
||||
} |
||||
|
||||
public void setDestTaskInstanceId(int destTaskInstanceId) { |
||||
this.destTaskInstanceId = destTaskInstanceId; |
||||
} |
||||
} |
@ -0,0 +1,78 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* db task final result response command |
||||
*/ |
||||
public class StateEventResponseCommand implements Serializable { |
||||
|
||||
private String key; |
||||
private int status; |
||||
|
||||
public StateEventResponseCommand() { |
||||
super(); |
||||
} |
||||
|
||||
public StateEventResponseCommand(int status, String key) { |
||||
this.status = status; |
||||
this.key = key; |
||||
} |
||||
|
||||
public int getStatus() { |
||||
return status; |
||||
} |
||||
|
||||
public void setStatus(int status) { |
||||
this.status = status; |
||||
} |
||||
|
||||
public String getKey() { |
||||
return key; |
||||
} |
||||
|
||||
public void setKey(String key) { |
||||
this.key = key; |
||||
} |
||||
|
||||
/** |
||||
* package response command |
||||
* |
||||
* @return command |
||||
*/ |
||||
public Command convert2Command() { |
||||
Command command = new Command(); |
||||
command.setType(CommandType.DB_TASK_RESPONSE); |
||||
byte[] body = JSONUtils.toJsonByteArray(this); |
||||
command.setBody(body); |
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "StateEventResponseCommand{" |
||||
+ "key=" + key |
||||
+ ", status=" + status |
||||
+ '}'; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,125 @@
|
||||
/* |
||||
* 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.processor; |
||||
|
||||
import static org.apache.dolphinscheduler.common.Constants.SLEEP_TIME_MILLIS; |
||||
|
||||
import org.apache.dolphinscheduler.remote.NettyRemotingClient; |
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.apache.dolphinscheduler.remote.config.NettyClientConfig; |
||||
import org.apache.dolphinscheduler.remote.utils.Host; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import io.netty.channel.Channel; |
||||
|
||||
/** |
||||
* task callback service |
||||
*/ |
||||
@Service |
||||
public class StateEventCallbackService { |
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(StateEventCallbackService.class); |
||||
private static final int[] RETRY_BACKOFF = {1, 2, 3, 5, 10, 20, 40, 100, 100, 100, 100, 200, 200, 200}; |
||||
|
||||
/** |
||||
* remote channels |
||||
*/ |
||||
private static final ConcurrentHashMap<String, NettyRemoteChannel> REMOTE_CHANNELS = new ConcurrentHashMap<>(); |
||||
|
||||
/** |
||||
* netty remoting client |
||||
*/ |
||||
private final NettyRemotingClient nettyRemotingClient; |
||||
|
||||
public StateEventCallbackService() { |
||||
final NettyClientConfig clientConfig = new NettyClientConfig(); |
||||
this.nettyRemotingClient = new NettyRemotingClient(clientConfig); |
||||
} |
||||
|
||||
/** |
||||
* add callback channel |
||||
* |
||||
* @param channel channel |
||||
*/ |
||||
public void addRemoteChannel(String host, NettyRemoteChannel channel) { |
||||
REMOTE_CHANNELS.put(host, channel); |
||||
} |
||||
|
||||
/** |
||||
* get callback channel |
||||
* |
||||
* @param host |
||||
* @return callback channel |
||||
*/ |
||||
private NettyRemoteChannel newRemoteChannel(Host host) { |
||||
Channel newChannel; |
||||
NettyRemoteChannel nettyRemoteChannel = REMOTE_CHANNELS.get(host.getAddress()); |
||||
if (nettyRemoteChannel != null) { |
||||
if (nettyRemoteChannel.isActive()) { |
||||
return nettyRemoteChannel; |
||||
} |
||||
} |
||||
newChannel = nettyRemotingClient.getChannel(host); |
||||
if (newChannel != null) { |
||||
return newRemoteChannel(newChannel, host.getAddress()); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public int pause(int ntries) { |
||||
return SLEEP_TIME_MILLIS * RETRY_BACKOFF[ntries % RETRY_BACKOFF.length]; |
||||
} |
||||
|
||||
private NettyRemoteChannel newRemoteChannel(Channel newChannel, long opaque, String host) { |
||||
NettyRemoteChannel remoteChannel = new NettyRemoteChannel(newChannel, opaque); |
||||
addRemoteChannel(host, remoteChannel); |
||||
return remoteChannel; |
||||
} |
||||
|
||||
private NettyRemoteChannel newRemoteChannel(Channel newChannel, String host) { |
||||
NettyRemoteChannel remoteChannel = new NettyRemoteChannel(newChannel); |
||||
addRemoteChannel(host, remoteChannel); |
||||
return remoteChannel; |
||||
} |
||||
|
||||
/** |
||||
* remove callback channels |
||||
*/ |
||||
public void remove(String host) { |
||||
REMOTE_CHANNELS.remove(host); |
||||
} |
||||
|
||||
/** |
||||
* send result |
||||
* |
||||
* @param command command |
||||
*/ |
||||
public void sendResult(String address, int port, Command command) { |
||||
logger.info("send result, host:{}, command:{}", address, command.toString()); |
||||
Host host = new Host(address, port); |
||||
NettyRemoteChannel nettyRemoteChannel = newRemoteChannel(host); |
||||
if (nettyRemoteChannel != null) { |
||||
nettyRemoteChannel.writeAndFlush(command); |
||||
} |
||||
} |
||||
} |
@ -1,175 +0,0 @@
|
||||
/* |
||||
* 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.server.master.future; |
||||
|
||||
|
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import java.util.Iterator; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.CountDownLatch; |
||||
import java.util.concurrent.TimeUnit; |
||||
import java.util.concurrent.atomic.AtomicReference; |
||||
|
||||
/** |
||||
* task future |
||||
*/ |
||||
public class TaskFuture { |
||||
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(TaskFuture.class); |
||||
|
||||
private final static ConcurrentHashMap<Long,TaskFuture> FUTURE_TABLE = new ConcurrentHashMap<>(256); |
||||
|
||||
/** |
||||
* request unique identification |
||||
*/ |
||||
private final long opaque; |
||||
|
||||
/** |
||||
* timeout |
||||
*/ |
||||
private final long timeoutMillis; |
||||
|
||||
private final CountDownLatch latch = new CountDownLatch(1); |
||||
|
||||
private final long beginTimestamp = System.currentTimeMillis(); |
||||
|
||||
/** |
||||
* response command |
||||
*/ |
||||
private AtomicReference<Command> responseCommandReference = new AtomicReference<>(); |
||||
|
||||
private volatile boolean sendOk = true; |
||||
|
||||
private AtomicReference<Throwable> causeReference; |
||||
|
||||
public TaskFuture(long opaque, long timeoutMillis) { |
||||
this.opaque = opaque; |
||||
this.timeoutMillis = timeoutMillis; |
||||
FUTURE_TABLE.put(opaque, this); |
||||
} |
||||
|
||||
/** |
||||
* wait for response |
||||
* @return command |
||||
* @throws InterruptedException if error throws InterruptedException |
||||
*/ |
||||
public Command waitResponse() throws InterruptedException { |
||||
this.latch.await(timeoutMillis, TimeUnit.MILLISECONDS); |
||||
return this.responseCommandReference.get(); |
||||
} |
||||
|
||||
/** |
||||
* put response |
||||
* |
||||
* @param responseCommand responseCommand |
||||
*/ |
||||
public void putResponse(final Command responseCommand) { |
||||
responseCommandReference.set(responseCommand); |
||||
this.latch.countDown(); |
||||
FUTURE_TABLE.remove(opaque); |
||||
} |
||||
|
||||
/** |
||||
* whether timeout |
||||
* @return timeout |
||||
*/ |
||||
public boolean isTimeout() { |
||||
long diff = System.currentTimeMillis() - this.beginTimestamp; |
||||
return diff > this.timeoutMillis; |
||||
} |
||||
|
||||
public static void notify(final Command responseCommand){ |
||||
TaskFuture taskFuture = FUTURE_TABLE.remove(responseCommand.getOpaque()); |
||||
if(taskFuture != null){ |
||||
taskFuture.putResponse(responseCommand); |
||||
} |
||||
} |
||||
|
||||
|
||||
public boolean isSendOK() { |
||||
return sendOk; |
||||
} |
||||
|
||||
public void setSendOk(boolean sendOk) { |
||||
this.sendOk = sendOk; |
||||
} |
||||
|
||||
public void setCause(Throwable cause) { |
||||
causeReference.set(cause); |
||||
} |
||||
|
||||
public Throwable getCause() { |
||||
return causeReference.get(); |
||||
} |
||||
|
||||
public long getOpaque() { |
||||
return opaque; |
||||
} |
||||
|
||||
public long getTimeoutMillis() { |
||||
return timeoutMillis; |
||||
} |
||||
|
||||
public long getBeginTimestamp() { |
||||
return beginTimestamp; |
||||
} |
||||
|
||||
public Command getResponseCommand() { |
||||
return responseCommandReference.get(); |
||||
} |
||||
|
||||
public void setResponseCommand(Command responseCommand) { |
||||
responseCommandReference.set(responseCommand); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* scan future table |
||||
*/ |
||||
public static void scanFutureTable(){ |
||||
final List<TaskFuture> futureList = new LinkedList<>(); |
||||
Iterator<Map.Entry<Long, TaskFuture>> it = FUTURE_TABLE.entrySet().iterator(); |
||||
while (it.hasNext()) { |
||||
Map.Entry<Long, TaskFuture> next = it.next(); |
||||
TaskFuture future = next.getValue(); |
||||
if ((future.getBeginTimestamp() + future.getTimeoutMillis() + 1000) <= System.currentTimeMillis()) { |
||||
futureList.add(future); |
||||
it.remove(); |
||||
LOGGER.warn("remove timeout request : {}", future); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "TaskFuture{" + |
||||
"opaque=" + opaque + |
||||
", timeoutMillis=" + timeoutMillis + |
||||
", latch=" + latch + |
||||
", beginTimestamp=" + beginTimestamp + |
||||
", responseCommand=" + responseCommandReference.get() + |
||||
", sendOk=" + sendOk + |
||||
", cause=" + causeReference.get() + |
||||
'}'; |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
/* |
||||
* 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.server.master.processor; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.Preconditions; |
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.apache.dolphinscheduler.remote.command.CommandType; |
||||
import org.apache.dolphinscheduler.remote.processor.NettyRequestProcessor; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import io.netty.channel.Channel; |
||||
|
||||
public class HostUpdateResponseProcessor implements NettyRequestProcessor { |
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HostUpdateResponseProcessor.class); |
||||
|
||||
@Override |
||||
public void process(Channel channel, Command command) { |
||||
Preconditions.checkArgument(CommandType.PROCESS_HOST_UPDATE_RESPONSE == command.getType(), String.format("invalid command type : %s", command.getType())); |
||||
|
||||
HostUpdateResponseProcessor responseCommand = JSONUtils.parseObject(command.getBody(), HostUpdateResponseProcessor.class); |
||||
logger.info("received process host response command : {}", responseCommand); |
||||
} |
||||
} |
@ -0,0 +1,74 @@
|
||||
/* |
||||
* 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.server.master.processor; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.StateEvent; |
||||
import org.apache.dolphinscheduler.common.enums.StateEventType; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.Preconditions; |
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.apache.dolphinscheduler.remote.command.CommandType; |
||||
import org.apache.dolphinscheduler.remote.command.StateEventChangeCommand; |
||||
import org.apache.dolphinscheduler.remote.processor.NettyRequestProcessor; |
||||
import org.apache.dolphinscheduler.server.master.processor.queue.StateEventResponseService; |
||||
import org.apache.dolphinscheduler.server.master.runner.WorkflowExecuteThread; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import io.netty.channel.Channel; |
||||
|
||||
/** |
||||
* handle state event received from master/api |
||||
*/ |
||||
public class StateEventProcessor implements NettyRequestProcessor { |
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(StateEventProcessor.class); |
||||
|
||||
private StateEventResponseService stateEventResponseService; |
||||
|
||||
public StateEventProcessor() { |
||||
stateEventResponseService = SpringApplicationContext.getBean(StateEventResponseService.class); |
||||
} |
||||
|
||||
public void init(ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceExecMaps) { |
||||
this.stateEventResponseService.init(processInstanceExecMaps); |
||||
} |
||||
|
||||
@Override |
||||
public void process(Channel channel, Command command) { |
||||
Preconditions.checkArgument(CommandType.STATE_EVENT_REQUEST == command.getType(), String.format("invalid command type: %s", command.getType())); |
||||
|
||||
StateEventChangeCommand stateEventChangeCommand = JSONUtils.parseObject(command.getBody(), StateEventChangeCommand.class); |
||||
StateEvent stateEvent = new StateEvent(); |
||||
stateEvent.setExecutionStatus(ExecutionStatus.RUNNING_EXECUTION); |
||||
stateEvent.setKey(stateEventChangeCommand.getKey()); |
||||
stateEvent.setProcessInstanceId(stateEventChangeCommand.getDestProcessInstanceId()); |
||||
stateEvent.setTaskInstanceId(stateEventChangeCommand.getDestTaskInstanceId()); |
||||
StateEventType type = stateEvent.getTaskInstanceId() == 0 ? StateEventType.PROCESS_STATE_CHANGE : StateEventType.TASK_STATE_CHANGE; |
||||
stateEvent.setType(type); |
||||
|
||||
logger.info("received command : {}", stateEvent.toString()); |
||||
stateEventResponseService.addResponse(stateEvent); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,149 @@
|
||||
/* |
||||
* 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.server.master.processor.queue; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.StateEvent; |
||||
import org.apache.dolphinscheduler.common.thread.Stopper; |
||||
import org.apache.dolphinscheduler.remote.command.StateEventResponseCommand; |
||||
import org.apache.dolphinscheduler.server.master.runner.WorkflowExecuteThread; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.concurrent.BlockingQueue; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
import javax.annotation.PreDestroy; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import io.netty.channel.Channel; |
||||
|
||||
/** |
||||
* task manager |
||||
*/ |
||||
@Component |
||||
public class StateEventResponseService { |
||||
|
||||
/** |
||||
* logger |
||||
*/ |
||||
private final Logger logger = LoggerFactory.getLogger(StateEventResponseService.class); |
||||
|
||||
/** |
||||
* attemptQueue |
||||
*/ |
||||
private final BlockingQueue<StateEvent> eventQueue = new LinkedBlockingQueue<>(5000); |
||||
|
||||
/** |
||||
* task response worker |
||||
*/ |
||||
private Thread responseWorker; |
||||
|
||||
private ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceMapper; |
||||
|
||||
public void init(ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceMapper) { |
||||
if (this.processInstanceMapper == null) { |
||||
this.processInstanceMapper = processInstanceMapper; |
||||
} |
||||
} |
||||
|
||||
@PostConstruct |
||||
public void start() { |
||||
this.responseWorker = new StateEventResponseWorker(); |
||||
this.responseWorker.setName("StateEventResponseWorker"); |
||||
this.responseWorker.start(); |
||||
} |
||||
|
||||
@PreDestroy |
||||
public void stop() { |
||||
this.responseWorker.interrupt(); |
||||
if (!eventQueue.isEmpty()) { |
||||
List<StateEvent> remainEvents = new ArrayList<>(eventQueue.size()); |
||||
eventQueue.drainTo(remainEvents); |
||||
for (StateEvent event : remainEvents) { |
||||
this.persist(event); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* put task to attemptQueue |
||||
*/ |
||||
public void addResponse(StateEvent stateEvent) { |
||||
try { |
||||
eventQueue.put(stateEvent); |
||||
} catch (InterruptedException e) { |
||||
logger.error("put state event : {} error :{}", stateEvent, e); |
||||
Thread.currentThread().interrupt(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* task worker thread |
||||
*/ |
||||
class StateEventResponseWorker extends Thread { |
||||
|
||||
@Override |
||||
public void run() { |
||||
|
||||
while (Stopper.isRunning()) { |
||||
try { |
||||
// if not task , blocking here
|
||||
StateEvent stateEvent = eventQueue.take(); |
||||
persist(stateEvent); |
||||
} catch (InterruptedException e) { |
||||
logger.warn("persist task error", e); |
||||
Thread.currentThread().interrupt(); |
||||
} |
||||
} |
||||
logger.info("StateEventResponseWorker stopped"); |
||||
} |
||||
} |
||||
|
||||
private void writeResponse(StateEvent stateEvent, ExecutionStatus status) { |
||||
Channel channel = stateEvent.getChannel(); |
||||
if (channel != null) { |
||||
StateEventResponseCommand command = new StateEventResponseCommand(status.getCode(), stateEvent.getKey()); |
||||
channel.writeAndFlush(command.convert2Command()); |
||||
} |
||||
} |
||||
|
||||
private void persist(StateEvent stateEvent) { |
||||
try { |
||||
if (!this.processInstanceMapper.containsKey(stateEvent.getProcessInstanceId())) { |
||||
writeResponse(stateEvent, ExecutionStatus.FAILURE); |
||||
return; |
||||
} |
||||
|
||||
WorkflowExecuteThread workflowExecuteThread = this.processInstanceMapper.get(stateEvent.getProcessInstanceId()); |
||||
workflowExecuteThread.addStateEvent(stateEvent); |
||||
writeResponse(stateEvent, ExecutionStatus.SUCCESS); |
||||
} catch (Exception e) { |
||||
logger.error("persist event queue error:", stateEvent.toString(), e); |
||||
} |
||||
} |
||||
|
||||
public BlockingQueue<StateEvent> getEventQueue() { |
||||
return eventQueue; |
||||
} |
||||
} |
@ -0,0 +1,195 @@
|
||||
/* |
||||
* 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.server.master.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.StateEvent; |
||||
import org.apache.dolphinscheduler.common.enums.StateEventType; |
||||
import org.apache.dolphinscheduler.common.thread.Stopper; |
||||
import org.apache.dolphinscheduler.common.thread.ThreadUtils; |
||||
import org.apache.dolphinscheduler.common.utils.NetUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.remote.command.StateEventChangeCommand; |
||||
import org.apache.dolphinscheduler.remote.processor.StateEventCallbackService; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ExecutorService; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import com.google.common.util.concurrent.FutureCallback; |
||||
import com.google.common.util.concurrent.Futures; |
||||
import com.google.common.util.concurrent.ListenableFuture; |
||||
import com.google.common.util.concurrent.ListeningExecutorService; |
||||
import com.google.common.util.concurrent.MoreExecutors; |
||||
|
||||
@Service |
||||
public class EventExecuteService extends Thread { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EventExecuteService.class); |
||||
|
||||
|
||||
/** |
||||
* dolphinscheduler database interface
|
||||
*/ |
||||
@Autowired |
||||
private ProcessService processService; |
||||
|
||||
@Autowired |
||||
private MasterConfig masterConfig; |
||||
|
||||
private ExecutorService eventExecService; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
private StateEventCallbackService stateEventCallbackService; |
||||
|
||||
|
||||
private ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceExecMaps; |
||||
private ConcurrentHashMap<String, WorkflowExecuteThread> eventHandlerMap = new ConcurrentHashMap(); |
||||
ListeningExecutorService listeningExecutorService; |
||||
|
||||
public void init(ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceExecMaps) { |
||||
|
||||
eventExecService = ThreadUtils.newDaemonFixedThreadExecutor("MasterEventExecution", masterConfig.getMasterExecThreads()); |
||||
|
||||
this.processInstanceExecMaps = processInstanceExecMaps; |
||||
|
||||
listeningExecutorService = MoreExecutors.listeningDecorator(eventExecService); |
||||
this.stateEventCallbackService = SpringApplicationContext.getBean(StateEventCallbackService.class); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public synchronized void start() { |
||||
super.setName("EventServiceStarted"); |
||||
super.start(); |
||||
} |
||||
|
||||
public void close() { |
||||
eventExecService.shutdown(); |
||||
logger.info("event service stopped..."); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
logger.info("Event service started"); |
||||
while (Stopper.isRunning()) { |
||||
try { |
||||
eventHandler(); |
||||
|
||||
} catch (Exception e) { |
||||
logger.error("Event service thread error", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void eventHandler() { |
||||
for (WorkflowExecuteThread workflowExecuteThread : this.processInstanceExecMaps.values()) { |
||||
if (workflowExecuteThread.eventSize() == 0 |
||||
|| StringUtils.isEmpty(workflowExecuteThread.getKey()) |
||||
|| eventHandlerMap.containsKey(workflowExecuteThread.getKey())) { |
||||
continue; |
||||
} |
||||
int processInstanceId = workflowExecuteThread.getProcessInstance().getId(); |
||||
logger.info("handle process instance : {} events, count:{}", |
||||
processInstanceId, |
||||
workflowExecuteThread.eventSize()); |
||||
logger.info("already exists handler process size:{}", this.eventHandlerMap.size()); |
||||
eventHandlerMap.put(workflowExecuteThread.getKey(), workflowExecuteThread); |
||||
ListenableFuture future = this.listeningExecutorService.submit(workflowExecuteThread); |
||||
FutureCallback futureCallback = new FutureCallback() { |
||||
@Override |
||||
public void onSuccess(Object o) { |
||||
if (workflowExecuteThread.workFlowFinish()) { |
||||
processInstanceExecMaps.remove(processInstanceId); |
||||
notifyProcessChanged(); |
||||
logger.info("process instance {} finished.", processInstanceId); |
||||
} |
||||
if (workflowExecuteThread.getProcessInstance().getId() != processInstanceId) { |
||||
processInstanceExecMaps.remove(processInstanceId); |
||||
processInstanceExecMaps.put(workflowExecuteThread.getProcessInstance().getId(), workflowExecuteThread); |
||||
|
||||
} |
||||
eventHandlerMap.remove(workflowExecuteThread.getKey()); |
||||
} |
||||
|
||||
private void notifyProcessChanged() { |
||||
Map<ProcessInstance, TaskInstance> fatherMaps |
||||
= processService.notifyProcessList(processInstanceId, 0); |
||||
|
||||
for (ProcessInstance processInstance : fatherMaps.keySet()) { |
||||
String address = NetUtils.getAddr(masterConfig.getListenPort()); |
||||
if (processInstance.getHost().equalsIgnoreCase(address)) { |
||||
notifyMyself(processInstance, fatherMaps.get(processInstance)); |
||||
} else { |
||||
notifyProcess(processInstance, fatherMaps.get(processInstance)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void notifyMyself(ProcessInstance processInstance, TaskInstance taskInstance) { |
||||
logger.info("notify process {} task {} state change", processInstance.getId(), taskInstance.getId()); |
||||
if (!processInstanceExecMaps.containsKey(processInstance.getId())) { |
||||
return; |
||||
} |
||||
WorkflowExecuteThread workflowExecuteThreadNotify = processInstanceExecMaps.get(processInstance.getId()); |
||||
StateEvent stateEvent = new StateEvent(); |
||||
stateEvent.setTaskInstanceId(taskInstance.getId()); |
||||
stateEvent.setType(StateEventType.TASK_STATE_CHANGE); |
||||
stateEvent.setProcessInstanceId(processInstance.getId()); |
||||
stateEvent.setExecutionStatus(ExecutionStatus.RUNNING_EXECUTION); |
||||
workflowExecuteThreadNotify.addStateEvent(stateEvent); |
||||
} |
||||
|
||||
private void notifyProcess(ProcessInstance processInstance, TaskInstance taskInstance) { |
||||
String host = processInstance.getHost(); |
||||
if (StringUtils.isEmpty(host)) { |
||||
logger.info("process {} host is empty, cannot notify task {} now.", |
||||
processInstance.getId(), taskInstance.getId()); |
||||
return; |
||||
} |
||||
String address = host.split(":")[0]; |
||||
int port = Integer.parseInt(host.split(":")[1]); |
||||
logger.info("notify process {} task {} state change, host:{}", |
||||
processInstance.getId(), taskInstance.getId(), host); |
||||
StateEventChangeCommand stateEventChangeCommand = new StateEventChangeCommand( |
||||
processInstanceId, 0, workflowExecuteThread.getProcessInstance().getState(), processInstance.getId(), taskInstance.getId() |
||||
); |
||||
|
||||
stateEventCallbackService.sendResult(address, port, stateEventChangeCommand.convert2Command()); |
||||
} |
||||
|
||||
@Override |
||||
public void onFailure(Throwable throwable) { |
||||
} |
||||
}; |
||||
Futures.addCallback(future, futureCallback, this.listeningExecutorService); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,154 @@
|
||||
/* |
||||
* 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.server.master.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.StateEvent; |
||||
import org.apache.dolphinscheduler.common.enums.StateEventType; |
||||
import org.apache.dolphinscheduler.common.enums.TimeoutFlag; |
||||
import org.apache.dolphinscheduler.common.thread.Stopper; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
|
||||
import org.apache.hadoop.util.ThreadUtil; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* 1. timeout check wheel |
||||
* 2. dependent task check wheel |
||||
*/ |
||||
public class StateWheelExecuteThread extends Thread { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StateWheelExecuteThread.class); |
||||
|
||||
ConcurrentHashMap<Integer, ProcessInstance> processInstanceCheckList; |
||||
ConcurrentHashMap<Integer, TaskInstance> taskInstanceCheckList; |
||||
private ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceExecMaps; |
||||
|
||||
private int stateCheckIntervalSecs; |
||||
|
||||
public StateWheelExecuteThread(ConcurrentHashMap<Integer, ProcessInstance> processInstances, |
||||
ConcurrentHashMap<Integer, TaskInstance> taskInstances, |
||||
ConcurrentHashMap<Integer, WorkflowExecuteThread> processInstanceExecMaps, |
||||
int stateCheckIntervalSecs) { |
||||
this.processInstanceCheckList = processInstances; |
||||
this.taskInstanceCheckList = taskInstances; |
||||
this.processInstanceExecMaps = processInstanceExecMaps; |
||||
this.stateCheckIntervalSecs = stateCheckIntervalSecs; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
|
||||
logger.info("state wheel thread start"); |
||||
while (Stopper.isRunning()) { |
||||
try { |
||||
checkProcess(); |
||||
checkTask(); |
||||
} catch (Exception e) { |
||||
logger.error("state wheel thread check error:", e); |
||||
} |
||||
ThreadUtil.sleepAtLeastIgnoreInterrupts(stateCheckIntervalSecs); |
||||
} |
||||
} |
||||
|
||||
public boolean addProcess(ProcessInstance processInstance) { |
||||
this.processInstanceCheckList.put(processInstance.getId(), processInstance); |
||||
return true; |
||||
} |
||||
|
||||
public boolean addTask(TaskInstance taskInstance) { |
||||
this.taskInstanceCheckList.put(taskInstance.getId(), taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
private void checkTask() { |
||||
if (taskInstanceCheckList.isEmpty()) { |
||||
return; |
||||
} |
||||
|
||||
for (TaskInstance taskInstance : this.taskInstanceCheckList.values()) { |
||||
if (TimeoutFlag.OPEN == taskInstance.getTaskDefine().getTimeoutFlag()) { |
||||
long timeRemain = DateUtils.getRemainTime(taskInstance.getStartTime(), taskInstance.getTaskDefine().getTimeout() * Constants.SEC_2_MINUTES_TIME_UNIT); |
||||
if (0 <= timeRemain && processTimeout(taskInstance)) { |
||||
taskInstanceCheckList.remove(taskInstance.getId()); |
||||
return; |
||||
} |
||||
} |
||||
if (taskInstance.isSubProcess() || taskInstance.isDependTask()) { |
||||
processDependCheck(taskInstance); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void checkProcess() { |
||||
if (processInstanceCheckList.isEmpty()) { |
||||
return; |
||||
} |
||||
for (ProcessInstance processInstance : this.processInstanceCheckList.values()) { |
||||
|
||||
long timeRemain = DateUtils.getRemainTime(processInstance.getStartTime(), processInstance.getTimeout() * Constants.SEC_2_MINUTES_TIME_UNIT); |
||||
if (0 <= timeRemain && processTimeout(processInstance)) { |
||||
processInstanceCheckList.remove(processInstance.getId()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void putEvent(StateEvent stateEvent) { |
||||
|
||||
if (!processInstanceExecMaps.containsKey(stateEvent.getProcessInstanceId())) { |
||||
return; |
||||
} |
||||
WorkflowExecuteThread workflowExecuteThread = this.processInstanceExecMaps.get(stateEvent.getProcessInstanceId()); |
||||
workflowExecuteThread.addStateEvent(stateEvent); |
||||
} |
||||
|
||||
private boolean processDependCheck(TaskInstance taskInstance) { |
||||
StateEvent stateEvent = new StateEvent(); |
||||
stateEvent.setType(StateEventType.TASK_STATE_CHANGE); |
||||
stateEvent.setProcessInstanceId(taskInstance.getProcessInstanceId()); |
||||
stateEvent.setTaskInstanceId(taskInstance.getId()); |
||||
stateEvent.setExecutionStatus(ExecutionStatus.RUNNING_EXECUTION); |
||||
putEvent(stateEvent); |
||||
return true; |
||||
} |
||||
|
||||
private boolean processTimeout(TaskInstance taskInstance) { |
||||
StateEvent stateEvent = new StateEvent(); |
||||
stateEvent.setType(StateEventType.TASK_TIMEOUT); |
||||
stateEvent.setProcessInstanceId(taskInstance.getProcessInstanceId()); |
||||
stateEvent.setTaskInstanceId(taskInstance.getId()); |
||||
putEvent(stateEvent); |
||||
return true; |
||||
} |
||||
|
||||
private boolean processTimeout(ProcessInstance processInstance) { |
||||
StateEvent stateEvent = new StateEvent(); |
||||
stateEvent.setType(StateEventType.PROCESS_TIMEOUT); |
||||
stateEvent.setProcessInstanceId(processInstance.getId()); |
||||
putEvent(stateEvent); |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,112 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public abstract class BaseTaskProcessor implements ITaskProcessor { |
||||
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass()); |
||||
|
||||
protected boolean killed = false; |
||||
|
||||
protected boolean paused = false; |
||||
|
||||
protected boolean timeout = false; |
||||
|
||||
protected TaskInstance taskInstance = null; |
||||
|
||||
protected ProcessInstance processInstance; |
||||
|
||||
/** |
||||
* pause task, common tasks donot need this. |
||||
* |
||||
* @return |
||||
*/ |
||||
protected abstract boolean pauseTask(); |
||||
|
||||
/** |
||||
* kill task, all tasks need to realize this function |
||||
* |
||||
* @return |
||||
*/ |
||||
protected abstract boolean killTask(); |
||||
|
||||
/** |
||||
* task timeout process |
||||
* @return |
||||
*/ |
||||
protected abstract boolean taskTimeout(); |
||||
|
||||
@Override |
||||
public void run() { |
||||
} |
||||
|
||||
@Override |
||||
public boolean action(TaskAction taskAction) { |
||||
|
||||
switch (taskAction) { |
||||
case STOP: |
||||
return stop(); |
||||
case PAUSE: |
||||
return pause(); |
||||
case TIMEOUT: |
||||
return timeout(); |
||||
default: |
||||
logger.error("unknown task action: {}", taskAction.toString()); |
||||
|
||||
} |
||||
return false; |
||||
} |
||||
|
||||
protected boolean timeout() { |
||||
if (timeout) { |
||||
return true; |
||||
} |
||||
timeout = taskTimeout(); |
||||
return timeout; |
||||
} |
||||
|
||||
/** |
||||
* @return |
||||
*/ |
||||
protected boolean pause() { |
||||
if (paused) { |
||||
return true; |
||||
} |
||||
paused = pauseTask(); |
||||
return paused; |
||||
} |
||||
|
||||
protected boolean stop() { |
||||
if (killed) { |
||||
return true; |
||||
} |
||||
killed = killTask(); |
||||
return killed; |
||||
} |
||||
|
||||
@Override |
||||
public String getType() { |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
|
||||
public class CommonTaskProcessFactory implements ITaskProcessFactory { |
||||
@Override |
||||
public String type() { |
||||
return Constants.COMMON_TASK_TYPE; |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public ITaskProcessor create() { |
||||
return new CommonTaskProcessor(); |
||||
} |
||||
} |
@ -0,0 +1,175 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.remote.command.TaskKillRequestCommand; |
||||
import org.apache.dolphinscheduler.remote.utils.Host; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
import org.apache.dolphinscheduler.server.master.dispatch.context.ExecutionContext; |
||||
import org.apache.dolphinscheduler.server.master.dispatch.enums.ExecutorType; |
||||
import org.apache.dolphinscheduler.server.master.dispatch.exceptions.ExecuteException; |
||||
import org.apache.dolphinscheduler.server.master.dispatch.executor.NettyExecutorManager; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
import org.apache.dolphinscheduler.service.queue.TaskPriority; |
||||
import org.apache.dolphinscheduler.service.queue.TaskPriorityQueue; |
||||
import org.apache.dolphinscheduler.service.queue.TaskPriorityQueueImpl; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
/** |
||||
* common task processor |
||||
*/ |
||||
public class CommonTaskProcessor extends BaseTaskProcessor { |
||||
|
||||
@Autowired |
||||
private TaskPriorityQueue taskUpdateQueue; |
||||
|
||||
@Autowired |
||||
MasterConfig masterConfig; |
||||
|
||||
@Autowired |
||||
NettyExecutorManager nettyExecutorManager; |
||||
|
||||
/** |
||||
* logger of MasterBaseTaskExecThread |
||||
*/ |
||||
protected Logger logger = LoggerFactory.getLogger(getClass()); |
||||
|
||||
protected ProcessService processService = SpringApplicationContext.getBean(ProcessService.class); |
||||
|
||||
@Override |
||||
public boolean submit(TaskInstance task, ProcessInstance processInstance, int maxRetryTimes, int commitInterval) { |
||||
this.processInstance = processInstance; |
||||
this.taskInstance = processService.submitTask(task, maxRetryTimes, commitInterval); |
||||
|
||||
if (this.taskInstance == null) { |
||||
return false; |
||||
} |
||||
dispatchTask(taskInstance, processInstance); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public ExecutionStatus taskState() { |
||||
return this.taskInstance.getState(); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
} |
||||
|
||||
@Override |
||||
protected boolean taskTimeout() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* common task cannot be paused |
||||
*/ |
||||
@Override |
||||
protected boolean pauseTask() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String getType() { |
||||
return Constants.COMMON_TASK_TYPE; |
||||
} |
||||
|
||||
private boolean dispatchTask(TaskInstance taskInstance, ProcessInstance processInstance) { |
||||
|
||||
try { |
||||
if (taskUpdateQueue == null) { |
||||
this.initQueue(); |
||||
} |
||||
if (taskInstance.getState().typeIsFinished()) { |
||||
logger.info(String.format("submit task , but task [%s] state [%s] is already finished. ", taskInstance.getName(), taskInstance.getState().toString())); |
||||
return true; |
||||
} |
||||
// task cannot be submitted because its execution state is RUNNING or DELAY.
|
||||
if (taskInstance.getState() == ExecutionStatus.RUNNING_EXECUTION |
||||
|| taskInstance.getState() == ExecutionStatus.DELAY_EXECUTION) { |
||||
logger.info("submit task, but the status of the task {} is already running or delayed.", taskInstance.getName()); |
||||
return true; |
||||
} |
||||
logger.info("task ready to submit: {}", taskInstance); |
||||
|
||||
TaskPriority taskPriority = new TaskPriority(processInstance.getProcessInstancePriority().getCode(), |
||||
processInstance.getId(), taskInstance.getProcessInstancePriority().getCode(), |
||||
taskInstance.getId(), org.apache.dolphinscheduler.common.Constants.DEFAULT_WORKER_GROUP); |
||||
taskUpdateQueue.put(taskPriority); |
||||
logger.info(String.format("master submit success, task : %s", taskInstance.getName())); |
||||
return true; |
||||
} catch (Exception e) { |
||||
logger.error("submit task Exception: ", e); |
||||
logger.error("task error : %s", JSONUtils.toJsonString(taskInstance)); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public void initQueue() { |
||||
this.taskUpdateQueue = SpringApplicationContext.getBean(TaskPriorityQueueImpl.class); |
||||
} |
||||
|
||||
@Override |
||||
public boolean killTask() { |
||||
|
||||
try { |
||||
taskInstance = processService.findTaskInstanceById(taskInstance.getId()); |
||||
if (taskInstance == null) { |
||||
return true; |
||||
} |
||||
if (taskInstance.getState().typeIsFinished()) { |
||||
return true; |
||||
} |
||||
if (null == taskInstance.getHost() || taskInstance.getHost().isEmpty()) { |
||||
taskInstance.setState(ExecutionStatus.KILL); |
||||
taskInstance.setEndTime(new Date()); |
||||
processService.updateTaskInstance(taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
TaskKillRequestCommand killCommand = new TaskKillRequestCommand(); |
||||
killCommand.setTaskInstanceId(taskInstance.getId()); |
||||
|
||||
ExecutionContext executionContext = new ExecutionContext(killCommand.convert2Command(), ExecutorType.WORKER); |
||||
|
||||
Host host = Host.of(taskInstance.getHost()); |
||||
executionContext.setHost(host); |
||||
|
||||
nettyExecutorManager.executeDirectly(executionContext); |
||||
} catch (ExecuteException e) { |
||||
logger.error("kill task error:", e); |
||||
return false; |
||||
} |
||||
|
||||
logger.info("master kill taskInstance name :{} taskInstance id:{}", |
||||
taskInstance.getName(), taskInstance.getId()); |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
|
||||
public class ConditionTaskProcessFactory implements ITaskProcessFactory { |
||||
@Override |
||||
public String type() { |
||||
return TaskType.CONDITIONS.getDesc(); |
||||
} |
||||
|
||||
@Override |
||||
public ITaskProcessor create() { |
||||
return new ConditionTaskProcessor(); |
||||
} |
||||
} |
@ -0,0 +1,210 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.DependResult; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.model.DependentItem; |
||||
import org.apache.dolphinscheduler.common.model.DependentTaskModel; |
||||
import org.apache.dolphinscheduler.common.task.dependent.DependentParameters; |
||||
import org.apache.dolphinscheduler.common.utils.DependentUtils; |
||||
import org.apache.dolphinscheduler.common.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.common.utils.NetUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
import org.apache.dolphinscheduler.server.utils.LogUtils; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* condition task processor |
||||
*/ |
||||
public class ConditionTaskProcessor extends BaseTaskProcessor { |
||||
|
||||
/** |
||||
* dependent parameters |
||||
*/ |
||||
private DependentParameters dependentParameters; |
||||
|
||||
ProcessInstance processInstance; |
||||
|
||||
/** |
||||
* condition result |
||||
*/ |
||||
private DependResult conditionResult = DependResult.WAITING; |
||||
|
||||
/** |
||||
* complete task map |
||||
*/ |
||||
private Map<String, ExecutionStatus> completeTaskList = new ConcurrentHashMap<>(); |
||||
|
||||
protected ProcessService processService = SpringApplicationContext.getBean(ProcessService.class); |
||||
MasterConfig masterConfig = SpringApplicationContext.getBean(MasterConfig.class); |
||||
|
||||
private TaskDefinition taskDefinition; |
||||
|
||||
@Override |
||||
public boolean submit(TaskInstance task, ProcessInstance processInstance, int masterTaskCommitRetryTimes, int masterTaskCommitInterval) { |
||||
this.processInstance = processInstance; |
||||
this.taskInstance = processService.submitTask(task, masterTaskCommitRetryTimes, masterTaskCommitInterval); |
||||
|
||||
if (this.taskInstance == null) { |
||||
return false; |
||||
} |
||||
taskDefinition = processService.findTaskDefinition( |
||||
taskInstance.getTaskCode(), taskInstance.getTaskDefinitionVersion() |
||||
); |
||||
|
||||
logger = LoggerFactory.getLogger(LoggerUtils.buildTaskId(LoggerUtils.TASK_LOGGER_INFO_PREFIX, |
||||
processInstance.getProcessDefinitionCode(), |
||||
processInstance.getProcessDefinitionVersion(), |
||||
taskInstance.getProcessInstanceId(), |
||||
taskInstance.getId())); |
||||
String threadLoggerInfoName = String.format(Constants.TASK_LOG_INFO_FORMAT, processService.formatTaskAppId(this.taskInstance)); |
||||
Thread.currentThread().setName(threadLoggerInfoName); |
||||
initTaskParameters(); |
||||
logger.info("dependent task start"); |
||||
endTask(); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public ExecutionStatus taskState() { |
||||
return this.taskInstance.getState(); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
if (conditionResult.equals(DependResult.WAITING)) { |
||||
setConditionResult(); |
||||
} else { |
||||
endTask(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected boolean pauseTask() { |
||||
this.taskInstance.setState(ExecutionStatus.PAUSE); |
||||
this.taskInstance.setEndTime(new Date()); |
||||
processService.saveTaskInstance(taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean taskTimeout() { |
||||
TaskTimeoutStrategy taskTimeoutStrategy = |
||||
taskDefinition.getTimeoutNotifyStrategy(); |
||||
if (taskTimeoutStrategy == TaskTimeoutStrategy.WARN) { |
||||
return true; |
||||
} |
||||
logger.info("condition task {} timeout, strategy {} ", |
||||
taskInstance.getId(), taskTimeoutStrategy.getDescp()); |
||||
conditionResult = DependResult.FAILED; |
||||
endTask(); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean killTask() { |
||||
this.taskInstance.setState(ExecutionStatus.KILL); |
||||
this.taskInstance.setEndTime(new Date()); |
||||
processService.saveTaskInstance(taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public String getType() { |
||||
return TaskType.CONDITIONS.getDesc(); |
||||
} |
||||
|
||||
private void initTaskParameters() { |
||||
taskInstance.setLogPath(LogUtils.getTaskLogPath(processInstance.getProcessDefinitionCode(), |
||||
processInstance.getProcessDefinitionVersion(), |
||||
taskInstance.getProcessInstanceId(), |
||||
taskInstance.getId())); |
||||
this.taskInstance.setHost(NetUtils.getAddr(masterConfig.getListenPort())); |
||||
taskInstance.setState(ExecutionStatus.RUNNING_EXECUTION); |
||||
taskInstance.setStartTime(new Date()); |
||||
this.processService.saveTaskInstance(taskInstance); |
||||
this.dependentParameters = taskInstance.getDependency(); |
||||
} |
||||
|
||||
private void setConditionResult() { |
||||
|
||||
List<TaskInstance> taskInstances = processService.findValidTaskListByProcessId(taskInstance.getProcessInstanceId()); |
||||
for (TaskInstance task : taskInstances) { |
||||
completeTaskList.putIfAbsent(task.getName(), task.getState()); |
||||
} |
||||
|
||||
List<DependResult> modelResultList = new ArrayList<>(); |
||||
for (DependentTaskModel dependentTaskModel : dependentParameters.getDependTaskList()) { |
||||
List<DependResult> itemDependResult = new ArrayList<>(); |
||||
for (DependentItem item : dependentTaskModel.getDependItemList()) { |
||||
itemDependResult.add(getDependResultForItem(item)); |
||||
} |
||||
DependResult modelResult = DependentUtils.getDependResultForRelation(dependentTaskModel.getRelation(), itemDependResult); |
||||
modelResultList.add(modelResult); |
||||
} |
||||
conditionResult = DependentUtils.getDependResultForRelation(dependentParameters.getRelation(), modelResultList); |
||||
logger.info("the conditions task depend result : {}", conditionResult); |
||||
} |
||||
|
||||
/** |
||||
* depend result for depend item |
||||
*/ |
||||
private DependResult getDependResultForItem(DependentItem item) { |
||||
|
||||
DependResult dependResult = DependResult.SUCCESS; |
||||
if (!completeTaskList.containsKey(item.getDepTasks())) { |
||||
logger.info("depend item: {} have not completed yet.", item.getDepTasks()); |
||||
dependResult = DependResult.FAILED; |
||||
return dependResult; |
||||
} |
||||
ExecutionStatus executionStatus = completeTaskList.get(item.getDepTasks()); |
||||
if (executionStatus != item.getStatus()) { |
||||
logger.info("depend item : {} expect status: {}, actual status: {}", item.getDepTasks(), item.getStatus(), executionStatus); |
||||
dependResult = DependResult.FAILED; |
||||
} |
||||
logger.info("dependent item complete {} {},{}", |
||||
Constants.DEPENDENT_SPLIT, item.getDepTasks(), dependResult); |
||||
return dependResult; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
private void endTask() { |
||||
ExecutionStatus status = (conditionResult == DependResult.SUCCESS) ? ExecutionStatus.SUCCESS : ExecutionStatus.FAILURE; |
||||
taskInstance.setState(status); |
||||
taskInstance.setEndTime(new Date()); |
||||
processService.updateTaskInstance(taskInstance); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
|
||||
public class DependentTaskProcessFactory implements ITaskProcessFactory { |
||||
|
||||
@Override |
||||
public String type() { |
||||
return TaskType.DEPENDENT.getDesc(); |
||||
} |
||||
|
||||
@Override |
||||
public ITaskProcessor create() { |
||||
return new DependentTaskProcessor(); |
||||
} |
||||
} |
@ -0,0 +1,220 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
import static org.apache.dolphinscheduler.common.Constants.DEPENDENT_SPLIT; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.DependResult; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.model.DependentTaskModel; |
||||
import org.apache.dolphinscheduler.common.task.dependent.DependentParameters; |
||||
import org.apache.dolphinscheduler.common.utils.DependentUtils; |
||||
import org.apache.dolphinscheduler.common.utils.NetUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
import org.apache.dolphinscheduler.server.utils.DependentExecute; |
||||
import org.apache.dolphinscheduler.server.utils.LogUtils; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
||||
/** |
||||
* dependent task processor |
||||
*/ |
||||
public class DependentTaskProcessor extends BaseTaskProcessor { |
||||
|
||||
private DependentParameters dependentParameters; |
||||
|
||||
/** |
||||
* dependent task list |
||||
*/ |
||||
private List<DependentExecute> dependentTaskList = new ArrayList<>(); |
||||
|
||||
/** |
||||
* depend item result map |
||||
* save the result to log file |
||||
*/ |
||||
private Map<String, DependResult> dependResultMap = new HashMap<>(); |
||||
|
||||
/** |
||||
* dependent date |
||||
*/ |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
private Date dependentDate; |
||||
|
||||
DependResult result; |
||||
|
||||
ProcessInstance processInstance; |
||||
TaskDefinition taskDefinition; |
||||
|
||||
protected ProcessService processService = SpringApplicationContext.getBean(ProcessService.class); |
||||
MasterConfig masterConfig = SpringApplicationContext.getBean(MasterConfig.class); |
||||
|
||||
boolean allDependentItemFinished; |
||||
|
||||
@Override |
||||
public boolean submit(TaskInstance task, ProcessInstance processInstance, int masterTaskCommitRetryTimes, int masterTaskCommitInterval) { |
||||
this.processInstance = processInstance; |
||||
this.taskInstance = task; |
||||
this.taskInstance = processService.submitTask(task, masterTaskCommitRetryTimes, masterTaskCommitInterval); |
||||
|
||||
if (this.taskInstance == null) { |
||||
return false; |
||||
} |
||||
taskDefinition = processService.findTaskDefinition( |
||||
taskInstance.getTaskCode(), taskInstance.getTaskDefinitionVersion() |
||||
); |
||||
taskInstance.setLogPath(LogUtils.getTaskLogPath(processInstance.getProcessDefinitionCode(), |
||||
processInstance.getProcessDefinitionVersion(), |
||||
taskInstance.getProcessInstanceId(), |
||||
taskInstance.getId())); |
||||
taskInstance.setHost(NetUtils.getAddr(masterConfig.getListenPort())); |
||||
taskInstance.setState(ExecutionStatus.RUNNING_EXECUTION); |
||||
taskInstance.setStartTime(new Date()); |
||||
processService.updateTaskInstance(taskInstance); |
||||
initDependParameters(); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public ExecutionStatus taskState() { |
||||
return this.taskInstance.getState(); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
if (!allDependentItemFinished) { |
||||
allDependentItemFinished = allDependentTaskFinish(); |
||||
} |
||||
if (allDependentItemFinished) { |
||||
getTaskDependResult(); |
||||
endTask(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected boolean taskTimeout() { |
||||
TaskTimeoutStrategy taskTimeoutStrategy = |
||||
taskDefinition.getTimeoutNotifyStrategy(); |
||||
if (TaskTimeoutStrategy.FAILED != taskTimeoutStrategy |
||||
&& TaskTimeoutStrategy.WARNFAILED != taskTimeoutStrategy) { |
||||
return true; |
||||
} |
||||
logger.info("dependent task {} timeout, strategy {} ", |
||||
taskInstance.getId(), taskTimeoutStrategy.getDescp()); |
||||
result = DependResult.FAILED; |
||||
endTask(); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* init dependent parameters |
||||
*/ |
||||
private void initDependParameters() { |
||||
this.dependentParameters = taskInstance.getDependency(); |
||||
for (DependentTaskModel taskModel : dependentParameters.getDependTaskList()) { |
||||
this.dependentTaskList.add(new DependentExecute(taskModel.getDependItemList(), taskModel.getRelation())); |
||||
} |
||||
if (processInstance.getScheduleTime() != null) { |
||||
this.dependentDate = this.processInstance.getScheduleTime(); |
||||
} else { |
||||
this.dependentDate = new Date(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected boolean pauseTask() { |
||||
this.taskInstance.setState(ExecutionStatus.PAUSE); |
||||
this.taskInstance.setEndTime(new Date()); |
||||
processService.saveTaskInstance(taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean killTask() { |
||||
this.taskInstance.setState(ExecutionStatus.KILL); |
||||
this.taskInstance.setEndTime(new Date()); |
||||
processService.saveTaskInstance(taskInstance); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* judge all dependent tasks finish |
||||
* |
||||
* @return whether all dependent tasks finish |
||||
*/ |
||||
private boolean allDependentTaskFinish() { |
||||
boolean finish = true; |
||||
for (DependentExecute dependentExecute : dependentTaskList) { |
||||
for (Map.Entry<String, DependResult> entry : dependentExecute.getDependResultMap().entrySet()) { |
||||
if (!dependResultMap.containsKey(entry.getKey())) { |
||||
dependResultMap.put(entry.getKey(), entry.getValue()); |
||||
//save depend result to log
|
||||
logger.info("dependent item complete {} {},{}", DEPENDENT_SPLIT, entry.getKey(), entry.getValue()); |
||||
} |
||||
} |
||||
if (!dependentExecute.finish(dependentDate)) { |
||||
finish = false; |
||||
} |
||||
} |
||||
return finish; |
||||
} |
||||
|
||||
/** |
||||
* get dependent result |
||||
* |
||||
* @return DependResult |
||||
*/ |
||||
private DependResult getTaskDependResult() { |
||||
List<DependResult> dependResultList = new ArrayList<>(); |
||||
for (DependentExecute dependentExecute : dependentTaskList) { |
||||
DependResult dependResult = dependentExecute.getModelDependResult(dependentDate); |
||||
dependResultList.add(dependResult); |
||||
} |
||||
result = DependentUtils.getDependResultForRelation(this.dependentParameters.getRelation(), dependResultList); |
||||
logger.info("dependent task completed, dependent result:{}", result); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
private void endTask() { |
||||
ExecutionStatus status; |
||||
status = (result == DependResult.SUCCESS) ? ExecutionStatus.SUCCESS : ExecutionStatus.FAILURE; |
||||
taskInstance.setState(status); |
||||
taskInstance.setEndTime(new Date()); |
||||
processService.saveTaskInstance(taskInstance); |
||||
} |
||||
|
||||
@Override |
||||
public String getType() { |
||||
return TaskType.DEPENDENT.getDesc(); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
/* |
||||
* 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.server.master.runner.task; |
||||
|
||||
public interface ITaskProcessFactory { |
||||
|
||||
String type(); |
||||
|
||||
ITaskProcessor create(); |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue