HuangWei
3 years ago
committed by
GitHub
28 changed files with 883 additions and 15 deletions
@ -0,0 +1,76 @@
|
||||
# OpenMLDB Node |
||||
|
||||
## Overview |
||||
|
||||
[OpenMLDB](https://openmldb.ai/) is an excellent open source machine learning database, providing a full-stack |
||||
FeatureOps solution for production. |
||||
|
||||
OpenMLDB task plugin used to execute tasks on OpenMLDB cluster. |
||||
|
||||
## Create Task |
||||
|
||||
- Click `Project -> Management-Project -> Name-Workflow Definition`, and click the "Create Workflow" button to enter the |
||||
DAG editing page. |
||||
- Drag from the toolbar <img src="/img/tasks/icons/openmldb.png" width="15"/> task node to canvas. |
||||
|
||||
## Task Example |
||||
|
||||
First, introduce some general parameters of DolphinScheduler |
||||
|
||||
- **Node name**: The node name in a workflow definition is unique. |
||||
- **Run flag**: Identifies whether this node schedules normally, if it does not need to execute, select |
||||
the `prohibition execution`. |
||||
- **Descriptive information**: Describe the function of the node. |
||||
- **Task priority**: When the number of worker threads is insufficient, execute in the order of priority from high |
||||
to low, and tasks with the same priority will execute in a first-in first-out order. |
||||
- **Worker grouping**: Assign tasks to the machines of the worker group to execute. If `Default` is selected, |
||||
randomly select a worker machine for execution. |
||||
- **Environment Name**: Configure the environment name in which run the script. |
||||
- **Times of failed retry attempts**: The number of times the task failed to resubmit. |
||||
- **Failed retry interval**: The time interval (unit minute) for resubmitting the task after a failed task. |
||||
- **Delayed execution time**: The time (unit minute) that a task delays in execution. |
||||
- **Timeout alarm**: Check the timeout alarm and timeout failure. When the task runs exceed the "timeout", an alarm |
||||
email will send and the task execution will fail. |
||||
- **Predecessor task**: Selecting a predecessor task for the current task, will set the selected predecessor task as |
||||
upstream of the current task. |
||||
|
||||
### OpenMLDB Parameters |
||||
|
||||
**Task Parameter** |
||||
|
||||
- **zookeeper** :OpenMLDB cluster zookeeper address, e.g. 127.0.0.1:2181. |
||||
- **zookeeper path** : OpenMLDB cluster zookeeper path, e.g. /openmldb. |
||||
- **Execute Mode** :determine the init mode, offline or online. You can switch it in sql statement. |
||||
- **SQL statement** :SQL statement. |
||||
- Custom parameters: It is the user-defined parameters of Python, which will replace the content with \${variable} in the script. |
||||
|
||||
Here are some examples: |
||||
|
||||
#### Load data |
||||
|
||||
![load data](/img/tasks/demo/openmldb-load-data.png) |
||||
|
||||
We use `LOAD DATA` to load data into OpenMLDB cluster. We select `offline` here, so it will load to offline storage. |
||||
|
||||
#### Feature extraction |
||||
|
||||
![fe](/img/tasks/demo/openmldb-feature-extraction.png) |
||||
|
||||
We use `SELECT INTO` to do feature extraction. We select `offline` here, so it will run sql on offline engine. |
||||
|
||||
## Environment to prepare |
||||
|
||||
### Start the OpenMLDB cluster |
||||
|
||||
You should create an OpenMLDB cluster first. If in production env, please check [deploy OpenMLDB](https://openmldb.ai/docs/en/v0.5/deploy/install_deploy.html). |
||||
|
||||
You can follow [run OpenMLDB in docker](https://openmldb.ai/docs/zh/v0.5/quickstart/openmldb_quickstart.html#id11) |
||||
to a quick start. |
||||
|
||||
### Python env |
||||
|
||||
The OpenMLDB task will use OpenMLDB Python SDK to connect OpenMLDB cluster. So you should have the Python env. |
||||
|
||||
We will use `python3` by default. You can set `PYTHON_HOME` to use your custom python env. |
||||
|
||||
Make sure you have installed OpenMLDB Python SDK in the host where the worker server running, using `pip install openmldb`. |
@ -0,0 +1,68 @@
|
||||
# OpenMLDB 节点 |
||||
|
||||
## 综述 |
||||
|
||||
[OpenMLDB](https://openmldb.ai/) 是一个优秀的开源机器学习数据库,提供生产级数据及特征开发全栈解决方案。 |
||||
|
||||
OpenMLDB任务组件可以连接OpenMLDB集群执行任务。 |
||||
|
||||
## 创建任务 |
||||
|
||||
- 点击项目管理-项目名称-工作流定义,点击“创建工作流”按钮,进入 DAG 编辑页面; |
||||
- 拖动工具栏的 <img src="/img/tasks/icons/openmldb.png" width="15"/> 任务节点到画板中。 |
||||
|
||||
## 任务样例 |
||||
|
||||
首先介绍一些DS通用参数: |
||||
|
||||
- **节点名称** :设置任务的名称。一个工作流定义中的节点名称是唯一的。 |
||||
- **运行标志** :标识这个节点是否能正常调度,如果不需要执行,可以打开禁止执行开关。 |
||||
- **描述** :描述该节点的功能。 |
||||
- **任务优先级** :worker 线程数不足时,根据优先级从高到低依次执行,优先级一样时根据先进先出原则执行。 |
||||
- **Worker 分组** :任务分配给 worker 组的机器执行,选择 Default,会随机选择一台 worker 机执行。 |
||||
- **环境名称** :配置运行脚本的环境。 |
||||
- **失败重试次数** :任务失败重新提交的次数。 |
||||
- **失败重试间隔** :任务失败重新提交任务的时间间隔,以分钟为单位。 |
||||
- **延迟执行时间** :任务延迟执行的时间,以分钟为单位。 |
||||
- **超时告警** :勾选超时告警、超时失败,当任务超过"超时时长"后,会发送告警邮件并且任务执行失败。 |
||||
- **前置任务** :选择当前任务的前置任务,会将被选择的前置任务设置为当前任务的上游。 |
||||
|
||||
### OpenMLDB 参数 |
||||
|
||||
**任务参数** |
||||
|
||||
- **zookeeper地址** :OpenMLDB集群连接地址中的zookeeper地址, e.g. 127.0.0.1:2181。 |
||||
- **zookeeper路径** : OpenMLDB集群连接地址中的zookeeper路径, e.g. /openmldb。 |
||||
- **执行模式** :初始执行模式(离线/在线),你可以在sql语句中随时切换。 |
||||
- **SQL语句** :SQL语句。 |
||||
- 自定义参数:是PYTHON局部的用户自定义参数,会替换脚本中以${变量}的内容。 |
||||
|
||||
下面有几个例子: |
||||
|
||||
#### 导入数据 |
||||
|
||||
![load data](/img/tasks/demo/openmldb-load-data.png) |
||||
|
||||
我们使用`LOAD DATA`语句导入数据到OpenMLDB集群。因为选择的是离线执行模式,所以将会导入数据到离线存储中。 |
||||
|
||||
#### 特征抽取 |
||||
|
||||
![fe](/img/tasks/demo/openmldb-feature-extraction.png) |
||||
|
||||
我们使用`SELECT INTO`进行特征抽取。因为选择的是离线执行模式,所以会使用离线引擎做特征计算。 |
||||
|
||||
## 环境准备 |
||||
|
||||
### OpenMLDB 启动 |
||||
|
||||
执行任务之前,你需要启动OpenMLDB集群。如果是在生产环境,请参考[deploy OpenMLDB](https://openmldb.ai/docs/zh/v0.5/deploy/install_deploy.html). |
||||
|
||||
你可以参考[在docker中运行OpenMLDB集群](https://openmldb.ai/docs/zh/v0.5/quickstart/openmldb_quickstart.html#id11) 快速启动。 |
||||
|
||||
### Python 环境 |
||||
|
||||
OpenMLDB任务组件将使用OpenMLDB Python SDK来连接OpenMLDB。所以你需要Python环境。 |
||||
|
||||
我们默认使用`python3`,你可以通过配置`PYTHON_HOME`来设置自己的Python环境。 |
||||
|
||||
请确保已通过`pip install openmldb`,在worker server的主机中安装了OpenMLDB Python SDK。 |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 88 KiB |
@ -0,0 +1,45 @@
|
||||
<?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. |
||||
--> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>dolphinscheduler-task-plugin</artifactId> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<version>dev-SNAPSHOT</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>dolphinscheduler-task-openmldb</artifactId> |
||||
<packaging>jar</packaging> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-spi</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-task-api</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-task-python</artifactId> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,90 @@
|
||||
/* |
||||
* 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.plugin.task.openmldb; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.model.ResourceInfo; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters; |
||||
import org.apache.dolphinscheduler.spi.utils.StringUtils; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class OpenmldbParameters extends AbstractParameters { |
||||
|
||||
private String zk; |
||||
private String zkPath; |
||||
private String executeMode; |
||||
/** |
||||
* origin sql script |
||||
*/ |
||||
private String sql; |
||||
|
||||
/** |
||||
* resource list |
||||
*/ |
||||
private List<ResourceInfo> resourceList; |
||||
|
||||
public String getZk() { |
||||
return zk; |
||||
} |
||||
|
||||
public void setZk(String zk) { |
||||
this.zk = zk; |
||||
} |
||||
|
||||
public String getZkPath() { |
||||
return zkPath; |
||||
} |
||||
|
||||
public void setZkPath(String zkPath) { |
||||
this.zkPath = zkPath; |
||||
} |
||||
|
||||
public String getExecuteMode() { |
||||
return executeMode; |
||||
} |
||||
|
||||
public void setExecuteMode(String executeMode) { |
||||
this.executeMode = executeMode; |
||||
} |
||||
|
||||
public String getSql() { |
||||
return sql; |
||||
} |
||||
|
||||
public void setSql(String sql) { |
||||
this.sql = sql; |
||||
} |
||||
|
||||
public List<ResourceInfo> getResourceList() { |
||||
return resourceList; |
||||
} |
||||
|
||||
public void setResourceList(List<ResourceInfo> resourceList) { |
||||
this.resourceList = resourceList; |
||||
} |
||||
|
||||
@Override |
||||
public boolean checkParameters() { |
||||
return StringUtils.isNotEmpty(zk) && StringUtils.isNotEmpty(zkPath) && StringUtils.isNotEmpty(sql); |
||||
} |
||||
|
||||
@Override |
||||
public List<ResourceInfo> getResourceFilesList() { |
||||
return this.resourceList; |
||||
} |
||||
} |
@ -0,0 +1,176 @@
|
||||
/* |
||||
* 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.plugin.task.openmldb; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskException; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parser.ParamUtils; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parser.ParameterUtils; |
||||
import org.apache.dolphinscheduler.plugin.task.python.PythonTask; |
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.spi.utils.StringUtils; |
||||
|
||||
import java.nio.file.Paths; |
||||
import java.util.Locale; |
||||
import java.util.Map; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.google.common.base.Preconditions; |
||||
|
||||
/** |
||||
* openmldb task |
||||
*/ |
||||
public class OpenmldbTask extends PythonTask { |
||||
|
||||
/** |
||||
* openmldb parameters |
||||
*/ |
||||
private OpenmldbParameters openmldbParameters; |
||||
|
||||
/** |
||||
* python process(openmldb only supports version 3 by default) |
||||
*/ |
||||
private static final String OPENMLDB_PYTHON = "python3"; |
||||
private static final Pattern PYTHON_PATH_PATTERN = Pattern.compile("/bin/python[\\d.]*$"); |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskRequest taskRequest |
||||
*/ |
||||
public OpenmldbTask(TaskExecutionContext taskRequest) { |
||||
super(taskRequest); |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
logger.info("openmldb task params {}", taskRequest.getTaskParams()); |
||||
|
||||
openmldbParameters = JSONUtils.parseObject(taskRequest.getTaskParams(), OpenmldbParameters.class); |
||||
|
||||
if (openmldbParameters == null || !openmldbParameters.checkParameters()) { |
||||
throw new TaskException("openmldb task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
@Deprecated |
||||
public String getPreScript() { |
||||
return ""; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return openmldbParameters; |
||||
} |
||||
|
||||
/** |
||||
* build python command file path |
||||
* |
||||
* @return python command file path |
||||
*/ |
||||
@Override |
||||
protected String buildPythonCommandFilePath() { |
||||
return String.format("%s/openmldb_%s.py", taskRequest.getExecutePath(), taskRequest.getTaskAppId()); |
||||
} |
||||
|
||||
/** |
||||
* build python script content from sql |
||||
* |
||||
* @return raw python script |
||||
*/ |
||||
@Override |
||||
protected String buildPythonScriptContent() { |
||||
logger.info("raw sql script : {}", openmldbParameters.getSql()); |
||||
|
||||
String rawSQLScript = openmldbParameters.getSql().replaceAll("[\\r]?\\n", "\n"); |
||||
Map<String, Property> paramsMap = mergeParamsWithContext(openmldbParameters); |
||||
rawSQLScript = ParameterUtils.convertParameterPlaceholders(rawSQLScript, ParamUtils.convert(paramsMap)); |
||||
|
||||
// convert sql to python script
|
||||
String pythonScript = buildPythonScriptsFromSql(rawSQLScript); |
||||
logger.info("rendered python script : {}", pythonScript); |
||||
return pythonScript; |
||||
} |
||||
|
||||
private String buildPythonScriptsFromSql(String rawSqlScript) { |
||||
// imports
|
||||
StringBuilder builder = new StringBuilder("import openmldb\nimport sqlalchemy as db\n"); |
||||
|
||||
// connect to openmldb
|
||||
builder.append(String.format("engine = db.create_engine('openmldb:///?zk=%s&zkPath=%s')\n", |
||||
openmldbParameters.getZk(), openmldbParameters.getZkPath())); |
||||
builder.append("con = engine.connect()\n"); |
||||
|
||||
// execute mode
|
||||
String executeMode = openmldbParameters.getExecuteMode().toLowerCase(Locale.ROOT); |
||||
builder.append("con.execute(\"set @@execute_mode='").append(executeMode).append("';\")\n"); |
||||
// offline job should be sync, and set job_timeout to 30min(==server.channel_keep_alive_time).
|
||||
// You can set it longer in sqls.
|
||||
if (executeMode.equals("offline")) { |
||||
builder.append("con.execute(\"set @@sync_job=true\")\n"); |
||||
builder.append("con.execute(\"set @@job_timeout=1800000\")\n"); |
||||
} |
||||
|
||||
// split sql to list
|
||||
// skip the sql only has space characters
|
||||
Pattern pattern = Pattern.compile("\\S"); |
||||
for (String sql : rawSqlScript.split(";")) { |
||||
if (pattern.matcher(sql).find()) { |
||||
sql = sql.replaceAll("\\n", "\\\\n"); |
||||
builder.append("con.execute(\"").append(sql).append("\")\n"); |
||||
} |
||||
} |
||||
return builder.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Build the python task command. |
||||
* If user have set the 'PYTHON_HOME' environment, we will use the 'PYTHON_HOME', |
||||
* if not, we will default use python. |
||||
* |
||||
* @param pythonFile Python file, cannot be empty. |
||||
* @return Python execute command, e.g. 'python test.py'. |
||||
*/ |
||||
@Override |
||||
protected String buildPythonExecuteCommand(String pythonFile) { |
||||
Preconditions.checkNotNull(pythonFile, "Python file cannot be null"); |
||||
return getPythonCommand() + " " + pythonFile; |
||||
} |
||||
|
||||
private String getPythonCommand() { |
||||
String pythonHome = System.getenv(PYTHON_HOME); |
||||
return getPythonCommand(pythonHome); |
||||
} |
||||
|
||||
private String getPythonCommand(String pythonHome) { |
||||
if (StringUtils.isEmpty(pythonHome)) { |
||||
return OPENMLDB_PYTHON; |
||||
} |
||||
// If your python home is "xx/bin/python[xx]", you are forced to use python3
|
||||
String pythonBinPath = "/bin/" + OPENMLDB_PYTHON; |
||||
Matcher matcher = PYTHON_PATH_PATTERN.matcher(pythonHome); |
||||
if (matcher.find()) { |
||||
return matcher.replaceAll(pythonBinPath); |
||||
} |
||||
return Paths.get(pythonHome, pythonBinPath).toString(); |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.task.openmldb; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskChannel; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.resource.ResourceParametersHelper; |
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils; |
||||
|
||||
public class OpenmldbTaskChannel implements TaskChannel { |
||||
@Override |
||||
public void cancelApplication(boolean status) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public OpenmldbTask createTask(TaskExecutionContext taskRequest) { |
||||
return new OpenmldbTask(taskRequest); |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters parseParameters(ParametersNode parametersNode) { |
||||
return JSONUtils.parseObject(parametersNode.getTaskParams(), OpenmldbParameters.class); |
||||
} |
||||
|
||||
@Override |
||||
public ResourceParametersHelper getResources(String parameters) { |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,44 @@
|
||||
/* |
||||
* 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.plugin.task.openmldb; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskChannel; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskChannelFactory; |
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.google.auto.service.AutoService; |
||||
|
||||
@AutoService(TaskChannelFactory.class) |
||||
public class OpenmldbTaskChannelFactory implements TaskChannelFactory { |
||||
@Override |
||||
public TaskChannel create() { |
||||
return new OpenmldbTaskChannel(); |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return "OPENMLDB"; |
||||
} |
||||
|
||||
@Override |
||||
public List<PluginParams> getParams() { |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,89 @@
|
||||
/* |
||||
* 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.plugin.task.openmldb; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.powermock.reflect.Whitebox; |
||||
|
||||
public class OpenmldbTaskTest { |
||||
static class MockOpenmldbTask extends OpenmldbTask { |
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskRequest taskRequest |
||||
*/ |
||||
public MockOpenmldbTask(TaskExecutionContext taskRequest) { |
||||
super(taskRequest); |
||||
} |
||||
|
||||
@Override |
||||
protected Map<String, Property> mergeParamsWithContext(AbstractParameters parameters) { |
||||
return new HashMap<>(); |
||||
} |
||||
} |
||||
|
||||
private OpenmldbTask createOpenmldbTask() { |
||||
return new MockOpenmldbTask(null); |
||||
} |
||||
|
||||
@Test |
||||
public void buildPythonExecuteCommand() throws Exception { |
||||
OpenmldbTask openmldbTask = createOpenmldbTask(); |
||||
String pythonFile = "test.py"; |
||||
String result1 = openmldbTask.buildPythonExecuteCommand(pythonFile); |
||||
Assert.assertEquals("python3 test.py", result1); |
||||
} |
||||
|
||||
@Test |
||||
public void buildSQLWithComment() throws Exception { |
||||
OpenmldbTask openmldbTask = createOpenmldbTask(); |
||||
OpenmldbParameters openmldbParameters = new OpenmldbParameters(); |
||||
openmldbParameters.setExecuteMode("offline"); |
||||
String rawSQLScript = "select * from users\r\n" |
||||
+ "-- some comment\n" |
||||
+ "inner join order on users.order_id = order.id; \n\n;" |
||||
+ "select * from users;"; |
||||
openmldbParameters.setSql(rawSQLScript); |
||||
Whitebox.setInternalState(openmldbTask, "openmldbParameters", openmldbParameters); |
||||
OpenmldbParameters internal = (OpenmldbParameters) openmldbTask.getParameters(); |
||||
Assert.assertNotNull(internal); |
||||
Assert.assertEquals(internal.getExecuteMode(), "offline"); |
||||
|
||||
String result1 = openmldbTask.buildPythonScriptContent(); |
||||
Assert.assertEquals("import openmldb\n" |
||||
+ "import sqlalchemy as db\n" |
||||
+ "engine = db.create_engine('openmldb:///?zk=null&zkPath=null')\n" |
||||
+ "con = engine.connect()\n" |
||||
+ "con.execute(\"set @@execute_mode='offline';\")\n" |
||||
+ "con.execute(\"set @@sync_job=true\")\n" |
||||
+ "con.execute(\"set @@job_timeout=1800000\")\n" |
||||
+ "con.execute(\"select * from users\\n-- some comment\\ninner join order on users.order_id = " |
||||
+ "order.id\")\n" |
||||
+ "con.execute(\"select * from users\")\n" |
||||
, result1); |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,87 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
import { useI18n } from 'vue-i18n' |
||||
import { useCustomParams, useResources } from '.' |
||||
import type { IJsonItem } from '../types' |
||||
|
||||
export function useOpenmldb(model: { [field: string]: any }): IJsonItem[] { |
||||
const { t } = useI18n() |
||||
const options = [ |
||||
{ |
||||
label: t('project.node.openmldb_execute_mode_offline'), |
||||
value: 'offline' |
||||
}, |
||||
{ |
||||
label: t('project.node.openmldb_execute_mode_online'), |
||||
value: 'online' |
||||
} |
||||
] |
||||
return [ |
||||
{ |
||||
type: 'input', |
||||
field: 'zk', |
||||
name: t('project.node.openmldb_zk_address'), |
||||
props: { |
||||
placeholder: t('project.node.openmldb_zk_address_tips') |
||||
}, |
||||
validate: { |
||||
trigger: ['input', 'blur'], |
||||
required: true, |
||||
validator(validate: any, value: string) { |
||||
if (!value) { |
||||
return new Error(t('project.node.openmldb_zk_address_tips')) |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
type: 'input', |
||||
field: 'zkPath', |
||||
name: t('project.node.openmldb_zk_path'), |
||||
props: { |
||||
placeholder: t('project.node.openmldb_zk_path_tips') |
||||
}, |
||||
validate: { |
||||
trigger: ['input', 'blur'], |
||||
required: true, |
||||
validator(validate: any, value: string) { |
||||
if (!value) { |
||||
return new Error(t('project.node.openmldb_zk_path_tips')) |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
type: 'radio', |
||||
field: 'executeMode', |
||||
name: t('project.node.openmldb_execute_mode'), |
||||
options: options |
||||
}, |
||||
{ |
||||
type: 'editor', |
||||
field: 'sql', |
||||
name: t('project.node.sql_statement'), |
||||
validate: { |
||||
trigger: ['input', 'trigger'], |
||||
required: true, |
||||
message: t('project.node.sql_empty_tips') |
||||
} |
||||
}, |
||||
useResources(), |
||||
...useCustomParams({ model, field: 'localParams', isSimple: false }) |
||||
] |
||||
} |
@ -0,0 +1,85 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
import { reactive } from 'vue' |
||||
import * as Fields from '../fields/index' |
||||
import type { IJsonItem, INodeData } from '../types' |
||||
import { ITaskData } from '../types' |
||||
|
||||
export function useOpenmldb({ |
||||
projectCode, |
||||
from = 0, |
||||
readonly, |
||||
data |
||||
}: { |
||||
projectCode: number |
||||
from?: number |
||||
readonly?: boolean |
||||
data?: ITaskData |
||||
}) { |
||||
const model = reactive({ |
||||
name: '', |
||||
taskType: 'OPENMLDB', |
||||
flag: 'YES', |
||||
description: '', |
||||
timeoutFlag: false, |
||||
timeoutNotifyStrategy: ['WARN'], |
||||
localParams: [], |
||||
environmentCode: null, |
||||
failRetryInterval: 1, |
||||
failRetryTimes: 0, |
||||
workerGroup: 'default', |
||||
delayTime: 0, |
||||
timeout: 30, |
||||
zk: '', |
||||
zkPath: '', |
||||
executeMode: 'offline' |
||||
} as INodeData) |
||||
|
||||
let extra: IJsonItem[] = [] |
||||
if (from === 1) { |
||||
extra = [ |
||||
Fields.useTaskType(model, readonly), |
||||
Fields.useProcessName({ |
||||
model, |
||||
projectCode, |
||||
isCreate: !data?.id, |
||||
from, |
||||
processName: data?.processName |
||||
}) |
||||
] |
||||
} |
||||
|
||||
return { |
||||
json: [ |
||||
Fields.useName(from), |
||||
...extra, |
||||
Fields.useRunFlag(), |
||||
Fields.useDescription(), |
||||
Fields.useTaskPriority(), |
||||
Fields.useWorkerGroup(), |
||||
Fields.useEnvironmentName(model, !model.id), |
||||
...Fields.useTaskGroup(model, projectCode), |
||||
...Fields.useFailed(), |
||||
Fields.useDelayTime(model), |
||||
...Fields.useTimeoutAlarm(model), |
||||
...Fields.useOpenmldb(model), |
||||
Fields.usePreTasks() |
||||
] as IJsonItem[], |
||||
model |
||||
} |
||||
} |
Loading…
Reference in new issue