recurvedata-lib 0.1.487__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of recurvedata-lib might be problematic. Click here for more details.
- recurvedata/__init__.py +0 -0
- recurvedata/__version__.py +1 -0
- recurvedata/client/__init__.py +3 -0
- recurvedata/client/client.py +150 -0
- recurvedata/client/server_client.py +91 -0
- recurvedata/config.py +99 -0
- recurvedata/connectors/__init__.py +20 -0
- recurvedata/connectors/_register.py +46 -0
- recurvedata/connectors/base.py +111 -0
- recurvedata/connectors/config_schema.py +1575 -0
- recurvedata/connectors/connectors/__init__.py +0 -0
- recurvedata/connectors/connectors/aliyun_access_key.py +30 -0
- recurvedata/connectors/connectors/auth.py +44 -0
- recurvedata/connectors/connectors/azure_blob.py +89 -0
- recurvedata/connectors/connectors/azure_synapse.py +79 -0
- recurvedata/connectors/connectors/bigquery.py +359 -0
- recurvedata/connectors/connectors/clickhouse.py +219 -0
- recurvedata/connectors/connectors/dingtalk.py +61 -0
- recurvedata/connectors/connectors/doris.py +215 -0
- recurvedata/connectors/connectors/es.py +62 -0
- recurvedata/connectors/connectors/feishu.py +65 -0
- recurvedata/connectors/connectors/ftp.py +50 -0
- recurvedata/connectors/connectors/generic.py +49 -0
- recurvedata/connectors/connectors/google_cloud_storage.py +115 -0
- recurvedata/connectors/connectors/google_service_account.py +225 -0
- recurvedata/connectors/connectors/hive.py +207 -0
- recurvedata/connectors/connectors/impala.py +210 -0
- recurvedata/connectors/connectors/jenkins.py +51 -0
- recurvedata/connectors/connectors/mail.py +89 -0
- recurvedata/connectors/connectors/microsoft_fabric.py +284 -0
- recurvedata/connectors/connectors/mongo.py +79 -0
- recurvedata/connectors/connectors/mssql.py +131 -0
- recurvedata/connectors/connectors/mysql.py +191 -0
- recurvedata/connectors/connectors/n8n.py +141 -0
- recurvedata/connectors/connectors/oss.py +74 -0
- recurvedata/connectors/connectors/owncloud.py +36 -0
- recurvedata/connectors/connectors/phoenix.py +36 -0
- recurvedata/connectors/connectors/postgres.py +230 -0
- recurvedata/connectors/connectors/python.py +50 -0
- recurvedata/connectors/connectors/redshift.py +187 -0
- recurvedata/connectors/connectors/s3.py +93 -0
- recurvedata/connectors/connectors/sftp.py +87 -0
- recurvedata/connectors/connectors/slack.py +35 -0
- recurvedata/connectors/connectors/spark.py +99 -0
- recurvedata/connectors/connectors/starrocks.py +175 -0
- recurvedata/connectors/connectors/tencent_cos.py +40 -0
- recurvedata/connectors/connectors/tidb.py +49 -0
- recurvedata/connectors/const.py +315 -0
- recurvedata/connectors/datasource.py +189 -0
- recurvedata/connectors/dbapi.py +469 -0
- recurvedata/connectors/fs.py +66 -0
- recurvedata/connectors/ftp.py +40 -0
- recurvedata/connectors/object_store.py +60 -0
- recurvedata/connectors/pigeon.py +172 -0
- recurvedata/connectors/proxy.py +104 -0
- recurvedata/connectors/service.py +223 -0
- recurvedata/connectors/utils.py +47 -0
- recurvedata/consts.py +49 -0
- recurvedata/core/__init__.py +0 -0
- recurvedata/core/config.py +46 -0
- recurvedata/core/configurable.py +27 -0
- recurvedata/core/consts.py +2 -0
- recurvedata/core/templating.py +206 -0
- recurvedata/core/tracing.py +223 -0
- recurvedata/core/transformer.py +186 -0
- recurvedata/core/translation.py +91 -0
- recurvedata/dbt/client.py +97 -0
- recurvedata/dbt/consts.py +99 -0
- recurvedata/dbt/cosmos_utils.py +275 -0
- recurvedata/dbt/error_codes.py +18 -0
- recurvedata/dbt/schemas.py +98 -0
- recurvedata/dbt/service.py +451 -0
- recurvedata/dbt/utils.py +246 -0
- recurvedata/error_codes.py +71 -0
- recurvedata/exceptions.py +72 -0
- recurvedata/executors/__init__.py +4 -0
- recurvedata/executors/cli/__init__.py +7 -0
- recurvedata/executors/cli/connector.py +117 -0
- recurvedata/executors/cli/dbt.py +118 -0
- recurvedata/executors/cli/main.py +82 -0
- recurvedata/executors/cli/parameters.py +18 -0
- recurvedata/executors/client.py +190 -0
- recurvedata/executors/consts.py +50 -0
- recurvedata/executors/debug_executor.py +100 -0
- recurvedata/executors/executor.py +300 -0
- recurvedata/executors/link_executor.py +189 -0
- recurvedata/executors/models.py +34 -0
- recurvedata/executors/schemas.py +222 -0
- recurvedata/executors/service/__init__.py +0 -0
- recurvedata/executors/service/connector.py +380 -0
- recurvedata/executors/utils.py +172 -0
- recurvedata/filestorage/__init__.py +11 -0
- recurvedata/filestorage/_factory.py +33 -0
- recurvedata/filestorage/backends/__init__.py +0 -0
- recurvedata/filestorage/backends/fsspec.py +45 -0
- recurvedata/filestorage/backends/local.py +67 -0
- recurvedata/filestorage/backends/oss.py +56 -0
- recurvedata/filestorage/interface.py +84 -0
- recurvedata/operators/__init__.py +10 -0
- recurvedata/operators/base.py +28 -0
- recurvedata/operators/config.py +21 -0
- recurvedata/operators/context.py +255 -0
- recurvedata/operators/dbt_operator/__init__.py +2 -0
- recurvedata/operators/dbt_operator/model_pipeline_link_operator.py +55 -0
- recurvedata/operators/dbt_operator/operator.py +353 -0
- recurvedata/operators/link_operator/__init__.py +1 -0
- recurvedata/operators/link_operator/operator.py +120 -0
- recurvedata/operators/models.py +55 -0
- recurvedata/operators/notify_operator/__init__.py +1 -0
- recurvedata/operators/notify_operator/operator.py +180 -0
- recurvedata/operators/operator.py +119 -0
- recurvedata/operators/python_operator/__init__.py +1 -0
- recurvedata/operators/python_operator/operator.py +132 -0
- recurvedata/operators/sensor_operator/__init__.py +1 -0
- recurvedata/operators/sensor_operator/airflow_utils.py +63 -0
- recurvedata/operators/sensor_operator/operator.py +172 -0
- recurvedata/operators/spark_operator/__init__.py +1 -0
- recurvedata/operators/spark_operator/operator.py +200 -0
- recurvedata/operators/spark_operator/spark_sample.py +47 -0
- recurvedata/operators/sql_operator/__init__.py +1 -0
- recurvedata/operators/sql_operator/operator.py +90 -0
- recurvedata/operators/task.py +211 -0
- recurvedata/operators/transfer_operator/__init__.py +40 -0
- recurvedata/operators/transfer_operator/const.py +10 -0
- recurvedata/operators/transfer_operator/dump_aliyun_sls.py +82 -0
- recurvedata/operators/transfer_operator/dump_sheet_task_base.py +292 -0
- recurvedata/operators/transfer_operator/dump_task_cass.py +155 -0
- recurvedata/operators/transfer_operator/dump_task_dbapi.py +209 -0
- recurvedata/operators/transfer_operator/dump_task_es.py +113 -0
- recurvedata/operators/transfer_operator/dump_task_feishu_sheet.py +114 -0
- recurvedata/operators/transfer_operator/dump_task_ftp.py +234 -0
- recurvedata/operators/transfer_operator/dump_task_google_sheet.py +66 -0
- recurvedata/operators/transfer_operator/dump_task_mongodb.py +168 -0
- recurvedata/operators/transfer_operator/dump_task_oss.py +285 -0
- recurvedata/operators/transfer_operator/dump_task_python.py +212 -0
- recurvedata/operators/transfer_operator/dump_task_s3.py +270 -0
- recurvedata/operators/transfer_operator/dump_task_sftp.py +229 -0
- recurvedata/operators/transfer_operator/load_task_aliyun_oss.py +107 -0
- recurvedata/operators/transfer_operator/load_task_azure_blob.py +115 -0
- recurvedata/operators/transfer_operator/load_task_azure_synapse.py +90 -0
- recurvedata/operators/transfer_operator/load_task_clickhouse.py +167 -0
- recurvedata/operators/transfer_operator/load_task_doris.py +164 -0
- recurvedata/operators/transfer_operator/load_task_email.py +188 -0
- recurvedata/operators/transfer_operator/load_task_es.py +86 -0
- recurvedata/operators/transfer_operator/load_task_filebrowser.py +151 -0
- recurvedata/operators/transfer_operator/load_task_ftp.py +19 -0
- recurvedata/operators/transfer_operator/load_task_google_bigquery.py +90 -0
- recurvedata/operators/transfer_operator/load_task_google_cloud_storage.py +127 -0
- recurvedata/operators/transfer_operator/load_task_google_sheet.py +130 -0
- recurvedata/operators/transfer_operator/load_task_hive.py +158 -0
- recurvedata/operators/transfer_operator/load_task_microsoft_fabric.py +105 -0
- recurvedata/operators/transfer_operator/load_task_mssql.py +153 -0
- recurvedata/operators/transfer_operator/load_task_mysql.py +157 -0
- recurvedata/operators/transfer_operator/load_task_owncloud.py +135 -0
- recurvedata/operators/transfer_operator/load_task_postgresql.py +109 -0
- recurvedata/operators/transfer_operator/load_task_qcloud_cos.py +119 -0
- recurvedata/operators/transfer_operator/load_task_recurve_data_prep.py +75 -0
- recurvedata/operators/transfer_operator/load_task_redshift.py +95 -0
- recurvedata/operators/transfer_operator/load_task_s3.py +150 -0
- recurvedata/operators/transfer_operator/load_task_sftp.py +90 -0
- recurvedata/operators/transfer_operator/load_task_starrocks.py +169 -0
- recurvedata/operators/transfer_operator/load_task_yicrowds.py +97 -0
- recurvedata/operators/transfer_operator/mixin.py +31 -0
- recurvedata/operators/transfer_operator/operator.py +231 -0
- recurvedata/operators/transfer_operator/task.py +223 -0
- recurvedata/operators/transfer_operator/utils.py +134 -0
- recurvedata/operators/ui.py +80 -0
- recurvedata/operators/utils/__init__.py +51 -0
- recurvedata/operators/utils/file_factory.py +150 -0
- recurvedata/operators/utils/fs.py +10 -0
- recurvedata/operators/utils/lineage.py +265 -0
- recurvedata/operators/web_init.py +15 -0
- recurvedata/pigeon/connector/__init__.py +294 -0
- recurvedata/pigeon/connector/_registry.py +17 -0
- recurvedata/pigeon/connector/aliyun_oss.py +80 -0
- recurvedata/pigeon/connector/awss3.py +123 -0
- recurvedata/pigeon/connector/azure_blob.py +176 -0
- recurvedata/pigeon/connector/azure_synapse.py +51 -0
- recurvedata/pigeon/connector/cass.py +151 -0
- recurvedata/pigeon/connector/clickhouse.py +403 -0
- recurvedata/pigeon/connector/clickhouse_native.py +351 -0
- recurvedata/pigeon/connector/dbapi.py +571 -0
- recurvedata/pigeon/connector/doris.py +166 -0
- recurvedata/pigeon/connector/es.py +176 -0
- recurvedata/pigeon/connector/feishu.py +1135 -0
- recurvedata/pigeon/connector/ftp.py +163 -0
- recurvedata/pigeon/connector/google_bigquery.py +283 -0
- recurvedata/pigeon/connector/google_cloud_storage.py +130 -0
- recurvedata/pigeon/connector/hbase_phoenix.py +108 -0
- recurvedata/pigeon/connector/hdfs.py +204 -0
- recurvedata/pigeon/connector/hive_impala.py +383 -0
- recurvedata/pigeon/connector/microsoft_fabric.py +95 -0
- recurvedata/pigeon/connector/mongodb.py +56 -0
- recurvedata/pigeon/connector/mssql.py +467 -0
- recurvedata/pigeon/connector/mysql.py +175 -0
- recurvedata/pigeon/connector/owncloud.py +92 -0
- recurvedata/pigeon/connector/postgresql.py +267 -0
- recurvedata/pigeon/connector/power_bi.py +179 -0
- recurvedata/pigeon/connector/qcloud_cos.py +79 -0
- recurvedata/pigeon/connector/redshift.py +123 -0
- recurvedata/pigeon/connector/sftp.py +73 -0
- recurvedata/pigeon/connector/sqlite.py +42 -0
- recurvedata/pigeon/connector/starrocks.py +144 -0
- recurvedata/pigeon/connector/tableau.py +162 -0
- recurvedata/pigeon/const.py +21 -0
- recurvedata/pigeon/csv.py +172 -0
- recurvedata/pigeon/docs/datasources-example.json +82 -0
- recurvedata/pigeon/docs/images/pigeon_design.png +0 -0
- recurvedata/pigeon/docs/lightweight-data-sync-solution.md +111 -0
- recurvedata/pigeon/dumper/__init__.py +171 -0
- recurvedata/pigeon/dumper/aliyun_sls.py +415 -0
- recurvedata/pigeon/dumper/base.py +141 -0
- recurvedata/pigeon/dumper/cass.py +213 -0
- recurvedata/pigeon/dumper/dbapi.py +346 -0
- recurvedata/pigeon/dumper/es.py +112 -0
- recurvedata/pigeon/dumper/ftp.py +64 -0
- recurvedata/pigeon/dumper/mongodb.py +103 -0
- recurvedata/pigeon/handler/__init__.py +4 -0
- recurvedata/pigeon/handler/base.py +153 -0
- recurvedata/pigeon/handler/csv_handler.py +290 -0
- recurvedata/pigeon/loader/__init__.py +87 -0
- recurvedata/pigeon/loader/base.py +83 -0
- recurvedata/pigeon/loader/csv_to_azure_synapse.py +214 -0
- recurvedata/pigeon/loader/csv_to_clickhouse.py +152 -0
- recurvedata/pigeon/loader/csv_to_doris.py +215 -0
- recurvedata/pigeon/loader/csv_to_es.py +51 -0
- recurvedata/pigeon/loader/csv_to_google_bigquery.py +169 -0
- recurvedata/pigeon/loader/csv_to_hive.py +468 -0
- recurvedata/pigeon/loader/csv_to_microsoft_fabric.py +242 -0
- recurvedata/pigeon/loader/csv_to_mssql.py +174 -0
- recurvedata/pigeon/loader/csv_to_mysql.py +180 -0
- recurvedata/pigeon/loader/csv_to_postgresql.py +248 -0
- recurvedata/pigeon/loader/csv_to_redshift.py +240 -0
- recurvedata/pigeon/loader/csv_to_starrocks.py +233 -0
- recurvedata/pigeon/meta.py +116 -0
- recurvedata/pigeon/row_factory.py +42 -0
- recurvedata/pigeon/schema/__init__.py +124 -0
- recurvedata/pigeon/schema/types.py +13 -0
- recurvedata/pigeon/sync.py +283 -0
- recurvedata/pigeon/transformer.py +146 -0
- recurvedata/pigeon/utils/__init__.py +134 -0
- recurvedata/pigeon/utils/bloomfilter.py +181 -0
- recurvedata/pigeon/utils/date_time.py +323 -0
- recurvedata/pigeon/utils/escape.py +15 -0
- recurvedata/pigeon/utils/fs.py +266 -0
- recurvedata/pigeon/utils/json.py +44 -0
- recurvedata/pigeon/utils/keyed_tuple.py +85 -0
- recurvedata/pigeon/utils/mp.py +156 -0
- recurvedata/pigeon/utils/sql.py +328 -0
- recurvedata/pigeon/utils/timing.py +155 -0
- recurvedata/provider_manager.py +0 -0
- recurvedata/providers/__init__.py +0 -0
- recurvedata/providers/dbapi/__init__.py +0 -0
- recurvedata/providers/flywheel/__init__.py +0 -0
- recurvedata/providers/mysql/__init__.py +0 -0
- recurvedata/schedulers/__init__.py +1 -0
- recurvedata/schedulers/airflow.py +974 -0
- recurvedata/schedulers/airflow_db_process.py +331 -0
- recurvedata/schedulers/airflow_operators.py +61 -0
- recurvedata/schedulers/airflow_plugin.py +9 -0
- recurvedata/schedulers/airflow_trigger_dag_patch.py +117 -0
- recurvedata/schedulers/base.py +99 -0
- recurvedata/schedulers/cli.py +228 -0
- recurvedata/schedulers/client.py +56 -0
- recurvedata/schedulers/consts.py +52 -0
- recurvedata/schedulers/debug_celery.py +62 -0
- recurvedata/schedulers/model.py +63 -0
- recurvedata/schedulers/schemas.py +97 -0
- recurvedata/schedulers/service.py +20 -0
- recurvedata/schedulers/system_dags.py +59 -0
- recurvedata/schedulers/task_status.py +279 -0
- recurvedata/schedulers/utils.py +73 -0
- recurvedata/schema/__init__.py +0 -0
- recurvedata/schema/field.py +88 -0
- recurvedata/schema/schema.py +55 -0
- recurvedata/schema/types.py +17 -0
- recurvedata/schema.py +0 -0
- recurvedata/server/__init__.py +0 -0
- recurvedata/server/app.py +7 -0
- recurvedata/server/connector/__init__.py +0 -0
- recurvedata/server/connector/api.py +79 -0
- recurvedata/server/connector/schemas.py +28 -0
- recurvedata/server/data_service/__init__.py +0 -0
- recurvedata/server/data_service/api.py +126 -0
- recurvedata/server/data_service/client.py +18 -0
- recurvedata/server/data_service/consts.py +1 -0
- recurvedata/server/data_service/schemas.py +68 -0
- recurvedata/server/data_service/service.py +218 -0
- recurvedata/server/dbt/__init__.py +0 -0
- recurvedata/server/dbt/api.py +116 -0
- recurvedata/server/error_code.py +49 -0
- recurvedata/server/exceptions.py +19 -0
- recurvedata/server/executor/__init__.py +0 -0
- recurvedata/server/executor/api.py +37 -0
- recurvedata/server/executor/schemas.py +30 -0
- recurvedata/server/executor/service.py +220 -0
- recurvedata/server/main.py +32 -0
- recurvedata/server/schedulers/__init__.py +0 -0
- recurvedata/server/schedulers/api.py +252 -0
- recurvedata/server/schedulers/schemas.py +50 -0
- recurvedata/server/schemas.py +50 -0
- recurvedata/utils/__init__.py +15 -0
- recurvedata/utils/_typer.py +61 -0
- recurvedata/utils/attrdict.py +19 -0
- recurvedata/utils/command_helper.py +20 -0
- recurvedata/utils/compat.py +12 -0
- recurvedata/utils/compression.py +203 -0
- recurvedata/utils/crontab.py +42 -0
- recurvedata/utils/crypto_util.py +305 -0
- recurvedata/utils/dataclass.py +11 -0
- recurvedata/utils/date_time.py +464 -0
- recurvedata/utils/dispatch.py +114 -0
- recurvedata/utils/email_util.py +104 -0
- recurvedata/utils/files.py +386 -0
- recurvedata/utils/helpers.py +170 -0
- recurvedata/utils/httputil.py +117 -0
- recurvedata/utils/imports.py +132 -0
- recurvedata/utils/json.py +80 -0
- recurvedata/utils/log.py +117 -0
- recurvedata/utils/log_capture.py +153 -0
- recurvedata/utils/mp.py +178 -0
- recurvedata/utils/normalizer.py +102 -0
- recurvedata/utils/redis_lock.py +474 -0
- recurvedata/utils/registry.py +54 -0
- recurvedata/utils/shell.py +15 -0
- recurvedata/utils/singleton.py +33 -0
- recurvedata/utils/sql.py +6 -0
- recurvedata/utils/timeout.py +28 -0
- recurvedata/utils/tracing.py +14 -0
- recurvedata_lib-0.1.487.dist-info/METADATA +605 -0
- recurvedata_lib-0.1.487.dist-info/RECORD +333 -0
- recurvedata_lib-0.1.487.dist-info/WHEEL +5 -0
- recurvedata_lib-0.1.487.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
copied from recurve-server
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from enum import Enum, EnumMeta
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ErrorCodeMeta(EnumMeta):
|
|
9
|
+
_error_codes = set()
|
|
10
|
+
|
|
11
|
+
def __new__(metacls, clsname, bases, classdict):
|
|
12
|
+
enum_members = {k: v for k, v in classdict.items() if not k.startswith("_")}
|
|
13
|
+
for name, code in enum_members.items():
|
|
14
|
+
if type(code) is not tuple:
|
|
15
|
+
continue
|
|
16
|
+
for error_code in metacls._error_codes:
|
|
17
|
+
if code[0] == error_code[1][0]:
|
|
18
|
+
raise ValueError(f"Error code {code[0]} in {clsname} already exists globally")
|
|
19
|
+
metacls._error_codes.add((name, code))
|
|
20
|
+
return super().__new__(metacls, clsname, bases, classdict)
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def error_codes(cls):
|
|
24
|
+
return sorted(list(cls._error_codes), key=lambda x: x[1][0])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class BaseErrorCode(Enum, metaclass=ErrorCodeMeta):
|
|
28
|
+
@property
|
|
29
|
+
def code(self):
|
|
30
|
+
return self.value[0]
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def message(self):
|
|
34
|
+
return self.value[1]
|
|
35
|
+
|
|
36
|
+
def to_dict(self):
|
|
37
|
+
return {"code": self.code, "msg": self.message}
|
|
38
|
+
|
|
39
|
+
def exception(self, data: dict | None = None):
|
|
40
|
+
from recurvedata.exceptions import RecurveException
|
|
41
|
+
|
|
42
|
+
return RecurveException(data=data, code=self)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ErrorCode(BaseErrorCode):
|
|
46
|
+
# 00: General
|
|
47
|
+
UNAUTHORIZED = ("A0001", "Unauthorized")
|
|
48
|
+
PERMISSION_DENIED = ("A0003", "Permission Denied")
|
|
49
|
+
NOT_FOUND = ("A0004", "Not Found")
|
|
50
|
+
ALREADY_EXISTS = ("A0008", "Already Exists")
|
|
51
|
+
INVALID_ARGUMENT = ("A0010", "Invalid Argument")
|
|
52
|
+
MAX_FILE_SIZE_EXCEEDED = ("A0011", "Max File Size Exceeded")
|
|
53
|
+
INVALID_FILE_FORMAT = ("A0012", "Invalid File Format")
|
|
54
|
+
INVALID_READONLY_QUERY = ("A0013", "Query Should be Read Only")
|
|
55
|
+
INTERNAL_SERVER_ERROR = ("B0001", "Internal Server Error")
|
|
56
|
+
NOT_IMPLEMENTED = ("B0002", "Not Implemented")
|
|
57
|
+
FAILED_TO_PARSE_QUERY = ("B0003", "Failed to Parse Query")
|
|
58
|
+
|
|
59
|
+
UNKNOWN_ERROR = ("D0001", "Unknown Error")
|
|
60
|
+
|
|
61
|
+
# agent task
|
|
62
|
+
API_REQUEST_FAILED = ("A1202", "API request failed")
|
|
63
|
+
MAX_RETRIES_EXCEEDED = ("A1203", "max retries exceeded")
|
|
64
|
+
TIMEOUT = ("A1204", "time out")
|
|
65
|
+
|
|
66
|
+
# data service
|
|
67
|
+
DP_FETCH_CONNECTION_FAILED = ("A1401", "DP fetch connection failed")
|
|
68
|
+
PREVIEW_DATA_FAILED = ("A1402", "Preview data failed")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
ERR = ErrorCode # shortcut
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
|
|
3
|
+
from recurvedata.error_codes import ERR, BaseErrorCode
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RecurveException(Exception):
|
|
7
|
+
_default_code: ERR = ERR.UNKNOWN_ERROR
|
|
8
|
+
|
|
9
|
+
def __init__(self, data: dict | str = None, code: BaseErrorCode = None):
|
|
10
|
+
self.code = code or self._default_code
|
|
11
|
+
self.data = data
|
|
12
|
+
|
|
13
|
+
def to_dict(self) -> dict:
|
|
14
|
+
return self.code.to_dict() | {"data": self.data}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InvalidArgument(RecurveException):
|
|
18
|
+
_default_code: ERR = ERR.INVALID_ARGUMENT
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class APIError(RecurveException):
|
|
22
|
+
"""Raised when an API request fails."""
|
|
23
|
+
|
|
24
|
+
_default_code: ERR = ERR.API_REQUEST_FAILED
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class UnauthorizedError(RecurveException):
|
|
28
|
+
"""Raised when an unauthorized request is made."""
|
|
29
|
+
|
|
30
|
+
_default_code = ERR.UNAUTHORIZED
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MaxRetriesExceededException(RecurveException):
|
|
34
|
+
"""Raised when the maximum number of retries is exceeded."""
|
|
35
|
+
|
|
36
|
+
_default_code: ERR = ERR.MAX_RETRIES_EXCEEDED
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TimeoutException(RecurveException):
|
|
40
|
+
"""Raised when a timeout occurs."""
|
|
41
|
+
|
|
42
|
+
_default_code: ERR = ERR.TIMEOUT
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class WrapRecurveException(RecurveException):
|
|
46
|
+
"""
|
|
47
|
+
raised in wrap_error function
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, code: ERR, exception: Exception, data: dict | str = None):
|
|
51
|
+
super().__init__(data=data, code=code)
|
|
52
|
+
self.exception: Exception = exception
|
|
53
|
+
|
|
54
|
+
def to_dict(self) -> dict:
|
|
55
|
+
return self.code.to_dict() | {"data": self.data, "exception": str(self.exception)}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def wrap_error(err_code: ERR):
|
|
59
|
+
def decorator(func):
|
|
60
|
+
@wraps(func)
|
|
61
|
+
def wrapper(*args, **kwargs):
|
|
62
|
+
try:
|
|
63
|
+
return func(*args, **kwargs)
|
|
64
|
+
except RecurveException:
|
|
65
|
+
raise
|
|
66
|
+
except Exception as e:
|
|
67
|
+
wrapped_error = WrapRecurveException(err_code, e)
|
|
68
|
+
raise wrapped_error
|
|
69
|
+
|
|
70
|
+
return wrapper
|
|
71
|
+
|
|
72
|
+
return decorator
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from recurvedata.executors.service.connector import ConnectionService
|
|
6
|
+
from recurvedata.executors.utils import run_with_result_handling
|
|
7
|
+
from recurvedata.utils import init_logging
|
|
8
|
+
from recurvedata.utils._typer import RecurveTyper
|
|
9
|
+
|
|
10
|
+
cli = RecurveTyper()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@cli.callback()
|
|
14
|
+
def init():
|
|
15
|
+
init_logging()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@cli.command()
|
|
19
|
+
def test_connection(
|
|
20
|
+
connection_type: str = typer.Option(
|
|
21
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
22
|
+
),
|
|
23
|
+
config: str = typer.Option(..., "--config", help="JSON string of connection configuration"),
|
|
24
|
+
result_filename: str = typer.Option(None, "--result-filename", help="Filename to save the json result"),
|
|
25
|
+
timeout: int = typer.Option(30, "--timeout", help="Timeout for the connection test in seconds"),
|
|
26
|
+
):
|
|
27
|
+
"""
|
|
28
|
+
Test if a connection is valid
|
|
29
|
+
"""
|
|
30
|
+
connection_config = json.loads(config)
|
|
31
|
+
run_with_result_handling(
|
|
32
|
+
ConnectionService.test_connection, timeout, result_filename, connection_type, connection_config
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@cli.command()
|
|
37
|
+
async def list_databases(
|
|
38
|
+
connection_type: str = typer.Option(
|
|
39
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
40
|
+
),
|
|
41
|
+
config: str = typer.Option(..., "--config", help="JSON string of connection configuration"),
|
|
42
|
+
result_filename: str = typer.Option(None, "--result-filename", help="Filename to save the json result"),
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
List databases for a given connection
|
|
46
|
+
"""
|
|
47
|
+
connection_config = json.loads(config)
|
|
48
|
+
run_with_result_handling(
|
|
49
|
+
ConnectionService.list_databases,
|
|
50
|
+
result_filename=result_filename,
|
|
51
|
+
connection_type=connection_type,
|
|
52
|
+
connection_config=connection_config,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@cli.command()
|
|
57
|
+
async def list_tables(
|
|
58
|
+
connection_type: str = typer.Option(
|
|
59
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
60
|
+
),
|
|
61
|
+
config: str = typer.Option(..., "--config", help="JSON string of connection configuration"),
|
|
62
|
+
database: str = typer.Option(..., "--database", help="Database name"),
|
|
63
|
+
result_filename: str = typer.Option(None, "--result-filename", help="Filename to save the json result"),
|
|
64
|
+
):
|
|
65
|
+
"""List tables for a given connection and database"""
|
|
66
|
+
connection_config = json.loads(config)
|
|
67
|
+
run_with_result_handling(
|
|
68
|
+
ConnectionService.list_tables,
|
|
69
|
+
result_filename=result_filename,
|
|
70
|
+
connection_type=connection_type,
|
|
71
|
+
connection_config=connection_config,
|
|
72
|
+
database=database,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@cli.command()
|
|
77
|
+
async def list_columns(
|
|
78
|
+
connection_type: str = typer.Option(
|
|
79
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
80
|
+
),
|
|
81
|
+
config: str = typer.Option(..., "--config", help="JSON string of connection configuration"),
|
|
82
|
+
database: str = typer.Option(..., "--database", help="Database name"),
|
|
83
|
+
table: str = typer.Option(..., "--table", help="Table name"),
|
|
84
|
+
result_filename: str = typer.Option(None, "--result-filename", help="Filename to save the json result"),
|
|
85
|
+
):
|
|
86
|
+
"""List columns for a given connection, database and table"""
|
|
87
|
+
connection_config = json.loads(config)
|
|
88
|
+
run_with_result_handling(
|
|
89
|
+
ConnectionService.list_columns,
|
|
90
|
+
result_filename=result_filename,
|
|
91
|
+
connection_type=connection_type,
|
|
92
|
+
connection_config=connection_config,
|
|
93
|
+
database_name=database,
|
|
94
|
+
table_name=table,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@cli.command()
|
|
99
|
+
async def list_full_databases(
|
|
100
|
+
connection_type: str = typer.Option(
|
|
101
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
102
|
+
),
|
|
103
|
+
config: str = typer.Option(..., "--config", help="JSON string of connection configuration"),
|
|
104
|
+
result_filename: str = typer.Option(None, "--result-filename", help="Filename to save the json result"),
|
|
105
|
+
):
|
|
106
|
+
"""List full databases for a given connection"""
|
|
107
|
+
connection_config = json.loads(config)
|
|
108
|
+
run_with_result_handling(
|
|
109
|
+
ConnectionService.list_full_databases,
|
|
110
|
+
result_filename=result_filename,
|
|
111
|
+
connection_type=connection_type,
|
|
112
|
+
connection_config=connection_config,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == "__main__":
|
|
117
|
+
cli()
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from recurvedata.client.server_client import ServerDbtClient
|
|
4
|
+
from recurvedata.core.tracing import Tracing
|
|
5
|
+
from recurvedata.executors.cli import parameters as param
|
|
6
|
+
from recurvedata.executors.utils import run_with_result_handling
|
|
7
|
+
from recurvedata.utils import init_logging
|
|
8
|
+
from recurvedata.utils._typer import RecurveTyper
|
|
9
|
+
from recurvedata.utils.sql import trim_replace_special_character
|
|
10
|
+
|
|
11
|
+
dbt_tracer = Tracing()
|
|
12
|
+
cli = RecurveTyper()
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@cli.callback()
|
|
17
|
+
def init():
|
|
18
|
+
from recurvedata.core.tracing import Tracing
|
|
19
|
+
|
|
20
|
+
if not Tracing.is_instantiated():
|
|
21
|
+
from recurvedata.utils.tracing import create_dp_tracer
|
|
22
|
+
|
|
23
|
+
create_dp_tracer("recurve-lib-dbt")
|
|
24
|
+
init_logging()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@cli.command()
|
|
28
|
+
@dbt_tracer.create_span(context_payload_name="tracing_context")
|
|
29
|
+
async def compile(
|
|
30
|
+
project_id: int = param.project_id,
|
|
31
|
+
alias: str = param.alias,
|
|
32
|
+
sql: str = param.sql,
|
|
33
|
+
tracing_context: str = param.tracing_context,
|
|
34
|
+
force_regenerate_dir: bool = param.force_regenerate_dir,
|
|
35
|
+
result_filename: str = param.result_filename,
|
|
36
|
+
):
|
|
37
|
+
try:
|
|
38
|
+
_compile_using_server(project_id, alias, sql, force_regenerate_dir, result_filename)
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.exception(f"_compile_using_server failed: {e}, try _compile_using_service")
|
|
41
|
+
_compile_using_service(project_id, alias, sql, force_regenerate_dir, result_filename)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dbt_tracer.create_span()
|
|
45
|
+
def _compile_using_server(project_id: int, alias: str, sql: str, force_regenerate_dir: bool, result_filename: str):
|
|
46
|
+
client = ServerDbtClient()
|
|
47
|
+
res = client.compile(project_id, sql, alias, force_regenerate_dir)
|
|
48
|
+
if result_filename:
|
|
49
|
+
res.model_dump_json_file(result_filename)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dbt_tracer.create_span()
|
|
53
|
+
def _compile_using_service(
|
|
54
|
+
project_id: int, alias: str, sql: str, force_regenerate_dir: bool, result_filename: str = param.result_filename
|
|
55
|
+
):
|
|
56
|
+
from recurvedata.dbt.service import DbtService
|
|
57
|
+
|
|
58
|
+
sql = trim_replace_special_character(sql)
|
|
59
|
+
service = DbtService(
|
|
60
|
+
project_id=project_id,
|
|
61
|
+
project_connection_name=alias,
|
|
62
|
+
force_regenerate_dir=force_regenerate_dir,
|
|
63
|
+
need_fetch_variable=True,
|
|
64
|
+
)
|
|
65
|
+
run_with_result_handling(service.compile, inline_sql=sql, result_filename=result_filename)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@cli.command()
|
|
69
|
+
async def preview(
|
|
70
|
+
project_id: int = param.project_id,
|
|
71
|
+
alias: str = param.alias,
|
|
72
|
+
sql: str = param.sql,
|
|
73
|
+
limit: int = param.limit,
|
|
74
|
+
no_data: bool = param.no_data,
|
|
75
|
+
force_regenerate_dir: bool = param.force_regenerate_dir,
|
|
76
|
+
result_filename: str = param.result_filename,
|
|
77
|
+
):
|
|
78
|
+
try:
|
|
79
|
+
_preview_using_server(project_id, alias, sql, limit, force_regenerate_dir, result_filename) # todo: add no_data
|
|
80
|
+
except Exception as e:
|
|
81
|
+
logger.exception(f"_preview_using_server failed: {e}, try _preview_using_service")
|
|
82
|
+
_preview_using_service(project_id, alias, sql, limit, force_regenerate_dir, no_data, result_filename)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _preview_using_server(
|
|
86
|
+
project_id: int, alias: str, sql: str, limit: int, force_regenerate_dir: bool, result_filename: str
|
|
87
|
+
):
|
|
88
|
+
client = ServerDbtClient()
|
|
89
|
+
res = client.preview(project_id, sql, alias, limit, force_regenerate_dir)
|
|
90
|
+
if result_filename:
|
|
91
|
+
res.model_dump_json_file(result_filename)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _preview_using_service(
|
|
95
|
+
project_id: int,
|
|
96
|
+
alias: str,
|
|
97
|
+
sql: str,
|
|
98
|
+
limit: int,
|
|
99
|
+
force_regenerate_dir: bool,
|
|
100
|
+
no_data: bool,
|
|
101
|
+
result_filename: str = param.result_filename,
|
|
102
|
+
):
|
|
103
|
+
from recurvedata.dbt.service import DbtService
|
|
104
|
+
|
|
105
|
+
sql = trim_replace_special_character(sql, strip_sufix=True)
|
|
106
|
+
service = DbtService(
|
|
107
|
+
project_id=project_id,
|
|
108
|
+
project_connection_name=alias,
|
|
109
|
+
force_regenerate_dir=force_regenerate_dir,
|
|
110
|
+
need_fetch_variable=True,
|
|
111
|
+
)
|
|
112
|
+
run_with_result_handling(
|
|
113
|
+
service.preview, inline_sql=sql, limit=limit, result_filename=result_filename, no_data=no_data
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
cli()
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from recurvedata.consts import ScheduleType
|
|
4
|
+
from recurvedata.executors.cli.connector import cli as connector_cli
|
|
5
|
+
from recurvedata.executors.cli.dbt import cli as dbt_cli
|
|
6
|
+
from recurvedata.executors.debug_executor import DebugExecutor
|
|
7
|
+
from recurvedata.executors.executor import Executor
|
|
8
|
+
from recurvedata.utils import init_logging
|
|
9
|
+
from recurvedata.utils._typer import RecurveTyper
|
|
10
|
+
from recurvedata.utils.date_time import astimezone
|
|
11
|
+
|
|
12
|
+
cli = RecurveTyper()
|
|
13
|
+
cli.add_typer(connector_cli, name="connector")
|
|
14
|
+
cli.add_typer(dbt_cli, name="dbt")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@cli.callback()
|
|
18
|
+
def init():
|
|
19
|
+
from recurvedata.core.tracing import Tracing
|
|
20
|
+
|
|
21
|
+
if not Tracing.is_instantiated():
|
|
22
|
+
from recurvedata.utils.tracing import create_dp_tracer
|
|
23
|
+
|
|
24
|
+
create_dp_tracer("recurve-lib")
|
|
25
|
+
init_logging()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@cli.command()
|
|
29
|
+
def execute(
|
|
30
|
+
dag_slug: str = typer.Option(..., "--dag_slug", help="Unique identifier for the DAG"),
|
|
31
|
+
node_slug: str = typer.Option(..., "--node_slug", help="Unique identifier for the node"),
|
|
32
|
+
execution_date: str = typer.Option(..., "--execution_date", help="Date/time of execution"),
|
|
33
|
+
# RecurveLink settings
|
|
34
|
+
link_workflow_id: int = typer.Option(None, "--link_workflow_id", help="ID of linked workflow"),
|
|
35
|
+
link_node_id: int = typer.Option(None, "--link_node_id", help="ID of linked node"),
|
|
36
|
+
is_link_workflow: bool = typer.Option(False, "--is_link_workflow", help="Whether this is a linked workflow"),
|
|
37
|
+
):
|
|
38
|
+
"""
|
|
39
|
+
Execute a specific node in a DAG at the given execution date.
|
|
40
|
+
|
|
41
|
+
Optionally configure workflow linking settings.
|
|
42
|
+
"""
|
|
43
|
+
# Initialize and run the executor
|
|
44
|
+
executor = Executor(dag_slug=dag_slug, node_slug=node_slug, execution_date=execution_date)
|
|
45
|
+
executor.set_link_settings(
|
|
46
|
+
link_workflow_id=link_workflow_id, link_node_id=link_node_id, is_link_workflow=is_link_workflow
|
|
47
|
+
)
|
|
48
|
+
executor.run()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@cli.command()
|
|
52
|
+
def debug(
|
|
53
|
+
workflow_id: int = typer.Option(..., "--workflow_id", help="ID of the workflow to debug"),
|
|
54
|
+
node_key: str = typer.Option(..., "--node_key", help="Key identifier of the node to debug"),
|
|
55
|
+
schedule_type: ScheduleType = typer.Option(..., "--schedule_type", help="Type of schedule"),
|
|
56
|
+
schedule_interval: str = typer.Option(..., "--schedule_interval", help="Schedule interval specification"),
|
|
57
|
+
execution_date: str = typer.Option(..., "--execution_date", help="Execution timestamp"),
|
|
58
|
+
timezone: str = typer.Option(..., "--timezone", help="Timezone for execution"),
|
|
59
|
+
celery_task_id: str = typer.Option(..., "--celery_task_id", help="Celery task ID for tracking"),
|
|
60
|
+
):
|
|
61
|
+
"""
|
|
62
|
+
Debug a workflow node by executing it in isolation.
|
|
63
|
+
|
|
64
|
+
This command allows debugging a specific node from a workflow by running it independently.
|
|
65
|
+
The execution context (schedule, timing, etc) can be controlled via the parameters.
|
|
66
|
+
"""
|
|
67
|
+
# execution_date = ensure_datetime(execution_date).replace(tzinfo=ensure_tz(timezone))
|
|
68
|
+
execution_date = astimezone(execution_date, timezone)
|
|
69
|
+
executor = DebugExecutor(
|
|
70
|
+
workflow_id=workflow_id,
|
|
71
|
+
node_key=node_key,
|
|
72
|
+
schedule_type=schedule_type,
|
|
73
|
+
schedule_interval=schedule_interval,
|
|
74
|
+
execution_date=execution_date,
|
|
75
|
+
timezone=timezone,
|
|
76
|
+
celery_task_id=celery_task_id,
|
|
77
|
+
)
|
|
78
|
+
executor.run()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
cli()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typer import Option
|
|
2
|
+
|
|
3
|
+
connection_type = Option(
|
|
4
|
+
..., "--connection-type", help="Type of the connection (e.g., 'mysql', 'postgresql', 'snowflake')"
|
|
5
|
+
)
|
|
6
|
+
connection_config = Option(..., "--config", help="JSON string of connection configuration")
|
|
7
|
+
result_filename = Option(None, "--result-filename", help="Filename to save the json result")
|
|
8
|
+
timeout = Option(30, "--timeout", help="Timeout for the connection test in seconds")
|
|
9
|
+
database = Option(..., "--database", help="Database name")
|
|
10
|
+
table = Option(..., "--table", help="Table name")
|
|
11
|
+
project_id = Option(..., "--project-id", help="Project ID")
|
|
12
|
+
connection_name = Option(..., "--connection-name", help="Connection Name")
|
|
13
|
+
alias = Option(..., "--alias", help="Alias") # project connection name
|
|
14
|
+
limit = Option(100, "--limit")
|
|
15
|
+
sql = Option(..., "--sql")
|
|
16
|
+
tracing_context = Option(None, "--tracing-context", help="Tracing context")
|
|
17
|
+
force_regenerate_dir = Option(False, "--force-regenerate-dir", help="Whether to force regenerate dbt project")
|
|
18
|
+
no_data = Option(False, "--no-data", help="Whether to include data in preview result")
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from recurvedata.client import Client
|
|
5
|
+
from recurvedata.config import RECURVE_EXECUTOR_PYENV_NAME
|
|
6
|
+
from recurvedata.consts import ETLExecutionStatus, Operator
|
|
7
|
+
from recurvedata.executors.schemas import (
|
|
8
|
+
ConnectionItem,
|
|
9
|
+
DebugEnd,
|
|
10
|
+
DebugLogRecord,
|
|
11
|
+
DebugStart,
|
|
12
|
+
JobNodeItem,
|
|
13
|
+
TaskInstanceEnd,
|
|
14
|
+
TaskInstanceStart,
|
|
15
|
+
TaskInstanceStartResponse,
|
|
16
|
+
TaskLogRecord,
|
|
17
|
+
WorkflowNodeItem,
|
|
18
|
+
)
|
|
19
|
+
from recurvedata.utils import get_env_id
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ExecutorClient(Client):
|
|
23
|
+
def get_node(self, job_id: int, node_id: int) -> JobNodeItem:
|
|
24
|
+
params = {
|
|
25
|
+
"env_id": get_env_id(),
|
|
26
|
+
"job_id": job_id,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return self.request(
|
|
30
|
+
"GET", path=f"/api/executor/node/{node_id}", response_model_class=JobNodeItem, params=params
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def get_connection(self, project_id: int, connection_name: str) -> ConnectionItem:
|
|
34
|
+
params = {
|
|
35
|
+
"env_id": get_env_id(),
|
|
36
|
+
"name": connection_name,
|
|
37
|
+
"project_id": project_id,
|
|
38
|
+
}
|
|
39
|
+
return self.request("GET", path="/api/executor/connection", response_model_class=ConnectionItem, params=params)
|
|
40
|
+
|
|
41
|
+
def task_instance_start(
|
|
42
|
+
self,
|
|
43
|
+
job_id: int,
|
|
44
|
+
node_id: int,
|
|
45
|
+
operator: Operator,
|
|
46
|
+
task: str,
|
|
47
|
+
execution_date: datetime.datetime,
|
|
48
|
+
rendered_config: dict,
|
|
49
|
+
start_time: datetime.datetime,
|
|
50
|
+
hostname: Optional[str],
|
|
51
|
+
pid: Optional[int],
|
|
52
|
+
):
|
|
53
|
+
payload = TaskInstanceStart(
|
|
54
|
+
job_id=job_id,
|
|
55
|
+
node_id=node_id,
|
|
56
|
+
task=task,
|
|
57
|
+
operator=operator,
|
|
58
|
+
execution_date=execution_date.isoformat(),
|
|
59
|
+
rendered_config=rendered_config,
|
|
60
|
+
start_time=start_time.isoformat(),
|
|
61
|
+
hostname=hostname,
|
|
62
|
+
pid=pid,
|
|
63
|
+
).model_dump()
|
|
64
|
+
params = {
|
|
65
|
+
"env_id": get_env_id(),
|
|
66
|
+
}
|
|
67
|
+
return self.request(
|
|
68
|
+
"POST",
|
|
69
|
+
path="/api/executor/start",
|
|
70
|
+
response_model_class=TaskInstanceStartResponse,
|
|
71
|
+
params=params,
|
|
72
|
+
json=payload,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def task_instance_end(
|
|
76
|
+
self,
|
|
77
|
+
meta: Any,
|
|
78
|
+
traceback: Any,
|
|
79
|
+
status: ETLExecutionStatus,
|
|
80
|
+
end_time: datetime.datetime,
|
|
81
|
+
execution_date: datetime.datetime,
|
|
82
|
+
job_id: int,
|
|
83
|
+
node_id: int,
|
|
84
|
+
run_id: str,
|
|
85
|
+
current_retry_number: Optional[int],
|
|
86
|
+
max_retry_number: Optional[int],
|
|
87
|
+
link_workflow_id: Optional[int],
|
|
88
|
+
link_node_id: Optional[int],
|
|
89
|
+
data_interval_end: Optional[str],
|
|
90
|
+
**kwargs,
|
|
91
|
+
):
|
|
92
|
+
payload = TaskInstanceEnd(
|
|
93
|
+
job_id=job_id,
|
|
94
|
+
node_id=node_id,
|
|
95
|
+
run_id=run_id,
|
|
96
|
+
end_time=end_time.isoformat(),
|
|
97
|
+
execution_date=execution_date.isoformat(),
|
|
98
|
+
meta=meta,
|
|
99
|
+
traceback=traceback,
|
|
100
|
+
status=status,
|
|
101
|
+
current_retry_number=current_retry_number,
|
|
102
|
+
max_retry_number=max_retry_number,
|
|
103
|
+
link_workflow_id=link_workflow_id,
|
|
104
|
+
link_node_id=link_node_id,
|
|
105
|
+
data_interval_end=data_interval_end,
|
|
106
|
+
).model_dump()
|
|
107
|
+
params = {
|
|
108
|
+
"env_id": get_env_id(),
|
|
109
|
+
}
|
|
110
|
+
return self.request(
|
|
111
|
+
"POST",
|
|
112
|
+
path="/api/executor/end",
|
|
113
|
+
params=params,
|
|
114
|
+
json=payload,
|
|
115
|
+
timeout=10, # todo: backend process time is slow, dispatch still wait
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def get_workflow_node(self, workflow_id: int, node_id: int) -> WorkflowNodeItem:
|
|
119
|
+
params = {
|
|
120
|
+
"env_id": get_env_id(),
|
|
121
|
+
"workflow_id": workflow_id,
|
|
122
|
+
}
|
|
123
|
+
return self.request(
|
|
124
|
+
"GET", path=f"/api/executor/workflow_node/{node_id}", response_model_class=WorkflowNodeItem, params=params
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def send_back_logs(self, record: TaskLogRecord):
|
|
128
|
+
params = {
|
|
129
|
+
"env_id": get_env_id(),
|
|
130
|
+
}
|
|
131
|
+
return self.request("POST", path="/api/executor/logs", params=params, json={"records": [record.model_dump()]})
|
|
132
|
+
|
|
133
|
+
def send_back_debug_logs(self, record: DebugLogRecord):
|
|
134
|
+
params = {
|
|
135
|
+
"env_id": get_env_id(),
|
|
136
|
+
}
|
|
137
|
+
return self.request(
|
|
138
|
+
"POST", path="/api/executor/debug_logs", params=params, json={"records": [record.model_dump()]}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def get_debug_node(self, workflow_id: int, node_key: str) -> WorkflowNodeItem:
|
|
142
|
+
params = {
|
|
143
|
+
"env_id": get_env_id(),
|
|
144
|
+
"node_key": node_key,
|
|
145
|
+
}
|
|
146
|
+
return self.request(
|
|
147
|
+
"GET", path=f"/api/executor/debug_node/{workflow_id}", response_model_class=WorkflowNodeItem, params=params
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def debug_start(self, workflow_id: int, node_key: str, celery_task_id: str):
|
|
151
|
+
payload = DebugStart(workflow_id=workflow_id, node_key=node_key, celery_task_id=celery_task_id).model_dump()
|
|
152
|
+
params = {
|
|
153
|
+
"env_id": get_env_id(),
|
|
154
|
+
}
|
|
155
|
+
return self.request(
|
|
156
|
+
"POST",
|
|
157
|
+
path="/api/executor/debug_start",
|
|
158
|
+
params=params,
|
|
159
|
+
json=payload,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
def debug_end(self, workflow_id: int, node_key: str, celery_task_id: str, is_success: bool):
|
|
163
|
+
payload = DebugEnd(
|
|
164
|
+
workflow_id=workflow_id, node_key=node_key, celery_task_id=celery_task_id, is_success=is_success
|
|
165
|
+
).model_dump()
|
|
166
|
+
params = {
|
|
167
|
+
"env_id": get_env_id(),
|
|
168
|
+
}
|
|
169
|
+
return self.request(
|
|
170
|
+
"POST",
|
|
171
|
+
path="/api/executor/debug_end",
|
|
172
|
+
params=params,
|
|
173
|
+
json=payload,
|
|
174
|
+
timeout=10,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def get_py_conn_configs(
|
|
178
|
+
self,
|
|
179
|
+
conn_type: str = "python",
|
|
180
|
+
pyenv_name: str = RECURVE_EXECUTOR_PYENV_NAME,
|
|
181
|
+
project_conn_name: str = "",
|
|
182
|
+
project_id: int = 0,
|
|
183
|
+
) -> dict:
|
|
184
|
+
params = {
|
|
185
|
+
"conn_type": conn_type,
|
|
186
|
+
"pyenv_name": pyenv_name,
|
|
187
|
+
"project_conn_name": project_conn_name,
|
|
188
|
+
"project_id": project_id,
|
|
189
|
+
}
|
|
190
|
+
return self.request("GET", path="/api/executor/python-conn-configs", params=params)
|