mage-ai 0.9.75__py3-none-any.whl → 0.9.77__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 mage-ai might be problematic. Click here for more details.
- mage_ai/api/policies/PipelineSchedulePolicy.py +1 -0
- mage_ai/api/presenters/PipelineSchedulePresenter.py +11 -2
- mage_ai/api/resources/GitFileResource.py +8 -0
- mage_ai/api/resources/PipelineScheduleResource.py +11 -3
- mage_ai/api/resources/PipelineTriggerResource.py +3 -1
- mage_ai/api/resources/SessionResource.py +2 -2
- mage_ai/api/resources/SyncResource.py +1 -1
- mage_ai/api/resources/UserResource.py +1 -1
- mage_ai/cli/main.py +6 -1
- mage_ai/data_integrations/destinations/constants.py +2 -0
- mage_ai/data_integrations/sources/constants.py +2 -0
- mage_ai/data_preparation/executors/block_executor.py +8 -3
- mage_ai/data_preparation/executors/pipeline_executor.py +35 -19
- mage_ai/data_preparation/models/block/__init__.py +29 -23
- mage_ai/data_preparation/models/block/dbt/dbt_adapter.py +20 -8
- mage_ai/data_preparation/models/block/dynamic/constants.py +0 -1
- mage_ai/data_preparation/models/block/dynamic/counter.py +1 -3
- mage_ai/data_preparation/models/block/outputs.py +1 -1
- mage_ai/data_preparation/models/block/r/__init__.py +16 -5
- mage_ai/data_preparation/models/block/sql/__init__.py +2 -0
- mage_ai/data_preparation/models/block/sql/mssql.py +8 -0
- mage_ai/data_preparation/models/block/sql/utils/shared.py +6 -2
- mage_ai/data_preparation/models/constants.py +3 -0
- mage_ai/data_preparation/models/pipeline.py +1 -1
- mage_ai/data_preparation/storage/local_storage.py +4 -1
- mage_ai/data_preparation/templates/constants.py +7 -0
- mage_ai/data_preparation/templates/data_loaders/airtable.py +28 -0
- mage_ai/data_preparation/templates/repo/io_config.yaml +2 -0
- mage_ai/io/airtable.py +104 -0
- mage_ai/io/base.py +1 -0
- mage_ai/io/bigquery.py +36 -0
- mage_ai/io/config.py +6 -0
- mage_ai/io/mssql.py +21 -9
- mage_ai/io/mysql.py +6 -1
- mage_ai/io/postgres.py +3 -0
- mage_ai/io/redshift.py +13 -0
- mage_ai/io/sql.py +1 -0
- mage_ai/orchestration/db/__init__.py +20 -0
- mage_ai/orchestration/db/migrations/versions/39d36f1dab73_create_genericjob.py +47 -0
- mage_ai/orchestration/db/models/oauth.py +2 -1
- mage_ai/orchestration/db/models/schedules.py +107 -5
- mage_ai/orchestration/db/models/secrets.py +11 -1
- mage_ai/orchestration/job_manager.py +19 -0
- mage_ai/orchestration/metrics/pipeline_run.py +1 -1
- mage_ai/orchestration/notification/sender.py +2 -2
- mage_ai/orchestration/pipeline_scheduler_original.py +150 -6
- mage_ai/orchestration/pipeline_scheduler_project_platform.py +4 -5
- mage_ai/orchestration/queue/config.py +11 -1
- mage_ai/orchestration/queue/process_queue.py +2 -0
- mage_ai/orchestration/utils/distributed_lock.py +8 -1
- mage_ai/server/api/base.py +41 -0
- mage_ai/server/api/constants.py +1 -0
- mage_ai/server/api/triggers.py +9 -0
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-782dd4a6b13e1c42.js +2 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{webpack-0bc44da590c7cf85.js → webpack-b9a067f3bd0a3a05.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/{38-PtskJFUTYUpRhT1qF_ → qR0jauUABqPaFMjUsYeoG}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist/block-layout.html +2 -2
- mage_ai/server/frontend_dist/compute.html +2 -2
- mage_ai/server/frontend_dist/files.html +2 -2
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-data-products.html +2 -2
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/files.html +2 -2
- mage_ai/server/frontend_dist/manage/overview.html +2 -2
- mage_ai/server/frontend_dist/manage/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist/manage/settings.html +2 -2
- mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist/manage/users.html +2 -2
- mage_ai/server/frontend_dist/manage.html +2 -2
- mage_ai/server/frontend_dist/oauth.html +3 -3
- mage_ai/server/frontend_dist/overview.html +2 -2
- mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist/pipelines.html +2 -2
- mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist/settings.html +2 -2
- mage_ai/server/frontend_dist/sign-in.html +5 -5
- mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist/templates.html +2 -2
- mage_ai/server/frontend_dist/terminal.html +2 -2
- mage_ai/server/frontend_dist/test.html +2 -2
- mage_ai/server/frontend_dist/triggers.html +2 -2
- mage_ai/server/frontend_dist/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist/v2.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-ee5e328aaf51c698.js +2 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-12ad70eb5c31aa92.js → webpack-5f4be622608d9267.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/{dxnSzgIvSG4Ke5LM-tPQX → iCySon3_GCldnbC5U7C-s}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/compute.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/overview.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/oauth.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/test.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/v2.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
- mage_ai/server/scheduler_manager.py +2 -0
- mage_ai/server/terminal_server.py +3 -0
- mage_ai/settings/server.py +4 -0
- mage_ai/streaming/sources/kafka.py +2 -1
- mage_ai/tests/data_preparation/executors/test_block_executor.py +3 -3
- mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +1 -3
- mage_ai/tests/data_preparation/models/test_variable.py +2 -0
- mage_ai/tests/io/create_table/test_postgresql.py +3 -2
- mage_ai/tests/orchestration/notification/test_sender.py +5 -1
- mage_ai/tests/streaming/sources/test_kafka.py +2 -2
- mage_ai/usage_statistics/logger.py +99 -15
- mage_ai-0.9.77.dist-info/METADATA +356 -0
- {mage_ai-0.9.75.dist-info → mage_ai-0.9.77.dist-info}/RECORD +211 -208
- {mage_ai-0.9.75.dist-info → mage_ai-0.9.77.dist-info}/WHEEL +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/449-f689774546860ca4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-13bf3b7dcef50c29.js +0 -2
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-b99379d0aa6a8c25.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-e51cd04bd4d1fffe.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-0abf8a1b7243f93b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-38187954b6ec4b40.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-3ee783f5139c76a1.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/449-f689774546860ca4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-0392ef723ea2c6f8.js +0 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-b99379d0aa6a8c25.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-e51cd04bd4d1fffe.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-0abf8a1b7243f93b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-38187954b6ec4b40.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-3ee783f5139c76a1.js +0 -1
- mage_ai-0.9.75.dist-info/METADATA +0 -377
- /mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-13bf3b7dcef50c29.js.LICENSE.txt → _app-782dd4a6b13e1c42.js.LICENSE.txt} +0 -0
- /mage_ai/server/frontend_dist/_next/static/{38-PtskJFUTYUpRhT1qF_ → qR0jauUABqPaFMjUsYeoG}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-0392ef723ea2c6f8.js.LICENSE.txt → _app-ee5e328aaf51c698.js.LICENSE.txt} +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{dxnSzgIvSG4Ke5LM-tPQX → iCySon3_GCldnbC5U7C-s}/_ssgManifest.js +0 -0
- {mage_ai-0.9.75.dist-info → mage_ai-0.9.77.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.75.dist-info → mage_ai-0.9.77.dist-info/licenses}/LICENSE +0 -0
- {mage_ai-0.9.75.dist-info → mage_ai-0.9.77.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,7 @@ class JobType(StrEnum):
|
|
|
8
8
|
BLOCK_RUN = 'block_run'
|
|
9
9
|
PIPELINE_RUN = 'pipeline_run'
|
|
10
10
|
INTEGRATION_STREAM = 'integration_stream'
|
|
11
|
+
GENERIC_JOB = 'generic_job'
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class JobManager:
|
|
@@ -62,6 +63,19 @@ class JobManager:
|
|
|
62
63
|
logging_tags=logging_tags,
|
|
63
64
|
)
|
|
64
65
|
|
|
66
|
+
def has_generic_job(
|
|
67
|
+
self,
|
|
68
|
+
generic_job_id: int,
|
|
69
|
+
logger=None,
|
|
70
|
+
logging_tags: Dict = None,
|
|
71
|
+
) -> bool:
|
|
72
|
+
job_id = self.__job_id(JobType.GENERIC_JOB, generic_job_id)
|
|
73
|
+
return self.queue.has_job(
|
|
74
|
+
job_id,
|
|
75
|
+
logger=logger,
|
|
76
|
+
logging_tags=logging_tags,
|
|
77
|
+
)
|
|
78
|
+
|
|
65
79
|
def kill_block_run_job(self, block_run_id):
|
|
66
80
|
print(f'Kill block run id: {block_run_id}')
|
|
67
81
|
job_id = self.__job_id(JobType.BLOCK_RUN, block_run_id)
|
|
@@ -78,6 +92,11 @@ class JobManager:
|
|
|
78
92
|
job_id = self.__job_id(JobType.INTEGRATION_STREAM, id)
|
|
79
93
|
return self.queue.kill_job(job_id)
|
|
80
94
|
|
|
95
|
+
def kill_generic_job(self, generic_job_id):
|
|
96
|
+
print(f'Kill generic job id: {generic_job_id}')
|
|
97
|
+
job_id = self.__job_id(JobType.GENERIC_JOB, generic_job_id)
|
|
98
|
+
return self.queue.kill_job(job_id)
|
|
99
|
+
|
|
81
100
|
def start(self):
|
|
82
101
|
self.queue.start()
|
|
83
102
|
|
|
@@ -220,7 +220,7 @@ def __calculate_metrics(pipeline_run: PipelineRun, pipeline) -> Dict:
|
|
|
220
220
|
|
|
221
221
|
pipeline_metrics_by_stream = {}
|
|
222
222
|
pipeline_logs_by_stream = {}
|
|
223
|
-
pipeline_logs = pipeline_run.logs['content'].split('\n')
|
|
223
|
+
pipeline_logs = pipeline_run.logs[0]['content'].split('\n')
|
|
224
224
|
for pipeline_log in pipeline_logs:
|
|
225
225
|
tags = parse_line(pipeline_log)
|
|
226
226
|
stream = tags.get('stream')
|
|
@@ -69,7 +69,7 @@ class NotificationSender:
|
|
|
69
69
|
|
|
70
70
|
if self.config.teams_config is not None and self.config.teams_config.is_valid:
|
|
71
71
|
try:
|
|
72
|
-
send_teams_message(self.config.teams_config, summary)
|
|
72
|
+
send_teams_message(self.config.teams_config, summary, title)
|
|
73
73
|
except Exception:
|
|
74
74
|
traceback.print_exc()
|
|
75
75
|
|
|
@@ -87,7 +87,7 @@ class NotificationSender:
|
|
|
87
87
|
|
|
88
88
|
if self.config.google_chat_config is not None and self.config.google_chat_config.is_valid:
|
|
89
89
|
try:
|
|
90
|
-
send_google_chat_message(self.config.google_chat_config, summary)
|
|
90
|
+
send_google_chat_message(self.config.google_chat_config, summary, title)
|
|
91
91
|
except Exception:
|
|
92
92
|
traceback.print_exc()
|
|
93
93
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import collections
|
|
3
2
|
import os
|
|
4
3
|
import traceback
|
|
@@ -33,6 +32,7 @@ from mage_ai.orchestration.db.models.schedules import (
|
|
|
33
32
|
Backfill,
|
|
34
33
|
BlockRun,
|
|
35
34
|
EventMatcher,
|
|
35
|
+
GenericJob,
|
|
36
36
|
PipelineRun,
|
|
37
37
|
PipelineSchedule,
|
|
38
38
|
)
|
|
@@ -260,7 +260,7 @@ class PipelineScheduler:
|
|
|
260
260
|
pipeline=self.pipeline,
|
|
261
261
|
pipeline_run=self.pipeline_run,
|
|
262
262
|
)
|
|
263
|
-
|
|
263
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
264
264
|
|
|
265
265
|
self.logger_manager.output_logs_to_destination()
|
|
266
266
|
|
|
@@ -339,7 +339,7 @@ class PipelineScheduler:
|
|
|
339
339
|
error_msg: str,
|
|
340
340
|
status=PipelineRun.PipelineRunStatus.FAILED,
|
|
341
341
|
) -> None:
|
|
342
|
-
|
|
342
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
343
343
|
|
|
344
344
|
if status == PipelineRun.PipelineRunStatus.FAILED:
|
|
345
345
|
# Only send notification when pipeline run status is FAILED
|
|
@@ -929,6 +929,81 @@ class PipelineScheduler:
|
|
|
929
929
|
self.memory_usage_failure(tags=tags)
|
|
930
930
|
|
|
931
931
|
|
|
932
|
+
def on_pipeline_run_cancelled(
|
|
933
|
+
job_id: int,
|
|
934
|
+
pipeline_run_id: int,
|
|
935
|
+
cancelled_block_run_ids: List,
|
|
936
|
+
):
|
|
937
|
+
job = GenericJob.query.get(job_id)
|
|
938
|
+
if job.status not in [
|
|
939
|
+
GenericJob.JobStatus.INITIAL,
|
|
940
|
+
GenericJob.JobStatus.QUEUED,
|
|
941
|
+
GenericJob.JobStatus.RUNNING,
|
|
942
|
+
]:
|
|
943
|
+
return
|
|
944
|
+
job.mark_running()
|
|
945
|
+
|
|
946
|
+
if not pipeline_run_id:
|
|
947
|
+
job.mark_failed(
|
|
948
|
+
metadata=dict(
|
|
949
|
+
error_message='Pipeline run id is not provided in the job.',
|
|
950
|
+
),
|
|
951
|
+
)
|
|
952
|
+
return
|
|
953
|
+
if not cancelled_block_run_ids:
|
|
954
|
+
job.mark_failed(
|
|
955
|
+
metadata=dict(
|
|
956
|
+
error_message='Cancelled block run ids are not provided in the job.',
|
|
957
|
+
),
|
|
958
|
+
)
|
|
959
|
+
return
|
|
960
|
+
|
|
961
|
+
try:
|
|
962
|
+
# Run callback blocks for cancelled block runs
|
|
963
|
+
pipeline_run = PipelineRun.query.get(pipeline_run_id)
|
|
964
|
+
if not pipeline_run:
|
|
965
|
+
raise Exception(f'Fail to retrieve pipeline run with id {pipeline_run_id}')
|
|
966
|
+
pipeline_schedule = pipeline_run.pipeline_schedule
|
|
967
|
+
pipeline = get_pipeline_from_platform(
|
|
968
|
+
pipeline_run.pipeline_uuid,
|
|
969
|
+
repo_path=pipeline_schedule.repo_path if pipeline_schedule else None,
|
|
970
|
+
)
|
|
971
|
+
if pipeline_run.status != PipelineRun.PipelineRunStatus.CANCELLED:
|
|
972
|
+
job.mark_failed(
|
|
973
|
+
metadata=dict(
|
|
974
|
+
error_message=f'Pipeline run {pipeline_run_id} is not in cancelled status.',
|
|
975
|
+
),
|
|
976
|
+
)
|
|
977
|
+
return
|
|
978
|
+
for block_run_id in cancelled_block_run_ids:
|
|
979
|
+
block_run = BlockRun.query.get(block_run_id)
|
|
980
|
+
if not block_run:
|
|
981
|
+
continue
|
|
982
|
+
if block_run.status != BlockRun.BlockRunStatus.CANCELLED:
|
|
983
|
+
continue
|
|
984
|
+
ExecutorFactory.get_block_executor(
|
|
985
|
+
pipeline,
|
|
986
|
+
block_run.block_uuid,
|
|
987
|
+
block_run_id=block_run.id,
|
|
988
|
+
execution_partition=pipeline_run.execution_partition,
|
|
989
|
+
executor_type=ExecutorType.LOCAL_PYTHON,
|
|
990
|
+
).execute_callback(
|
|
991
|
+
callback='on_cancelled',
|
|
992
|
+
global_vars=pipeline_run.get_variables(),
|
|
993
|
+
logging_tags=None,
|
|
994
|
+
pipeline_run=pipeline_run,
|
|
995
|
+
block_run_id=block_run_id,
|
|
996
|
+
)
|
|
997
|
+
except Exception as e:
|
|
998
|
+
job.mark_failed(
|
|
999
|
+
metadata=dict(
|
|
1000
|
+
error_message=f'Failed to run pipeline run cancellation hook: {e}.',
|
|
1001
|
+
),
|
|
1002
|
+
)
|
|
1003
|
+
return
|
|
1004
|
+
job.mark_completed()
|
|
1005
|
+
|
|
1006
|
+
|
|
932
1007
|
def run_integration_streams(
|
|
933
1008
|
streams: List[Dict],
|
|
934
1009
|
*args,
|
|
@@ -1372,7 +1447,7 @@ def stop_pipeline_run(
|
|
|
1372
1447
|
# Update pipeline run status to cancelled
|
|
1373
1448
|
pipeline_run.update(status=status)
|
|
1374
1449
|
|
|
1375
|
-
|
|
1450
|
+
UsageStatisticLogger().pipeline_run_ended_sync(pipeline_run)
|
|
1376
1451
|
|
|
1377
1452
|
# Cancel all the block runs
|
|
1378
1453
|
cancel_block_runs_and_jobs(pipeline_run, pipeline)
|
|
@@ -1407,8 +1482,9 @@ def cancel_block_runs_and_jobs(
|
|
|
1407
1482
|
block_runs_to_cancel.append(b)
|
|
1408
1483
|
if b.status == BlockRun.BlockRunStatus.RUNNING:
|
|
1409
1484
|
running_blocks.append(b)
|
|
1485
|
+
cancelled_block_run_ids = [b.id for b in block_runs_to_cancel]
|
|
1410
1486
|
BlockRun.batch_update_status(
|
|
1411
|
-
|
|
1487
|
+
cancelled_block_run_ids,
|
|
1412
1488
|
BlockRun.BlockRunStatus.CANCELLED,
|
|
1413
1489
|
)
|
|
1414
1490
|
|
|
@@ -1436,6 +1512,18 @@ def cancel_block_runs_and_jobs(
|
|
|
1436
1512
|
for b in running_blocks:
|
|
1437
1513
|
job_manager.kill_block_run_job(b.id)
|
|
1438
1514
|
|
|
1515
|
+
GenericJob.enqueue_cancel_pipeline_run(pipeline_run.id, cancelled_block_run_ids)
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
def kill_cancelled_runs(pipeline_run_id: int, cancelled_block_run_ids: List):
|
|
1519
|
+
job_manager = get_job_manager()
|
|
1520
|
+
if pipeline_run_id and job_manager.has_pipeline_run_job(pipeline_run_id):
|
|
1521
|
+
job_manager.kill_pipeline_run_job(pipeline_run_id)
|
|
1522
|
+
if cancelled_block_run_ids:
|
|
1523
|
+
for block_run_id in cancelled_block_run_ids:
|
|
1524
|
+
if job_manager.has_block_run_job(block_run_id):
|
|
1525
|
+
job_manager.kill_block_run_job(block_run_id)
|
|
1526
|
+
|
|
1439
1527
|
|
|
1440
1528
|
def check_sla():
|
|
1441
1529
|
repo_pipelines = set(
|
|
@@ -1584,7 +1672,7 @@ def schedule_all():
|
|
|
1584
1672
|
pipeline_runs_excluded_by_limit = []
|
|
1585
1673
|
for pipeline_schedule in active_schedules:
|
|
1586
1674
|
lock_key = f'pipeline_schedule_{pipeline_schedule.id}'
|
|
1587
|
-
if not lock.try_acquire_lock(lock_key):
|
|
1675
|
+
if not lock.try_acquire_lock(lock_key, timeout=30):
|
|
1588
1676
|
continue
|
|
1589
1677
|
|
|
1590
1678
|
trigger_pipeline_run_limit = pipeline_schedule.get_settings().pipeline_run_limit
|
|
@@ -1733,6 +1821,13 @@ def schedule_all():
|
|
|
1733
1821
|
logger.exception(f'Failed to schedule {r}')
|
|
1734
1822
|
traceback.print_exc()
|
|
1735
1823
|
continue
|
|
1824
|
+
|
|
1825
|
+
try:
|
|
1826
|
+
schedule_generic_jobs()
|
|
1827
|
+
except Exception as e:
|
|
1828
|
+
logger.exception(f'Failed to schedule generic jobs {e}')
|
|
1829
|
+
traceback.print_exc()
|
|
1830
|
+
|
|
1736
1831
|
job_manager = get_job_manager()
|
|
1737
1832
|
if job_manager is None:
|
|
1738
1833
|
logger.info('Job manager is None.')
|
|
@@ -1913,3 +2008,52 @@ def sync_schedules(pipeline_uuids: List[str]):
|
|
|
1913
2008
|
trigger_configs.append(pipeline_trigger)
|
|
1914
2009
|
|
|
1915
2010
|
PipelineSchedule.create_or_update_batch(trigger_configs)
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
def schedule_generic_jobs():
|
|
2014
|
+
"""
|
|
2015
|
+
Schedule generic jobs that are in INITIAL status.
|
|
2016
|
+
|
|
2017
|
+
This method schedules jobs like cancel_pipeline_run that have been enqueued
|
|
2018
|
+
by the server process and are waiting to be executed by the job manager.
|
|
2019
|
+
"""
|
|
2020
|
+
try:
|
|
2021
|
+
# Get all jobs with INITIAL status across all repositories
|
|
2022
|
+
jobs = GenericJob.get_jobs_with_initial_status()
|
|
2023
|
+
job_manager = get_job_manager()
|
|
2024
|
+
|
|
2025
|
+
if not jobs:
|
|
2026
|
+
return
|
|
2027
|
+
|
|
2028
|
+
logger.info(f'Scheduling {len(jobs)} generic jobs')
|
|
2029
|
+
|
|
2030
|
+
# Schedule each job with the job manager
|
|
2031
|
+
for job in jobs:
|
|
2032
|
+
try:
|
|
2033
|
+
if job.job_type == GenericJob.JobType.CANCEL_PIPELINE_RUN:
|
|
2034
|
+
pipeline_run_id = job.payload.get('pipeline_run_id')
|
|
2035
|
+
cancelled_block_run_ids = job.payload.get('cancelled_block_run_ids')
|
|
2036
|
+
try:
|
|
2037
|
+
kill_cancelled_runs(pipeline_run_id, cancelled_block_run_ids)
|
|
2038
|
+
except Exception:
|
|
2039
|
+
pass
|
|
2040
|
+
# Add job to job manager for execution
|
|
2041
|
+
job_manager.add_job(
|
|
2042
|
+
JobType.GENERIC_JOB,
|
|
2043
|
+
job.id,
|
|
2044
|
+
on_pipeline_run_cancelled,
|
|
2045
|
+
# args
|
|
2046
|
+
job.id,
|
|
2047
|
+
pipeline_run_id,
|
|
2048
|
+
cancelled_block_run_ids,
|
|
2049
|
+
)
|
|
2050
|
+
job.mark_queued()
|
|
2051
|
+
logger.info(f'Scheduled generic job {job.id} ({job.job_type})')
|
|
2052
|
+
else:
|
|
2053
|
+
raise ValueError(f"Unknown job type: {job.job_type}")
|
|
2054
|
+
except Exception as e:
|
|
2055
|
+
error_message = f"Failed to schedule generic job: {str(e)}"
|
|
2056
|
+
logger.exception(f'Failed to schedule generic job {job.id}: {error_message}')
|
|
2057
|
+
job.mark_failed({'error': error_message})
|
|
2058
|
+
except Exception as e:
|
|
2059
|
+
logger.exception(f'Failed to schedule generic jobs: {e}')
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import collections
|
|
3
2
|
import os
|
|
4
3
|
import traceback
|
|
@@ -262,7 +261,7 @@ class PipelineScheduler:
|
|
|
262
261
|
pipeline_run=self.pipeline_run,
|
|
263
262
|
)
|
|
264
263
|
|
|
265
|
-
|
|
264
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
266
265
|
|
|
267
266
|
self.logger_manager.output_logs_to_destination()
|
|
268
267
|
|
|
@@ -338,7 +337,7 @@ class PipelineScheduler:
|
|
|
338
337
|
|
|
339
338
|
@safe_db_query
|
|
340
339
|
def on_pipeline_run_failure(self, error: str) -> None:
|
|
341
|
-
|
|
340
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
342
341
|
self.notification_sender.send_pipeline_run_failure_message(
|
|
343
342
|
pipeline=self.pipeline,
|
|
344
343
|
pipeline_run=self.pipeline_run,
|
|
@@ -1317,7 +1316,7 @@ def stop_pipeline_run(
|
|
|
1317
1316
|
# Update pipeline run status to cancelled
|
|
1318
1317
|
pipeline_run.update(status=status)
|
|
1319
1318
|
|
|
1320
|
-
|
|
1319
|
+
UsageStatisticLogger().pipeline_run_ended_sync(pipeline_run)
|
|
1321
1320
|
|
|
1322
1321
|
# Cancel all the block runs
|
|
1323
1322
|
cancel_block_runs_and_jobs(pipeline_run, pipeline)
|
|
@@ -1568,7 +1567,7 @@ def schedule_all():
|
|
|
1568
1567
|
concurrency_config = ConcurrencyConfig.load(config=pipeline.concurrency_config)
|
|
1569
1568
|
|
|
1570
1569
|
lock_key = f'pipeline_schedule_{pipeline_schedule.id}'
|
|
1571
|
-
if not lock.try_acquire_lock(lock_key):
|
|
1570
|
+
if not lock.try_acquire_lock(lock_key, timeout=30):
|
|
1572
1571
|
continue
|
|
1573
1572
|
|
|
1574
1573
|
try:
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import traceback
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
|
|
3
4
|
from mage_ai.shared.config import BaseConfig
|
|
4
5
|
from mage_ai.shared.enum import StrEnum
|
|
5
6
|
|
|
7
|
+
DEFAULT_CONCURRENCY = 20
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
class QueueType(StrEnum):
|
|
8
11
|
CELERY = 'celery'
|
|
@@ -17,5 +20,12 @@ class ProcessQueueConfig(BaseConfig):
|
|
|
17
20
|
@dataclass
|
|
18
21
|
class QueueConfig(BaseConfig):
|
|
19
22
|
queue_type: QueueType = QueueType.PROCESS
|
|
20
|
-
concurrency: int =
|
|
23
|
+
concurrency: int = DEFAULT_CONCURRENCY
|
|
21
24
|
process_queue_config: ProcessQueueConfig = None
|
|
25
|
+
|
|
26
|
+
def __post_init__(self):
|
|
27
|
+
try:
|
|
28
|
+
self.concurrency = int(self.concurrency)
|
|
29
|
+
except Exception:
|
|
30
|
+
traceback.print_exc()
|
|
31
|
+
self.concurrency = DEFAULT_CONCURRENCY
|
|
@@ -19,6 +19,7 @@ from mage_ai.settings import (
|
|
|
19
19
|
HOSTNAME,
|
|
20
20
|
REDIS_URL,
|
|
21
21
|
SENTRY_DSN,
|
|
22
|
+
SENTRY_SERVER_NAME,
|
|
22
23
|
SENTRY_TRACES_SAMPLE_RATE,
|
|
23
24
|
SERVER_LOGGING_FORMAT,
|
|
24
25
|
SERVER_VERBOSITY,
|
|
@@ -287,6 +288,7 @@ class Worker(mp.Process):
|
|
|
287
288
|
sentry_sdk.init(
|
|
288
289
|
self.dsn,
|
|
289
290
|
traces_sample_rate=SENTRY_TRACES_SAMPLE_RATE,
|
|
291
|
+
server_name=SENTRY_SERVER_NAME,
|
|
290
292
|
)
|
|
291
293
|
initialize_new_relic()
|
|
292
294
|
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from mage_ai.services.redis.redis import init_redis_client
|
|
2
4
|
from mage_ai.settings import REDIS_URL
|
|
3
5
|
|
|
6
|
+
try:
|
|
7
|
+
REDIS_LOCK_DEFAULT_TIMEOUT = int(os.getenv('REDIS_LOCK_DEFAULT_TIMEOUT', 30) or 30)
|
|
8
|
+
except Exception:
|
|
9
|
+
REDIS_LOCK_DEFAULT_TIMEOUT = 30
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
class DistributedLock:
|
|
6
13
|
def __init__(
|
|
7
14
|
self,
|
|
8
15
|
lock_key_prefix='LOCK_KEY',
|
|
9
|
-
lock_timeout=
|
|
16
|
+
lock_timeout=REDIS_LOCK_DEFAULT_TIMEOUT,
|
|
10
17
|
):
|
|
11
18
|
self.lock_key_prefix = lock_key_prefix
|
|
12
19
|
self.lock_timeout = lock_timeout
|
mage_ai/server/api/base.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
|
+
import re
|
|
3
4
|
import traceback
|
|
5
|
+
import urllib.parse
|
|
4
6
|
|
|
5
7
|
import dateutil.parser
|
|
6
8
|
import simplejson
|
|
7
9
|
import tornado.web
|
|
8
10
|
|
|
9
11
|
from mage_ai.api.middleware import OAuthMiddleware
|
|
12
|
+
from mage_ai.server.api.constants import PATH_TRAVERSAL_PATTERN
|
|
10
13
|
from mage_ai.shared.parsers import encode_complex
|
|
11
14
|
from mage_ai.shared.strings import camel_to_snake_case
|
|
12
15
|
from mage_ai.usage_statistics.constants import EventNameType
|
|
@@ -127,11 +130,49 @@ class BaseApiHandler(BaseHandler, OAuthMiddleware):
|
|
|
127
130
|
super().initialize(**kwargs)
|
|
128
131
|
self.is_health_check = kwargs.get('is_health_check', False)
|
|
129
132
|
|
|
133
|
+
def is_safe_path(self, user_input):
|
|
134
|
+
"""
|
|
135
|
+
Check if the user input is safe and doesn't contain path traversal sequences.
|
|
136
|
+
"""
|
|
137
|
+
return re.match(PATH_TRAVERSAL_PATTERN, user_input) is not None
|
|
138
|
+
|
|
130
139
|
def prepare(self):
|
|
131
140
|
from mage_ai.server.server import latest_user_activity
|
|
132
141
|
|
|
133
142
|
if not self.is_health_check:
|
|
134
143
|
latest_user_activity.update_latest_activity()
|
|
144
|
+
|
|
145
|
+
# Validate the request path by decoding from bytes to string if necessary
|
|
146
|
+
decoded_path = self.request.path
|
|
147
|
+
if isinstance(decoded_path, bytes):
|
|
148
|
+
decoded_path = decoded_path.decode('utf-8') # Decode only if it's a bytes object
|
|
149
|
+
|
|
150
|
+
decoded_path = urllib.parse.unquote(decoded_path) # Decode URL-encoded characters
|
|
151
|
+
if not self.is_safe_path(decoded_path):
|
|
152
|
+
self.set_status(400) # Bad Request
|
|
153
|
+
self.write("Error: Invalid path (path traversal detected)")
|
|
154
|
+
self.finish()
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
# Validate query parameters (if any)
|
|
158
|
+
for key, value in self.request.arguments.items():
|
|
159
|
+
# Decode each key and value from bytes to string if necessary
|
|
160
|
+
decoded_key = key
|
|
161
|
+
if isinstance(decoded_key, bytes):
|
|
162
|
+
decoded_key = decoded_key.decode('utf-8')
|
|
163
|
+
|
|
164
|
+
decoded_value = value[0]
|
|
165
|
+
if isinstance(decoded_value, bytes):
|
|
166
|
+
decoded_value = decoded_value.decode('utf-8')
|
|
167
|
+
|
|
168
|
+
decoded_value = urllib.parse.unquote(decoded_value) # Decode URL-encoded characters
|
|
169
|
+
if not self.is_safe_path(decoded_value):
|
|
170
|
+
self.set_status(400)
|
|
171
|
+
self.write(
|
|
172
|
+
f"Error: Invalid parameter value for '{decoded_key}' (path traversal detected)"
|
|
173
|
+
)
|
|
174
|
+
self.finish()
|
|
175
|
+
return
|
|
135
176
|
super().prepare()
|
|
136
177
|
|
|
137
178
|
|
mage_ai/server/api/constants.py
CHANGED
mage_ai/server/api/triggers.py
CHANGED
|
@@ -23,6 +23,15 @@ class ApiTriggerPipelineHandler(BaseHandler):
|
|
|
23
23
|
if token is None:
|
|
24
24
|
token = get_bearer_auth_token_from_headers(self.request.headers)
|
|
25
25
|
|
|
26
|
+
if ScheduleType.API != pipeline_schedule.schedule_type:
|
|
27
|
+
raise UnauthenticatedRequestException(
|
|
28
|
+
'This endpoint is only supported for API trigger.',
|
|
29
|
+
)
|
|
30
|
+
if not pipeline_schedule.token:
|
|
31
|
+
raise UnauthenticatedRequestException(
|
|
32
|
+
'The token of the API trigger cannot be empty.',
|
|
33
|
+
)
|
|
34
|
+
|
|
26
35
|
if ScheduleType.API == pipeline_schedule.schedule_type and \
|
|
27
36
|
pipeline_schedule.token and \
|
|
28
37
|
pipeline_schedule.token != token:
|
mage_ai/server/constants.py
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
})();
|
|
30
|
-
</script><link rel="preload" href="/_next/static/css/18782af6d2c4e826.css" as="style"/><link rel="stylesheet" href="/_next/static/css/18782af6d2c4e826.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-
|
|
30
|
+
</script><link rel="preload" href="/_next/static/css/18782af6d2c4e826.css" as="style"/><link rel="stylesheet" href="/_next/static/css/18782af6d2c4e826.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-b9a067f3bd0a3a05.js" defer=""></script><script src="/_next/static/chunks/framework-ea07653270784974.js" defer=""></script><script src="/_next/static/chunks/main-f39b6301263551db.js" defer=""></script><script src="/_next/static/chunks/pages/_app-782dd4a6b13e1c42.js" defer=""></script><script src="/_next/static/chunks/pages/404-8ecd93274c427b76.js" defer=""></script><script src="/_next/static/qR0jauUABqPaFMjUsYeoG/_buildManifest.js" defer=""></script><script src="/_next/static/qR0jauUABqPaFMjUsYeoG/_ssgManifest.js" defer=""></script><style data-styled="" data-styled-version="5.3.11">html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar;}/*!sc*/
|
|
31
31
|
*,*::before,*::after{-webkit-box-sizing:inherit;box-sizing:inherit;}/*!sc*/
|
|
32
32
|
data-styled.g4[id="sc-global-czSCUT1"]{content:"sc-global-czSCUT1,"}/*!sc*/
|
|
33
33
|
.cGTklP{margin-top:16px;margin-bottom:16px;}/*!sc*/
|
|
@@ -46,4 +46,4 @@ data-styled.g81[id="Headline__H1Style-sc-12jzt2e-2"]{content:"wrkfv,"}/*!sc*/
|
|
|
46
46
|
.dionUf .Toastify__toast--success{background:#00A81A !important;color:#FFFFFF !important;}/*!sc*/
|
|
47
47
|
.dionUf .Toastify__toast--warning{background:#DD9900 !important;color:#FFFFFF !important;}/*!sc*/
|
|
48
48
|
data-styled.g279[id="ToastWrapper-sc-1a33ph1-0"]{content:"dionUf,"}/*!sc*/
|
|
49
|
-
</style></head><body><div id="__next"><div class="" style="position:fixed;top:0;left:0;height:2px;background:transparent;z-index:99999999999;width:100%"><div class="" style="height:100%;background:#FF144D;transition:all 500ms ease;width:0%"><div style="box-shadow:0 0 10px #FF144D, 0 0 10px #FF144D;width:5%;opacity:1;position:absolute;height:100%;transition:all 500ms ease;transform:rotate(3deg) translate(0px, -4px);left:-10rem"></div></div></div><main style="align-items:center;display:flex;flex-direction:column;height:100vh;margin-top:16rem"><svg width="84.70857142857143" height="64" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.4" d="M15.3266 0L19.2641 1.82961e-06L11.9687 14L8.03125 14L15.3266 0Z" fill="url(#paint0_linear_1303_5)"></path><path d="M11.9692 1.82961e-06L8.03164 0L0.736328 14L4.67383 14L8.03164 7.55626V14H11.9691V8.38194e-05L11.9692 1.82961e-06Z" fill="url(#paint1_linear_1303_5)"></path><path d="M15.3269 2.57679e-06H19.2644V14H15.3269V2.57679e-06Z" fill="url(#paint2_linear_1303_5)"></path><defs><linearGradient id="paint0_linear_1303_5" x1="8.03125" y1="7" x2="19.2641" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient><linearGradient id="paint1_linear_1303_5" x1="0.736328" y1="7" x2="19.2644" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient><linearGradient id="paint2_linear_1303_5" x1="0.736328" y1="7" x2="19.2644" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient></defs></svg><div class="Spacing__SpacingStyle-sc-1mpmtgj-0 cGTklP"><div class="Headline__HeadlineContainerStyle-sc-12jzt2e-0 hxvzgz"><h1 class="Headline__H1Style-sc-12jzt2e-2 wrkfv">404 - Page Not Found<!-- --></h1></div></div><p class="Text__TextStyle-sc-sl5nur-0 cKjmRF">You will be redirected to the Pipelines dashboard in <!-- -->5<!-- --> seconds.<!-- --></p></main><div id="command-center-root"></div><div></div><div></div><div></div><div class="ToastWrapper-sc-1a33ph1-0 dionUf"><div class="Toastify"></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{},"currentTheme":{"accent":{"alert":"#F6540B","blue":"#4877FF","blueLight":"rgba(72, 119, 255, 0.5)","contentDefaultTransparent":"rgba(174, 174, 174, 0.5)","cyan":"#65E3FF","cyanLight":"rgba(101, 227, 255, 0.3)","cyanTransparent":"rgba(101, 227, 255, 0.12)","dbt":"#fc6949","dbtDark":"rgba(252, 105, 73, 0.3)","dbtLight":"rgba(252, 105, 73, 0.5)","info":"#00ABFF","infoTransparent":"rgba(0, 171, 255, 0.5)","negative":"#FF1E59","negativeTransparent":"rgba(255, 30, 89, 0.3)","pink":"#FF4FF8","pinkLight":"rgb(255, 79, 248, 0.5)","positive":"#00A81A","primaryTransparent":"rgba(155, 108, 167, 0.5)","purple":"#7D55EC","purpleLight":"rgba(125, 85, 236, 0.5)","rose":"#D1A2AB","roseLight":"rgba(209, 162, 171, 0.5)","sky":"#6AA1E0","skyLight":"rgba(106, 161, 224, 0.5)","teal":"#00B4CC","tealLight":"rgba(0, 180, 204, 0.5)","warning":"#DD9900","warningTransparent":"rgba(221, 153, 0, 0.5)","yellow":"#FFCC19","yellowLight":"rgba(255, 204, 25, 0.5)"},"background":{"blackTransparent":"rgba(0, 0, 0, 0.6)","blackTransparentDark":"rgba(0, 0, 0, 0.8)","chartBlock":"#2E3036","codeArea":"#1E1F24","codeTextarea":"#000000","content":"#1B1C20","danger":"#FFD0DB","dark":"#B1B8C3","dashboard":"#18181C","dashboardTransparent":"rgba(24, 24, 28, 0.1)","header":"#1B1B1B","menu":"#0F4CFF","muted":"#F9FAFC","navigation":"#EDEDED","output":"#2E3036","page":"#1E1F24","panel":"#232429","panelTransparent":"rgba(35, 36, 41, 0.7)","popup":"#27292E","row":"#2C2C2C","row2":"#51535C","scrollbarThumb":"rgba(100, 100, 100, 0.5)","scrollbarThumbHover":"rgba(255, 255, 255, 0.3)","scrollbarTrack":"#2E3036","success":"#8ADE00","successLight":"rgb(138, 222, 0, 0.3)","table":"#292A2F","tag":"#3A4550"},"borders":{"button":"#454850","contrast":"#FFFFFF","danger":"#FF144D","dark":"#000000","darkLight":"#2E3036","info":"#FFCC19","light":"#2F3034","medium":"#1C1C1C","medium2":"#141414","success":"#2FCB52"},"brand":{"earth100":"#C6EEDB","earth200":"#9DDFBF","earth300":"#6BBF96","earth400":"#37A46F","earth400Transparent":"rgba(55, 164, 111, 0.4)","earth500":"#00954C","energy100":"#FFF4BA","energy200":"#FFED92","energy300":"#FFE662","energy400":"#FFDA19","energy400Transparent":"rgba(255, 218, 25, 0.04)","energy500":"#F6C000","fire100":"#FFD7E0","fire200":"#FFA3B9","fire300":"#FF547D","fire400":"#FF144D","fire400Transparent":"rgba(255, 20, 77, 0.4)","fire500":"#EB0032","stone100":"#F3E6D7","stone200":"#E3D4C2","stone400":"#BFA78B","stone500":"#AF8859","water100":"#BDCEFF","water200":"#81A1FF","water300":"#517DFF","water400":"#2A60FE","water400Transparent":"rgba(42, 96, 254, 0.4)","water500":"#0F4CFF","wind100":"#EEEAFF","wind200":"#CCC1F4","wind300":"#A698DD","wind400":"#6B50D7","wind400SuperTransparent":"rgba(107, 80, 215, 0.12)","wind400Transparent":"rgba(107, 80, 215, 0.4)","wind500":"#4E32BC"},"chart":{"backgroundPrimary":"#7D55EC","backgroundSecondary":"#FF144D","backgroundTertiary":"#86E2FF","button1":"#4877FF","button2":"#FFCC19","button3":"#8ADE00","button4":"#FF4FF8","button5":"#B98D95","lines":"#9B6CA7","primary":"#6B50D7","secondary":"#FF144D","tertiary":"#2A60FE"},"content":{"active":"#FFFFFF","default":"#AEAEAE","disabled":"rgba(255, 255, 255, 0.3)","inverted":"#2C2C2C","muted":"#787A85"},"elevation":{"visualizationAccent":"#996CFF","visualizationAccentAlt":"#C1ACF7"},"feature":{"active":"rgba(250, 248, 254, 0.14)","disabled":"rgba(201, 206, 218, 0.12)"},"icons":{"neutral":"#787878"},"interactive":{"activeBorder":"#060606","blackBackgroundTransparent":"rgba(0, 0, 0, 0.5)","checked":"#060606","dangerBorder":"#FF144D","defaultBackground":"#36383F","defaultBackgroundTransparent":"rgba(54, 56, 63, 0.5)","defaultBorder":"#ffffff1a","disabledBorder":"#B1B8C3","focusBackground":"#B1B8C3","focusBorder":"#86E2FF","hoverBackground":"#4E4E4E","hoverBackgroundTransparent":"rgba(78, 78, 78, 0.5)","hoverBlackBackgroundTransparent":"rgba(0, 0, 0, 0.7)","hoverBorder":"#B9BFCA","hoverOverlay":"rgba(255, 255, 255, 0.1)","linkPrimary":"#1752FF","linkPrimaryHover":"#4877FF","linkPrimaryLight":"#5982ff","linkSecondary":"#6B50D7","linkSecondaryDisabled":"#C4B9EF","linkText":"#6AA1E0","linkTextLight":"#9ECBFF","purple":"#885EFF","rowHoverBackground":"rgba(0, 0, 0, 0.1)","transparent":"rgba(255, 255, 255, 0)"},"loader":{"color":"#EB0032","colorInverted":"#8ADE00"},"logo":{"color":"#FFFFFF"},"monotone":{"black":"#060606","blackTransparent":"rgba(0, 0, 0, 0.6)","gray":"#B1B8C3","grey100":"#F2F2F2","grey200":"#D5D7DC","grey300":"#B4B8C0","grey400":"#70747C","grey500":"#51535C","purple":"#6B50D7","white":"#FFFFFF","whiteTransparent":"rgba(255, 255, 255, 0.6)"},"neutral":{"n100":"#E7E8EA","n200":"#D8DADE","n300":"#CBCCD0","n400":"#BCBEC4","n500":"#AEB0B6"},"progress":{"negative":"#FF144D","positive":"#6B50D7"},"shadow":{"base":"12px 40px 120px rgba(0, 0, 0, 0.3)","frame":"0px 10px 40px rgba(0, 0, 0, 0.26)","menu":"4px 10px 20px rgba(6, 6, 6, 0.12)","popup":"10px 20px 40px rgba(0, 0, 0, 0.2)","small":"0px, 4px, rgba(0, 0, 0, 0.25)","window":"0px 10px 60px rgba(0, 0, 0, 0.7)"},"status":{"negative":"#FF144D","positive":"#24B400"},"text":{"fileBrowser":"#787A85"}}},"page":"/404","query":{},"buildId":"
|
|
49
|
+
</style></head><body><div id="__next"><div class="" style="position:fixed;top:0;left:0;height:2px;background:transparent;z-index:99999999999;width:100%"><div class="" style="height:100%;background:#FF144D;transition:all 500ms ease;width:0%"><div style="box-shadow:0 0 10px #FF144D, 0 0 10px #FF144D;width:5%;opacity:1;position:absolute;height:100%;transition:all 500ms ease;transform:rotate(3deg) translate(0px, -4px);left:-10rem"></div></div></div><main style="align-items:center;display:flex;flex-direction:column;height:100vh;margin-top:16rem"><svg width="84.70857142857143" height="64" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.4" d="M15.3266 0L19.2641 1.82961e-06L11.9687 14L8.03125 14L15.3266 0Z" fill="url(#paint0_linear_1303_5)"></path><path d="M11.9692 1.82961e-06L8.03164 0L0.736328 14L4.67383 14L8.03164 7.55626V14H11.9691V8.38194e-05L11.9692 1.82961e-06Z" fill="url(#paint1_linear_1303_5)"></path><path d="M15.3269 2.57679e-06H19.2644V14H15.3269V2.57679e-06Z" fill="url(#paint2_linear_1303_5)"></path><defs><linearGradient id="paint0_linear_1303_5" x1="8.03125" y1="7" x2="19.2641" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient><linearGradient id="paint1_linear_1303_5" x1="0.736328" y1="7" x2="19.2644" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient><linearGradient id="paint2_linear_1303_5" x1="0.736328" y1="7" x2="19.2644" y2="7" gradientUnits="userSpaceOnUse"><stop offset="0.28125" stop-color="#7D55EC"></stop><stop offset="1" stop-color="#2AB2FE"></stop></linearGradient></defs></svg><div class="Spacing__SpacingStyle-sc-1mpmtgj-0 cGTklP"><div class="Headline__HeadlineContainerStyle-sc-12jzt2e-0 hxvzgz"><h1 class="Headline__H1Style-sc-12jzt2e-2 wrkfv">404 - Page Not Found<!-- --></h1></div></div><p class="Text__TextStyle-sc-sl5nur-0 cKjmRF">You will be redirected to the Pipelines dashboard in <!-- -->5<!-- --> seconds.<!-- --></p></main><div id="command-center-root"></div><div></div><div></div><div></div><div class="ToastWrapper-sc-1a33ph1-0 dionUf"><div class="Toastify"></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{},"currentTheme":{"accent":{"alert":"#F6540B","blue":"#4877FF","blueLight":"rgba(72, 119, 255, 0.5)","contentDefaultTransparent":"rgba(174, 174, 174, 0.5)","cyan":"#65E3FF","cyanLight":"rgba(101, 227, 255, 0.3)","cyanTransparent":"rgba(101, 227, 255, 0.12)","dbt":"#fc6949","dbtDark":"rgba(252, 105, 73, 0.3)","dbtLight":"rgba(252, 105, 73, 0.5)","info":"#00ABFF","infoTransparent":"rgba(0, 171, 255, 0.5)","negative":"#FF1E59","negativeTransparent":"rgba(255, 30, 89, 0.3)","pink":"#FF4FF8","pinkLight":"rgb(255, 79, 248, 0.5)","positive":"#00A81A","primaryTransparent":"rgba(155, 108, 167, 0.5)","purple":"#7D55EC","purpleLight":"rgba(125, 85, 236, 0.5)","rose":"#D1A2AB","roseLight":"rgba(209, 162, 171, 0.5)","sky":"#6AA1E0","skyLight":"rgba(106, 161, 224, 0.5)","teal":"#00B4CC","tealLight":"rgba(0, 180, 204, 0.5)","warning":"#DD9900","warningTransparent":"rgba(221, 153, 0, 0.5)","yellow":"#FFCC19","yellowLight":"rgba(255, 204, 25, 0.5)"},"background":{"blackTransparent":"rgba(0, 0, 0, 0.6)","blackTransparentDark":"rgba(0, 0, 0, 0.8)","chartBlock":"#2E3036","codeArea":"#1E1F24","codeTextarea":"#000000","content":"#1B1C20","danger":"#FFD0DB","dark":"#B1B8C3","dashboard":"#18181C","dashboardTransparent":"rgba(24, 24, 28, 0.1)","header":"#1B1B1B","menu":"#0F4CFF","muted":"#F9FAFC","navigation":"#EDEDED","output":"#2E3036","page":"#1E1F24","panel":"#232429","panelTransparent":"rgba(35, 36, 41, 0.7)","popup":"#27292E","row":"#2C2C2C","row2":"#51535C","scrollbarThumb":"rgba(100, 100, 100, 0.5)","scrollbarThumbHover":"rgba(255, 255, 255, 0.3)","scrollbarTrack":"#2E3036","success":"#8ADE00","successLight":"rgb(138, 222, 0, 0.3)","table":"#292A2F","tag":"#3A4550"},"borders":{"button":"#454850","contrast":"#FFFFFF","danger":"#FF144D","dark":"#000000","darkLight":"#2E3036","info":"#FFCC19","light":"#2F3034","medium":"#1C1C1C","medium2":"#141414","success":"#2FCB52"},"brand":{"earth100":"#C6EEDB","earth200":"#9DDFBF","earth300":"#6BBF96","earth400":"#37A46F","earth400Transparent":"rgba(55, 164, 111, 0.4)","earth500":"#00954C","energy100":"#FFF4BA","energy200":"#FFED92","energy300":"#FFE662","energy400":"#FFDA19","energy400Transparent":"rgba(255, 218, 25, 0.04)","energy500":"#F6C000","fire100":"#FFD7E0","fire200":"#FFA3B9","fire300":"#FF547D","fire400":"#FF144D","fire400Transparent":"rgba(255, 20, 77, 0.4)","fire500":"#EB0032","stone100":"#F3E6D7","stone200":"#E3D4C2","stone400":"#BFA78B","stone500":"#AF8859","water100":"#BDCEFF","water200":"#81A1FF","water300":"#517DFF","water400":"#2A60FE","water400Transparent":"rgba(42, 96, 254, 0.4)","water500":"#0F4CFF","wind100":"#EEEAFF","wind200":"#CCC1F4","wind300":"#A698DD","wind400":"#6B50D7","wind400SuperTransparent":"rgba(107, 80, 215, 0.12)","wind400Transparent":"rgba(107, 80, 215, 0.4)","wind500":"#4E32BC"},"chart":{"backgroundPrimary":"#7D55EC","backgroundSecondary":"#FF144D","backgroundTertiary":"#86E2FF","button1":"#4877FF","button2":"#FFCC19","button3":"#8ADE00","button4":"#FF4FF8","button5":"#B98D95","lines":"#9B6CA7","primary":"#6B50D7","secondary":"#FF144D","tertiary":"#2A60FE"},"content":{"active":"#FFFFFF","default":"#AEAEAE","disabled":"rgba(255, 255, 255, 0.3)","inverted":"#2C2C2C","muted":"#787A85"},"elevation":{"visualizationAccent":"#996CFF","visualizationAccentAlt":"#C1ACF7"},"feature":{"active":"rgba(250, 248, 254, 0.14)","disabled":"rgba(201, 206, 218, 0.12)"},"icons":{"neutral":"#787878"},"interactive":{"activeBorder":"#060606","blackBackgroundTransparent":"rgba(0, 0, 0, 0.5)","checked":"#060606","dangerBorder":"#FF144D","defaultBackground":"#36383F","defaultBackgroundTransparent":"rgba(54, 56, 63, 0.5)","defaultBorder":"#ffffff1a","disabledBorder":"#B1B8C3","focusBackground":"#B1B8C3","focusBorder":"#86E2FF","hoverBackground":"#4E4E4E","hoverBackgroundTransparent":"rgba(78, 78, 78, 0.5)","hoverBlackBackgroundTransparent":"rgba(0, 0, 0, 0.7)","hoverBorder":"#B9BFCA","hoverOverlay":"rgba(255, 255, 255, 0.1)","linkPrimary":"#1752FF","linkPrimaryHover":"#4877FF","linkPrimaryLight":"#5982ff","linkSecondary":"#6B50D7","linkSecondaryDisabled":"#C4B9EF","linkText":"#6AA1E0","linkTextLight":"#9ECBFF","purple":"#885EFF","rowHoverBackground":"rgba(0, 0, 0, 0.1)","transparent":"rgba(255, 255, 255, 0)"},"loader":{"color":"#EB0032","colorInverted":"#8ADE00"},"logo":{"color":"#FFFFFF"},"monotone":{"black":"#060606","blackTransparent":"rgba(0, 0, 0, 0.6)","gray":"#B1B8C3","grey100":"#F2F2F2","grey200":"#D5D7DC","grey300":"#B4B8C0","grey400":"#70747C","grey500":"#51535C","purple":"#6B50D7","white":"#FFFFFF","whiteTransparent":"rgba(255, 255, 255, 0.6)"},"neutral":{"n100":"#E7E8EA","n200":"#D8DADE","n300":"#CBCCD0","n400":"#BCBEC4","n500":"#AEB0B6"},"progress":{"negative":"#FF144D","positive":"#6B50D7"},"shadow":{"base":"12px 40px 120px rgba(0, 0, 0, 0.3)","frame":"0px 10px 40px rgba(0, 0, 0, 0.26)","menu":"4px 10px 20px rgba(6, 6, 6, 0.12)","popup":"10px 20px 40px rgba(0, 0, 0, 0.2)","small":"0px, 4px, rgba(0, 0, 0, 0.25)","window":"0px 10px 60px rgba(0, 0, 0, 0.7)"},"status":{"negative":"#FF144D","positive":"#24B400"},"text":{"fileBrowser":"#787A85"}}},"page":"/404","query":{},"buildId":"qR0jauUABqPaFMjUsYeoG","nextExport":true,"isFallback":false,"appGip":true,"scriptLoader":[]}</script></body></html>
|