mage-ai 0.9.69__py3-none-any.whl → 0.9.71__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/ai/utils/xgboost.py +222 -0
- mage_ai/api/errors.py +37 -25
- mage_ai/api/operations/base.py +13 -1
- mage_ai/api/parsers/PipelineScheduleParser.py +1 -1
- mage_ai/api/policies/BackfillPolicy.py +1 -0
- mage_ai/api/policies/BlockOutputPolicy.py +40 -17
- mage_ai/api/policies/GlobalDataProductPolicy.py +91 -41
- mage_ai/api/policies/KernelPolicy.py +55 -32
- mage_ai/api/policies/KernelProcessPolicy.py +56 -0
- mage_ai/api/policies/OutputPolicy.py +73 -41
- mage_ai/api/policies/PipelinePolicy.py +206 -137
- mage_ai/api/policies/WorkspacePolicy.py +1 -0
- mage_ai/api/presenters/BackfillPresenter.py +1 -0
- mage_ai/api/presenters/BlockLayoutItemPresenter.py +9 -7
- mage_ai/api/presenters/BlockPresenter.py +1 -1
- mage_ai/api/presenters/GlobalDataProductPresenter.py +6 -1
- mage_ai/api/presenters/KernelPresenter.py +5 -26
- mage_ai/api/presenters/KernelProcessPresenter.py +28 -0
- mage_ai/api/presenters/PipelinePresenter.py +18 -5
- mage_ai/api/presenters/StatusPresenter.py +2 -0
- mage_ai/api/presenters/SyncPresenter.py +25 -0
- mage_ai/api/resources/AutocompleteItemResource.py +1 -1
- mage_ai/api/resources/BlockLayoutItemResource.py +90 -44
- mage_ai/api/resources/BlockOutputResource.py +42 -9
- mage_ai/api/resources/BlockResource.py +4 -3
- mage_ai/api/resources/BlockRunResource.py +27 -22
- mage_ai/api/resources/ClusterResource.py +4 -1
- mage_ai/api/resources/CustomTemplateResource.py +34 -14
- mage_ai/api/resources/DataProviderResource.py +1 -1
- mage_ai/api/resources/ExecutionStateResource.py +3 -1
- mage_ai/api/resources/FileContentResource.py +8 -2
- mage_ai/api/resources/FileResource.py +10 -4
- mage_ai/api/resources/FileVersionResource.py +3 -1
- mage_ai/api/resources/GitBranchResource.py +101 -31
- mage_ai/api/resources/GitCustomBranchResource.py +29 -1
- mage_ai/api/resources/GlobalDataProductResource.py +44 -7
- mage_ai/api/resources/GlobalHookResource.py +4 -1
- mage_ai/api/resources/IntegrationDestinationResource.py +6 -2
- mage_ai/api/resources/IntegrationSourceResource.py +8 -4
- mage_ai/api/resources/IntegrationSourceStreamResource.py +6 -2
- mage_ai/api/resources/KernelProcessResource.py +44 -0
- mage_ai/api/resources/KernelResource.py +25 -3
- mage_ai/api/resources/OauthResource.py +1 -1
- mage_ai/api/resources/OutputResource.py +33 -11
- mage_ai/api/resources/PageBlockLayoutResource.py +34 -23
- mage_ai/api/resources/PipelineInteractionResource.py +31 -15
- mage_ai/api/resources/PipelineResource.py +258 -125
- mage_ai/api/resources/PipelineRunResource.py +52 -7
- mage_ai/api/resources/PipelineScheduleResource.py +11 -2
- mage_ai/api/resources/PipelineTriggerResource.py +6 -1
- mage_ai/api/resources/ProjectResource.py +18 -7
- mage_ai/api/resources/PullRequestResource.py +6 -4
- mage_ai/api/resources/SecretResource.py +1 -1
- mage_ai/api/resources/SeedResource.py +8 -1
- mage_ai/api/resources/StatusResource.py +21 -6
- mage_ai/api/resources/SyncResource.py +6 -8
- mage_ai/api/resources/VariableResource.py +46 -26
- mage_ai/api/resources/VersionControlProjectResource.py +9 -2
- mage_ai/api/resources/WidgetResource.py +1 -1
- mage_ai/api/resources/WorkspaceResource.py +6 -5
- mage_ai/api/views.py +47 -40
- mage_ai/authentication/permissions/seed.py +16 -2
- mage_ai/authentication/providers/oidc.py +21 -1
- mage_ai/autocomplete/utils.py +13 -9
- mage_ai/cache/base.py +1 -1
- mage_ai/cache/block.py +18 -12
- mage_ai/cache/block_action_object/__init__.py +33 -5
- mage_ai/cache/file.py +22 -19
- mage_ai/cache/pipeline.py +18 -12
- mage_ai/cli/main.py +1 -0
- mage_ai/cluster_manager/aws/emr_cluster_manager.py +9 -5
- mage_ai/cluster_manager/config.py +2 -2
- mage_ai/cluster_manager/kubernetes/workload_manager.py +52 -1
- mage_ai/cluster_manager/manage.py +1 -1
- mage_ai/cluster_manager/workspace/base.py +7 -1
- mage_ai/cluster_manager/workspace/kubernetes.py +22 -1
- mage_ai/command_center/applications/factory.py +10 -7
- mage_ai/command_center/applications/utils.py +2 -2
- mage_ai/command_center/files/factory.py +17 -15
- mage_ai/command_center/presenters/text.py +1 -1
- mage_ai/command_center/utils.py +25 -13
- mage_ai/data/__init__.py +0 -0
- mage_ai/data/constants.py +45 -0
- mage_ai/data/models/__init__.py +0 -0
- mage_ai/data/models/base.py +119 -0
- mage_ai/data/models/constants.py +1 -0
- mage_ai/data/models/generator.py +115 -0
- mage_ai/data/models/manager.py +168 -0
- mage_ai/data/models/pyarrow/__init__.py +0 -0
- mage_ai/data/models/pyarrow/record_batch.py +55 -0
- mage_ai/data/models/pyarrow/shared.py +21 -0
- mage_ai/data/models/pyarrow/table.py +8 -0
- mage_ai/data/models/reader.py +103 -0
- mage_ai/data/models/utils.py +59 -0
- mage_ai/data/models/writer.py +91 -0
- mage_ai/data/tabular/__init__.py +0 -0
- mage_ai/data/tabular/constants.py +23 -0
- mage_ai/data/tabular/mocks.py +19 -0
- mage_ai/data/tabular/models.py +126 -0
- mage_ai/data/tabular/reader.py +602 -0
- mage_ai/data/tabular/utils.py +102 -0
- mage_ai/data/tabular/writer.py +266 -0
- mage_ai/data/variables/__init__.py +0 -0
- mage_ai/data/variables/wrapper.py +54 -0
- mage_ai/data_cleaner/analysis/charts.py +61 -39
- mage_ai/data_cleaner/column_types/column_type_detector.py +53 -31
- mage_ai/data_cleaner/estimators/encoders.py +5 -2
- mage_ai/data_integrations/utils/scheduler.py +16 -11
- mage_ai/data_preparation/decorators.py +1 -0
- mage_ai/data_preparation/executors/block_executor.py +237 -155
- mage_ai/data_preparation/executors/k8s_block_executor.py +30 -7
- mage_ai/data_preparation/executors/k8s_pipeline_executor.py +30 -7
- mage_ai/data_preparation/executors/streaming_pipeline_executor.py +2 -2
- mage_ai/data_preparation/git/__init__.py +77 -29
- mage_ai/data_preparation/git/api.py +69 -8
- mage_ai/data_preparation/git/utils.py +64 -34
- mage_ai/data_preparation/logging/logger_manager.py +4 -3
- mage_ai/data_preparation/models/block/__init__.py +1562 -879
- mage_ai/data_preparation/models/block/data_integration/mixins.py +4 -3
- mage_ai/data_preparation/models/block/dynamic/__init__.py +17 -6
- mage_ai/data_preparation/models/block/dynamic/child.py +41 -102
- mage_ai/data_preparation/models/block/dynamic/constants.py +1 -0
- mage_ai/data_preparation/models/block/dynamic/counter.py +296 -0
- mage_ai/data_preparation/models/block/dynamic/data.py +16 -0
- mage_ai/data_preparation/models/block/dynamic/factory.py +163 -0
- mage_ai/data_preparation/models/block/dynamic/models.py +19 -0
- mage_ai/data_preparation/models/block/dynamic/shared.py +92 -0
- mage_ai/data_preparation/models/block/dynamic/utils.py +295 -167
- mage_ai/data_preparation/models/block/dynamic/variables.py +384 -144
- mage_ai/data_preparation/models/block/dynamic/wrappers.py +77 -0
- mage_ai/data_preparation/models/block/extension/utils.py +10 -1
- mage_ai/data_preparation/models/block/global_data_product/__init__.py +35 -3
- mage_ai/data_preparation/models/block/integration/__init__.py +6 -2
- mage_ai/data_preparation/models/block/outputs.py +722 -0
- mage_ai/data_preparation/models/block/platform/mixins.py +7 -8
- mage_ai/data_preparation/models/block/r/__init__.py +56 -38
- mage_ai/data_preparation/models/block/remote/__init__.py +0 -0
- mage_ai/data_preparation/models/block/remote/models.py +58 -0
- mage_ai/data_preparation/models/block/settings/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/dynamic/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/dynamic/constants.py +7 -0
- mage_ai/data_preparation/models/block/settings/dynamic/mixins.py +118 -0
- mage_ai/data_preparation/models/block/settings/dynamic/models.py +31 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/mixins.py +20 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/models.py +46 -0
- mage_ai/data_preparation/models/block/settings/variables/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/variables/mixins.py +74 -0
- mage_ai/data_preparation/models/block/settings/variables/models.py +49 -0
- mage_ai/data_preparation/models/block/spark/mixins.py +2 -1
- mage_ai/data_preparation/models/block/sql/__init__.py +30 -5
- mage_ai/data_preparation/models/block/sql/utils/shared.py +21 -3
- mage_ai/data_preparation/models/block/utils.py +164 -69
- mage_ai/data_preparation/models/constants.py +21 -14
- mage_ai/data_preparation/models/custom_templates/custom_block_template.py +18 -13
- mage_ai/data_preparation/models/custom_templates/custom_pipeline_template.py +33 -16
- mage_ai/data_preparation/models/custom_templates/utils.py +1 -1
- mage_ai/data_preparation/models/file.py +41 -28
- mage_ai/data_preparation/models/global_data_product/__init__.py +100 -58
- mage_ai/data_preparation/models/global_hooks/models.py +1 -0
- mage_ai/data_preparation/models/interfaces.py +29 -0
- mage_ai/data_preparation/models/pipeline.py +374 -185
- mage_ai/data_preparation/models/pipelines/integration_pipeline.py +1 -2
- mage_ai/data_preparation/models/pipelines/seed.py +1 -1
- mage_ai/data_preparation/models/project/__init__.py +66 -18
- mage_ai/data_preparation/models/project/constants.py +2 -0
- mage_ai/data_preparation/models/triggers/__init__.py +124 -26
- mage_ai/data_preparation/models/utils.py +467 -17
- mage_ai/data_preparation/models/variable.py +1028 -137
- mage_ai/data_preparation/models/variables/__init__.py +0 -0
- mage_ai/data_preparation/models/variables/cache.py +149 -0
- mage_ai/data_preparation/models/variables/constants.py +72 -0
- mage_ai/data_preparation/models/variables/summarizer.py +336 -0
- mage_ai/data_preparation/models/variables/utils.py +77 -0
- mage_ai/data_preparation/models/widget/__init__.py +63 -41
- mage_ai/data_preparation/models/widget/charts.py +40 -27
- mage_ai/data_preparation/models/widget/constants.py +2 -0
- mage_ai/data_preparation/models/widget/utils.py +3 -3
- mage_ai/data_preparation/preferences.py +3 -3
- mage_ai/data_preparation/repo_manager.py +55 -21
- mage_ai/data_preparation/storage/base_storage.py +2 -2
- mage_ai/data_preparation/storage/gcs_storage.py +7 -4
- mage_ai/data_preparation/storage/local_storage.py +18 -9
- mage_ai/data_preparation/storage/s3_storage.py +5 -2
- mage_ai/data_preparation/templates/data_exporters/streaming/oracledb.yaml +8 -0
- mage_ai/data_preparation/variable_manager.py +281 -76
- mage_ai/io/base.py +3 -2
- mage_ai/io/bigquery.py +1 -0
- mage_ai/io/redshift.py +7 -5
- mage_ai/kernels/__init__.py +0 -0
- mage_ai/kernels/models.py +188 -0
- mage_ai/kernels/utils.py +169 -0
- mage_ai/orchestration/concurrency.py +6 -2
- mage_ai/orchestration/db/__init__.py +1 -0
- mage_ai/orchestration/db/migrations/versions/0227396a216c_add_userproject_table.py +38 -0
- mage_ai/orchestration/db/migrations/versions/42a14d6143f1_update_token_column_type.py +54 -0
- mage_ai/orchestration/db/models/dynamic/__init__.py +0 -0
- mage_ai/orchestration/db/models/dynamic/controller.py +67 -0
- mage_ai/orchestration/db/models/oauth.py +12 -18
- mage_ai/orchestration/db/models/projects.py +10 -0
- mage_ai/orchestration/db/models/schedules.py +225 -187
- mage_ai/orchestration/db/models/schedules_project_platform.py +18 -12
- mage_ai/orchestration/db/models/utils.py +46 -5
- mage_ai/orchestration/metrics/pipeline_run.py +8 -9
- mage_ai/orchestration/notification/sender.py +38 -15
- mage_ai/orchestration/pipeline_scheduler_original.py +64 -33
- mage_ai/orchestration/pipeline_scheduler_project_platform.py +1 -1
- mage_ai/orchestration/run_status_checker.py +11 -4
- mage_ai/orchestration/triggers/api.py +41 -2
- mage_ai/orchestration/triggers/global_data_product.py +9 -4
- mage_ai/orchestration/triggers/utils.py +10 -1
- mage_ai/orchestration/utils/resources.py +3 -0
- mage_ai/presenters/charts/data_sources/base.py +4 -2
- mage_ai/presenters/charts/data_sources/block.py +15 -9
- mage_ai/presenters/charts/data_sources/chart_code.py +8 -5
- mage_ai/presenters/charts/data_sources/constants.py +1 -0
- mage_ai/presenters/charts/data_sources/system_metrics.py +22 -0
- mage_ai/presenters/interactions/models.py +11 -7
- mage_ai/presenters/pages/loaders/pipelines.py +5 -3
- mage_ai/presenters/pages/models/page_components/pipeline_schedules.py +3 -1
- mage_ai/presenters/utils.py +2 -0
- mage_ai/server/api/blocks.py +2 -1
- mage_ai/server/api/downloads.py +9 -2
- mage_ai/server/api/runs.py +151 -0
- mage_ai/server/api/triggers.py +3 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +8 -8
- mage_ai/server/frontend_dist/_next/static/UZLabyPgcxtZvp0O0EUUS/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1557-25a7d985d5564fd3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{3548-fa0792ddb88f4646.js → 3548-9d26185b3fb663b1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{3763-61b542dafdbf5754.js → 3763-40780c6d1e4b261d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/5699-176f445e1313f001.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{main-77fe248a6fbd12d8.js → main-b99d4e30a88d9dc7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-9fe2d9d07c94e968.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{overview-597b74828bf105db.js → overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-3edc6270c5b0e962.js → frontend_dist/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7e737f6fc7e83e9b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-a5c0362763a21fa8.js → block-runs-284309877f3c5a5a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-7acc7afc00df17c2.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5f4c8128b2413fd8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-1bdfda8edc9cf4a8.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js → frontend_dist/_next/static/chunks/pages/settings/platform/settings-319ddbabc239e91b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{triggers-9cba3211434a8966.js → triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{webpack-d079359c241db804.js → webpack-ac7fdc472bedf682.js} +1 -1
- mage_ai/server/frontend_dist/block-layout.html +3 -3
- mage_ai/server/frontend_dist/compute.html +6 -6
- mage_ai/server/frontend_dist/files.html +6 -6
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-data-products.html +6 -6
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/index.html +3 -3
- mage_ai/server/frontend_dist/manage/files.html +6 -6
- mage_ai/server/frontend_dist/manage/settings.html +6 -6
- mage_ai/server/frontend_dist/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist/manage/users.html +6 -6
- mage_ai/server/frontend_dist/manage.html +6 -6
- mage_ai/server/frontend_dist/oauth.html +5 -5
- mage_ai/server/frontend_dist/overview.html +6 -6
- mage_ai/server/frontend_dist/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist/pipelines.html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist/settings.html +3 -3
- mage_ai/server/frontend_dist/sign-in.html +15 -15
- mage_ai/server/frontend_dist/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist/templates.html +6 -6
- mage_ai/server/frontend_dist/terminal.html +6 -6
- mage_ai/server/frontend_dist/test.html +3 -3
- mage_ai/server/frontend_dist/triggers.html +6 -6
- mage_ai/server/frontend_dist/version-control.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/404.html +8 -8
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-25a7d985d5564fd3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3548-fa0792ddb88f4646.js → 3548-9d26185b3fb663b1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3763-61b542dafdbf5754.js → 3763-40780c6d1e4b261d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-176f445e1313f001.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{main-70b78159c2bb3fe1.js → main-384298e9133cec76.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-13a578bce3b7f30c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{overview-597b74828bf105db.js → overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipeline-runs-3edc6270c5b0e962.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7e737f6fc7e83e9b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-a5c0362763a21fa8.js → block-runs-284309877f3c5a5a.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-7acc7afc00df17c2.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5f4c8128b2413fd8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-1bdfda8edc9cf4a8.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-319ddbabc239e91b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{triggers-9cba3211434a8966.js → triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-68c003fb6a175cd7.js → webpack-481689d9989710cd.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/kcptwoOU-JJJg6Vwpkfmx/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/compute.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/index.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/oauth.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/overview.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +15 -15
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/templates.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/terminal.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/version-control.html +6 -6
- mage_ai/server/kernel_output_parser.py +4 -1
- mage_ai/server/scheduler_manager.py +12 -1
- mage_ai/server/server.py +69 -42
- mage_ai/server/utils/custom_output.py +284 -0
- mage_ai/server/utils/execute_custom_code.py +245 -0
- mage_ai/server/utils/output_display.py +123 -289
- mage_ai/server/websocket_server.py +116 -69
- mage_ai/services/aws/ecs/ecs.py +1 -0
- mage_ai/services/k8s/config.py +27 -4
- mage_ai/services/k8s/job_manager.py +6 -1
- mage_ai/services/k8s/utils.py +97 -0
- mage_ai/services/ssh/aws/emr/utils.py +8 -8
- mage_ai/settings/keys/auth.py +1 -0
- mage_ai/settings/platform/__init__.py +159 -38
- mage_ai/settings/platform/constants.py +5 -0
- mage_ai/settings/platform/utils.py +53 -10
- mage_ai/settings/repo.py +26 -12
- mage_ai/settings/server.py +128 -37
- mage_ai/shared/array.py +24 -1
- mage_ai/shared/complex.py +45 -0
- mage_ai/shared/config.py +2 -1
- mage_ai/shared/custom_logger.py +11 -0
- mage_ai/shared/dates.py +10 -6
- mage_ai/shared/files.py +63 -8
- mage_ai/shared/hash.py +33 -9
- mage_ai/shared/io.py +9 -5
- mage_ai/shared/models.py +82 -24
- mage_ai/shared/outputs.py +87 -0
- mage_ai/shared/parsers.py +144 -13
- mage_ai/shared/path_fixer.py +11 -7
- mage_ai/shared/singletons/__init__.py +0 -0
- mage_ai/shared/singletons/base.py +47 -0
- mage_ai/shared/singletons/memory.py +38 -0
- mage_ai/shared/strings.py +34 -1
- mage_ai/shared/yaml.py +24 -0
- mage_ai/streaming/sinks/oracledb.py +57 -0
- mage_ai/streaming/sinks/sink_factory.py +4 -0
- mage_ai/system/__init__.py +0 -0
- mage_ai/system/constants.py +14 -0
- mage_ai/system/memory/__init__.py +0 -0
- mage_ai/system/memory/constants.py +1 -0
- mage_ai/system/memory/manager.py +174 -0
- mage_ai/system/memory/presenters.py +158 -0
- mage_ai/system/memory/process.py +216 -0
- mage_ai/system/memory/samples.py +13 -0
- mage_ai/system/memory/utils.py +656 -0
- mage_ai/system/memory/wrappers.py +177 -0
- mage_ai/system/models.py +58 -0
- mage_ai/system/storage/__init__.py +0 -0
- mage_ai/system/storage/utils.py +29 -0
- mage_ai/tests/api/endpoints/mixins.py +2 -2
- mage_ai/tests/api/endpoints/test_blocks.py +2 -1
- mage_ai/tests/api/endpoints/test_custom_designs.py +4 -4
- mage_ai/tests/api/endpoints/test_pipeline_runs.py +2 -2
- mage_ai/tests/api/endpoints/test_projects.py +2 -1
- mage_ai/tests/api/operations/base/mixins.py +1 -1
- mage_ai/tests/api/operations/base/test_base.py +27 -27
- mage_ai/tests/api/operations/base/test_base_with_user_authentication.py +27 -27
- mage_ai/tests/api/operations/base/test_base_with_user_permissions.py +23 -23
- mage_ai/tests/api/operations/test_syncs.py +6 -4
- mage_ai/tests/api/resources/test_pipeline_resource.py +11 -4
- mage_ai/tests/authentication/oauth/test_utils.py +1 -1
- mage_ai/tests/authentication/providers/test_oidc.py +59 -0
- mage_ai/tests/base_test.py +2 -2
- mage_ai/tests/data/__init__.py +0 -0
- mage_ai/tests/data/models/__init__.py +0 -0
- mage_ai/tests/data_preparation/executors/test_block_executor.py +23 -16
- mage_ai/tests/data_preparation/git/test_git.py +4 -1
- mage_ai/tests/data_preparation/models/block/dynamic/test_combos.py +305 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +212 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_factory.py +360 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_variables.py +332 -0
- mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +2 -2
- mage_ai/tests/data_preparation/models/block/platform/test_mixins.py +1 -1
- mage_ai/tests/data_preparation/models/block/sql/utils/test_shared.py +26 -1
- mage_ai/tests/data_preparation/models/block/test_global_data_product.py +5 -2
- mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +5 -4
- mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +3 -0
- mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +9 -3
- mage_ai/tests/data_preparation/models/test_block.py +115 -120
- mage_ai/tests/data_preparation/models/test_blocks_helper.py +114 -0
- mage_ai/tests/data_preparation/models/test_global_data_product.py +41 -24
- mage_ai/tests/data_preparation/models/test_pipeline.py +9 -6
- mage_ai/tests/data_preparation/models/test_project.py +4 -1
- mage_ai/tests/data_preparation/models/test_utils.py +80 -0
- mage_ai/tests/data_preparation/models/test_variable.py +242 -69
- mage_ai/tests/data_preparation/models/variables/__init__.py +0 -0
- mage_ai/tests/data_preparation/models/variables/test_summarizer.py +481 -0
- mage_ai/tests/data_preparation/storage/shared/__init__.py +0 -0
- mage_ai/tests/data_preparation/test_repo_manager.py +6 -7
- mage_ai/tests/data_preparation/test_variable_manager.py +57 -48
- mage_ai/tests/factory.py +64 -43
- mage_ai/tests/orchestration/db/models/test_schedules.py +3 -3
- mage_ai/tests/orchestration/db/models/test_schedules_dynamic_blocks.py +279 -0
- mage_ai/tests/orchestration/test_pipeline_scheduler.py +1 -0
- mage_ai/tests/orchestration/triggers/test_global_data_product.py +141 -138
- mage_ai/tests/orchestration/triggers/test_utils.py +3 -2
- mage_ai/tests/server/test_server.py +19 -0
- mage_ai/tests/services/k8s/test_job_manager.py +27 -6
- mage_ai/tests/streaming/sinks/test_oracledb.py +38 -0
- mage_ai/tests/test_shared.py +61 -0
- mage_ai/usage_statistics/logger.py +7 -2
- mage_ai/utils/code.py +33 -19
- mage_ai/version_control/branch/utils.py +2 -1
- mage_ai/version_control/models.py +3 -2
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/METADATA +6 -3
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/RECORD +555 -454
- mage_ai/data_preparation/models/global_data_product/constants.py +0 -6
- mage_ai/server/frontend_dist/_next/static/_krrrgup_C-dPOpX36S8I/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1557-df144fbd8b2208c3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/4783-422429203610c318.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-d9c89527266296f7.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1dd1ed71d26c10d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-503049734a8b082f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-5b26eeda8aed8a7b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-8b793b3b696a2cd3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/KLL5mirre9d7_ZeEpaw3s/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-df144fbd8b2208c3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4783-422429203610c318.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-d9c89527266296f7.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1dd1ed71d26c10d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-503049734a8b082f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-5b26eeda8aed8a7b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-8b793b3b696a2cd3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- mage_ai/shared/memory.py +0 -90
- mage_ai/tests/data_preparation/models/block/dynamic/test_dynamic_helpers.py +0 -48
- /mage_ai/{tests/data_preparation/shared → ai/utils}/__init__.py +0 -0
- /mage_ai/server/frontend_dist/_next/static/{_krrrgup_C-dPOpX36S8I → UZLabyPgcxtZvp0O0EUUS}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{KLL5mirre9d7_ZeEpaw3s → kcptwoOU-JJJg6Vwpkfmx}/_ssgManifest.js +0 -0
- /mage_ai/tests/data_preparation/{shared → storage/shared}/test_secrets.py +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/top_level.txt +0 -0
|
@@ -61,6 +61,7 @@ from mage_ai.data_preparation.variable_manager import get_global_variables
|
|
|
61
61
|
from mage_ai.orchestration.db import db_connection, safe_db_query
|
|
62
62
|
from mage_ai.orchestration.db.errors import ValidationError
|
|
63
63
|
from mage_ai.orchestration.db.models.base import Base, BaseModel, classproperty
|
|
64
|
+
from mage_ai.orchestration.db.models.dynamic.controller import is_ready_to_process_data
|
|
64
65
|
from mage_ai.orchestration.db.models.schedules_project_platform import (
|
|
65
66
|
BlockRunProjectPlatformMixin,
|
|
66
67
|
PipelineRunProjectPlatformMixin,
|
|
@@ -105,7 +106,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
105
106
|
event_matchers = relationship(
|
|
106
107
|
'EventMatcher',
|
|
107
108
|
secondary=pipeline_schedule_event_matcher_association_table,
|
|
108
|
-
back_populates='pipeline_schedules'
|
|
109
|
+
back_populates='pipeline_schedules',
|
|
109
110
|
)
|
|
110
111
|
|
|
111
112
|
@classproperty
|
|
@@ -123,10 +124,13 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
123
124
|
@validates('name')
|
|
124
125
|
def validate_name(self, key, value):
|
|
125
126
|
if not value or len(value) == 0:
|
|
126
|
-
raise ValidationError(
|
|
127
|
-
key
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
raise ValidationError(
|
|
128
|
+
f'{key} cannot be empty.',
|
|
129
|
+
metadata=dict(
|
|
130
|
+
key=key,
|
|
131
|
+
value=value,
|
|
132
|
+
),
|
|
133
|
+
)
|
|
130
134
|
|
|
131
135
|
return value
|
|
132
136
|
|
|
@@ -140,33 +144,26 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
140
144
|
@classmethod
|
|
141
145
|
def fetch_latest_pipeline_runs_without_retries(self, ids: List[int]) -> List:
|
|
142
146
|
sub_query = (
|
|
143
|
-
PipelineRun.
|
|
144
|
-
select(
|
|
147
|
+
PipelineRun.select(
|
|
145
148
|
PipelineRun.id,
|
|
146
149
|
PipelineRun.execution_date,
|
|
147
150
|
PipelineRun.started_at,
|
|
148
151
|
PipelineRun.status,
|
|
149
152
|
(
|
|
150
|
-
func.
|
|
151
|
-
|
|
152
|
-
over(
|
|
153
|
+
func.row_number()
|
|
154
|
+
.over(
|
|
153
155
|
partition_by=PipelineRun.execution_date,
|
|
154
|
-
order_by=(PipelineRun.started_at.desc(), PipelineRun.id.desc())
|
|
155
|
-
)
|
|
156
|
-
label('n_row_number')
|
|
157
|
-
)
|
|
158
|
-
).
|
|
159
|
-
filter(
|
|
156
|
+
order_by=(PipelineRun.started_at.desc(), PipelineRun.id.desc()),
|
|
157
|
+
)
|
|
158
|
+
.label('n_row_number')
|
|
159
|
+
),
|
|
160
|
+
).filter(
|
|
160
161
|
PipelineRun.pipeline_schedule_id.in_(ids),
|
|
161
162
|
)
|
|
162
163
|
).subquery()
|
|
163
164
|
|
|
164
|
-
query = (
|
|
165
|
-
|
|
166
|
-
select(sub_query).
|
|
167
|
-
where(
|
|
168
|
-
text('n_row_number = 1'),
|
|
169
|
-
)
|
|
165
|
+
query = PipelineRun.select(sub_query).where(
|
|
166
|
+
text('n_row_number = 1'),
|
|
170
167
|
)
|
|
171
168
|
|
|
172
169
|
query.cache = True
|
|
@@ -182,7 +179,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
182
179
|
if project_platform_activated():
|
|
183
180
|
return self.pipeline_project_platform
|
|
184
181
|
|
|
185
|
-
return Pipeline.get(self.pipeline_uuid)
|
|
182
|
+
return Pipeline.get(self.pipeline_uuid, repo_path=get_repo_path())
|
|
186
183
|
|
|
187
184
|
@property
|
|
188
185
|
def pipeline_in_progress_runs_count(self) -> int:
|
|
@@ -193,12 +190,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
193
190
|
PipelineRun.select(func.count(PipelineRun.id))
|
|
194
191
|
.filter(
|
|
195
192
|
PipelineRun.pipeline_schedule_id == self.id,
|
|
196
|
-
PipelineRun.status.in_(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
]
|
|
201
|
-
),
|
|
193
|
+
PipelineRun.status.in_([
|
|
194
|
+
PipelineRun.PipelineRunStatus.INITIAL,
|
|
195
|
+
PipelineRun.PipelineRunStatus.RUNNING,
|
|
196
|
+
]),
|
|
202
197
|
(coalesce(PipelineRun.passed_sla, False).is_(False)),
|
|
203
198
|
)
|
|
204
199
|
.scalar()
|
|
@@ -227,8 +222,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
227
222
|
|
|
228
223
|
@validates('schedule_interval')
|
|
229
224
|
def validate_schedule_interval(self, key, schedule_interval):
|
|
230
|
-
if schedule_interval and schedule_interval not in
|
|
231
|
-
[e.value for e in ScheduleInterval]:
|
|
225
|
+
if schedule_interval and schedule_interval not in [e.value for e in ScheduleInterval]:
|
|
232
226
|
if not croniter.is_valid(schedule_interval):
|
|
233
227
|
raise ValueError('Cron expression is invalid.')
|
|
234
228
|
|
|
@@ -258,23 +252,22 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
258
252
|
@property
|
|
259
253
|
def tag_associations(self):
|
|
260
254
|
return (
|
|
261
|
-
TagAssociation.
|
|
262
|
-
select(
|
|
255
|
+
TagAssociation.select(
|
|
263
256
|
TagAssociation.id,
|
|
264
257
|
TagAssociation.tag_id,
|
|
265
258
|
TagAssociation.taggable_id,
|
|
266
259
|
TagAssociation.taggable_type,
|
|
267
260
|
Tag.name,
|
|
268
|
-
)
|
|
269
|
-
join(
|
|
261
|
+
)
|
|
262
|
+
.join(
|
|
270
263
|
Tag,
|
|
271
264
|
Tag.id == TagAssociation.tag_id,
|
|
272
|
-
)
|
|
273
|
-
filter(
|
|
265
|
+
)
|
|
266
|
+
.filter(
|
|
274
267
|
TagAssociation.taggable_id == self.id,
|
|
275
268
|
TagAssociation.taggable_type == self.__class__.__name__,
|
|
276
|
-
)
|
|
277
|
-
all()
|
|
269
|
+
)
|
|
270
|
+
.all()
|
|
278
271
|
)
|
|
279
272
|
|
|
280
273
|
@classmethod
|
|
@@ -325,8 +318,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
325
318
|
continue
|
|
326
319
|
|
|
327
320
|
last_enabled_at = trigger_config.last_enabled_at
|
|
328
|
-
if
|
|
329
|
-
|
|
321
|
+
if (
|
|
322
|
+
trigger_config.status == ScheduleStatus.ACTIVE
|
|
323
|
+
and trigger_config.last_enabled_at is None
|
|
324
|
+
):
|
|
330
325
|
last_enabled_at = datetime.now(tz=pytz.UTC)
|
|
331
326
|
trigger_config.last_enabled_at = last_enabled_at
|
|
332
327
|
add_or_update_trigger_for_pipeline_and_persist(
|
|
@@ -335,6 +330,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
335
330
|
)
|
|
336
331
|
|
|
337
332
|
kwargs = dict(
|
|
333
|
+
description=trigger_config.description,
|
|
338
334
|
last_enabled_at=last_enabled_at,
|
|
339
335
|
name=trigger_config.name,
|
|
340
336
|
pipeline_uuid=trigger_config.pipeline_uuid,
|
|
@@ -345,12 +341,14 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
345
341
|
sla=trigger_config.sla,
|
|
346
342
|
start_time=trigger_config.start_time,
|
|
347
343
|
status=trigger_config.status,
|
|
344
|
+
token=trigger_config.token,
|
|
348
345
|
variables=trigger_config.variables,
|
|
349
346
|
)
|
|
350
347
|
|
|
351
348
|
if existing_trigger:
|
|
352
349
|
if any([
|
|
353
350
|
existing_trigger.last_enabled_at != kwargs.get('last_enabled_at'),
|
|
351
|
+
existing_trigger.description != kwargs.get('description'),
|
|
354
352
|
existing_trigger.name != kwargs.get('name'),
|
|
355
353
|
existing_trigger.pipeline_uuid != kwargs.get('pipeline_uuid'),
|
|
356
354
|
existing_trigger.repo_path != kwargs.get('repo_path'),
|
|
@@ -360,13 +358,15 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
360
358
|
existing_trigger.sla != kwargs.get('sla'),
|
|
361
359
|
existing_trigger.start_time != kwargs.get('start_time'),
|
|
362
360
|
existing_trigger.status != kwargs.get('status'),
|
|
361
|
+
existing_trigger.token != kwargs.get('token'),
|
|
363
362
|
existing_trigger.variables != kwargs.get('variables'),
|
|
364
363
|
]):
|
|
365
|
-
if existing_trigger.token is None:
|
|
364
|
+
if existing_trigger.token is None and kwargs.get('token') is None:
|
|
366
365
|
kwargs['token'] = uuid.uuid4().hex
|
|
367
366
|
existing_trigger.update(**kwargs)
|
|
368
367
|
else:
|
|
369
|
-
kwargs
|
|
368
|
+
if kwargs.get('token') is None:
|
|
369
|
+
kwargs['token'] = uuid.uuid4().hex
|
|
370
370
|
triggers_to_create.append(kwargs)
|
|
371
371
|
|
|
372
372
|
db_connection.session.bulk_save_objects(
|
|
@@ -424,16 +424,19 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
424
424
|
if self.schedule_interval is None:
|
|
425
425
|
return None
|
|
426
426
|
|
|
427
|
-
if
|
|
428
|
-
|
|
427
|
+
if (
|
|
428
|
+
self.schedule_interval == ScheduleInterval.ONCE
|
|
429
|
+
or self.schedule_interval == ScheduleInterval.ALWAYS_ON
|
|
430
|
+
):
|
|
429
431
|
current_execution_date = now
|
|
430
432
|
elif self.schedule_interval == ScheduleInterval.DAILY:
|
|
431
433
|
current_execution_date = now.replace(second=0, microsecond=0, minute=0, hour=0)
|
|
432
434
|
elif self.schedule_interval == ScheduleInterval.HOURLY:
|
|
433
435
|
current_execution_date = now.replace(second=0, microsecond=0, minute=0)
|
|
434
436
|
elif self.schedule_interval == ScheduleInterval.WEEKLY:
|
|
435
|
-
current_execution_date = now.replace(
|
|
436
|
-
|
|
437
|
+
current_execution_date = now.replace(
|
|
438
|
+
second=0, microsecond=0, minute=0, hour=0
|
|
439
|
+
) - timedelta(days=now.weekday())
|
|
437
440
|
elif self.schedule_interval == ScheduleInterval.MONTHLY:
|
|
438
441
|
current_execution_date = now.replace(second=0, microsecond=0, minute=0, hour=0, day=1)
|
|
439
442
|
else:
|
|
@@ -480,8 +483,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
480
483
|
if current_execution_date is None:
|
|
481
484
|
return None
|
|
482
485
|
|
|
483
|
-
if
|
|
484
|
-
|
|
486
|
+
if (
|
|
487
|
+
self.schedule_interval == ScheduleInterval.ONCE
|
|
488
|
+
or self.schedule_interval == ScheduleInterval.ALWAYS_ON
|
|
489
|
+
):
|
|
485
490
|
pass
|
|
486
491
|
elif self.schedule_interval == ScheduleInterval.DAILY:
|
|
487
492
|
next_execution_date = current_execution_date + timedelta(days=1)
|
|
@@ -502,6 +507,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
502
507
|
self,
|
|
503
508
|
previous_runtimes: List[int] = None,
|
|
504
509
|
pipeline: Pipeline = None,
|
|
510
|
+
repo_config=None,
|
|
505
511
|
) -> bool:
|
|
506
512
|
"""
|
|
507
513
|
Determine whether a pipeline schedule should be executed based on its configuration and
|
|
@@ -532,13 +538,20 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
532
538
|
if self.status != ScheduleStatus.ACTIVE:
|
|
533
539
|
return False
|
|
534
540
|
|
|
535
|
-
if
|
|
536
|
-
|
|
537
|
-
|
|
541
|
+
if (
|
|
542
|
+
not self.landing_time_enabled()
|
|
543
|
+
and self.start_time is not None
|
|
544
|
+
and compare(now, self.start_time.replace(tzinfo=pytz.UTC)) == -1
|
|
545
|
+
):
|
|
538
546
|
return False
|
|
539
547
|
|
|
540
548
|
try:
|
|
541
|
-
|
|
549
|
+
if pipeline is None:
|
|
550
|
+
pipeline = Pipeline.get(
|
|
551
|
+
self.pipeline_uuid,
|
|
552
|
+
repo_path=get_repo_path(),
|
|
553
|
+
repo_config=repo_config,
|
|
554
|
+
)
|
|
542
555
|
except Exception:
|
|
543
556
|
print(
|
|
544
557
|
f'[WARNING] Pipeline {self.pipeline_uuid} cannot be found '
|
|
@@ -550,7 +563,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
550
563
|
pipeline_run_count = self.pipeline_runs_count
|
|
551
564
|
if pipeline_run_count == 0:
|
|
552
565
|
return True
|
|
553
|
-
executor_count =
|
|
566
|
+
executor_count = pipeline.executor_count
|
|
554
567
|
# Used by streaming pipeline to launch multiple executors
|
|
555
568
|
if executor_count > 1 and pipeline_run_count < executor_count:
|
|
556
569
|
return True
|
|
@@ -585,16 +598,21 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
585
598
|
the initial pipeline run.
|
|
586
599
|
"""
|
|
587
600
|
create_initial_pipeline_run = self.get_settings().create_initial_pipeline_run
|
|
588
|
-
avoid_initial_pipeline_run =
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
601
|
+
avoid_initial_pipeline_run = (
|
|
602
|
+
compare(
|
|
603
|
+
current_execution_date,
|
|
604
|
+
self.last_enabled_at,
|
|
605
|
+
)
|
|
606
|
+
== -1
|
|
607
|
+
if not create_initial_pipeline_run
|
|
608
|
+
else False
|
|
609
|
+
)
|
|
592
610
|
|
|
593
611
|
# If the execution date is before start time or date pipeline schedule
|
|
594
612
|
# was last enabled, don't schedule it.
|
|
595
613
|
if (
|
|
596
|
-
self.start_time is not None
|
|
597
|
-
compare(current_execution_date, self.start_time.replace(tzinfo=pytz.UTC)) == -1
|
|
614
|
+
self.start_time is not None
|
|
615
|
+
and compare(current_execution_date, self.start_time.replace(tzinfo=pytz.UTC)) == -1
|
|
598
616
|
) or avoid_initial_pipeline_run:
|
|
599
617
|
return False
|
|
600
618
|
|
|
@@ -648,27 +666,17 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
648
666
|
pipeline_run=None,
|
|
649
667
|
sample_size: int = None,
|
|
650
668
|
):
|
|
651
|
-
pipeline_runs = (
|
|
652
|
-
PipelineRun.
|
|
653
|
-
|
|
654
|
-
filter(
|
|
655
|
-
PipelineRun.pipeline_schedule_id == self.id,
|
|
656
|
-
PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
|
|
657
|
-
)
|
|
669
|
+
pipeline_runs = PipelineRun.query.filter(
|
|
670
|
+
PipelineRun.pipeline_schedule_id == self.id,
|
|
671
|
+
PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
|
|
658
672
|
)
|
|
659
673
|
|
|
660
674
|
if pipeline_run:
|
|
661
|
-
pipeline_runs = (
|
|
662
|
-
|
|
663
|
-
filter(
|
|
664
|
-
PipelineRun.id != pipeline_run.id,
|
|
665
|
-
)
|
|
675
|
+
pipeline_runs = pipeline_runs.filter(
|
|
676
|
+
PipelineRun.id != pipeline_run.id,
|
|
666
677
|
)
|
|
667
678
|
|
|
668
|
-
pipeline_runs = (
|
|
669
|
-
pipeline_runs.
|
|
670
|
-
order_by(PipelineRun.execution_date.desc())
|
|
671
|
-
)
|
|
679
|
+
pipeline_runs = pipeline_runs.order_by(PipelineRun.execution_date.desc())
|
|
672
680
|
|
|
673
681
|
if sample_size:
|
|
674
682
|
pipeline_runs = pipeline_runs.limit(sample_size)
|
|
@@ -701,15 +709,11 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
|
|
|
701
709
|
)
|
|
702
710
|
|
|
703
711
|
for pr in pipeline_runs:
|
|
704
|
-
runtime = (
|
|
705
|
-
pr.completed_at - pr.created_at
|
|
706
|
-
).total_seconds()
|
|
712
|
+
runtime = (pr.completed_at - pr.created_at).total_seconds()
|
|
707
713
|
previous_runtimes.append(runtime)
|
|
708
714
|
|
|
709
715
|
if pipeline_run:
|
|
710
|
-
runtime = (
|
|
711
|
-
pipeline_run.completed_at - pipeline_run.created_at
|
|
712
|
-
).total_seconds()
|
|
716
|
+
runtime = (pipeline_run.completed_at - pipeline_run.created_at).total_seconds()
|
|
713
717
|
previous_runtimes = [runtime] + previous_runtimes
|
|
714
718
|
|
|
715
719
|
return previous_runtimes[:sample_size_to_use]
|
|
@@ -761,8 +765,10 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
761
765
|
super().__init__(**kwargs)
|
|
762
766
|
|
|
763
767
|
def __repr__(self):
|
|
764
|
-
return
|
|
765
|
-
|
|
768
|
+
return (
|
|
769
|
+
f'PipelineRun(id={self.id}, pipeline_uuid={self.pipeline_uuid},'
|
|
770
|
+
f' execution_date={self.execution_date})'
|
|
771
|
+
)
|
|
766
772
|
|
|
767
773
|
@property
|
|
768
774
|
def block_runs_count(self) -> int:
|
|
@@ -774,36 +780,35 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
774
780
|
|
|
775
781
|
@property
|
|
776
782
|
def execution_partition(self) -> str:
|
|
777
|
-
if
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
783
|
+
if (
|
|
784
|
+
self.variables
|
|
785
|
+
and isinstance(self.variables, dict)
|
|
786
|
+
and self.variables.get('execution_partition')
|
|
787
|
+
):
|
|
781
788
|
return self.variables.get('execution_partition')
|
|
782
789
|
if self.execution_date is None:
|
|
783
790
|
return str(self.pipeline_schedule_id)
|
|
784
791
|
else:
|
|
785
792
|
return '/'.join([
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
793
|
+
str(self.pipeline_schedule_id),
|
|
794
|
+
self.execution_date.strftime(format='%Y%m%dT%H%M%S'),
|
|
795
|
+
])
|
|
789
796
|
|
|
790
797
|
@property
|
|
791
798
|
def initial_block_runs(self) -> List['BlockRun']:
|
|
792
|
-
return [b for b in self.block_runs
|
|
793
|
-
if b.status == BlockRun.BlockRunStatus.INITIAL]
|
|
799
|
+
return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.INITIAL]
|
|
794
800
|
|
|
795
801
|
@property
|
|
796
802
|
def running_block_runs(self) -> List['BlockRun']:
|
|
797
|
-
return [
|
|
798
|
-
b for b in self.block_runs
|
|
799
|
-
if b.status == BlockRun.BlockRunStatus.RUNNING
|
|
800
|
-
]
|
|
803
|
+
return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.RUNNING]
|
|
801
804
|
|
|
802
805
|
@property
|
|
803
806
|
def queued_or_running_block_runs(self) -> List['BlockRun']:
|
|
804
807
|
return [
|
|
805
|
-
b
|
|
806
|
-
|
|
808
|
+
b
|
|
809
|
+
for b in self.block_runs
|
|
810
|
+
if b.status
|
|
811
|
+
in [
|
|
807
812
|
BlockRun.BlockRunStatus.QUEUED,
|
|
808
813
|
BlockRun.BlockRunStatus.RUNNING,
|
|
809
814
|
]
|
|
@@ -811,25 +816,22 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
811
816
|
|
|
812
817
|
@property
|
|
813
818
|
def completed_block_runs(self) -> List['BlockRun']:
|
|
814
|
-
return [b for b in self.block_runs
|
|
815
|
-
if b.status == BlockRun.BlockRunStatus.COMPLETED]
|
|
819
|
+
return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.COMPLETED]
|
|
816
820
|
|
|
817
821
|
@property
|
|
818
822
|
def failed_block_runs(self) -> List['BlockRun']:
|
|
819
|
-
return [b for b in self.block_runs
|
|
820
|
-
if b.status == BlockRun.BlockRunStatus.FAILED]
|
|
823
|
+
return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.FAILED]
|
|
821
824
|
|
|
822
825
|
@property
|
|
823
826
|
def pipeline(self) -> 'Pipeline':
|
|
824
827
|
if project_platform_activated():
|
|
825
828
|
return self.pipeline_project_platform
|
|
826
829
|
|
|
827
|
-
return Pipeline.get(self.pipeline_uuid)
|
|
830
|
+
return Pipeline.get(self.pipeline_uuid, repo_path=get_repo_path())
|
|
828
831
|
|
|
829
832
|
@property
|
|
830
833
|
def pipeline_type(self) -> PipelineType:
|
|
831
|
-
pipeline =
|
|
832
|
-
|
|
834
|
+
pipeline = self.pipeline
|
|
833
835
|
return pipeline.type if pipeline is not None else None
|
|
834
836
|
|
|
835
837
|
@property
|
|
@@ -862,13 +864,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
862
864
|
pipeline_schedule_id: int = None,
|
|
863
865
|
sample_size: int = None,
|
|
864
866
|
):
|
|
865
|
-
pipeline_runs = (
|
|
866
|
-
self.
|
|
867
|
-
|
|
868
|
-
filter(
|
|
869
|
-
self.pipeline_uuid == pipeline_uuid,
|
|
870
|
-
self.status == self.PipelineRunStatus.COMPLETED,
|
|
871
|
-
)
|
|
867
|
+
pipeline_runs = self.query.filter(
|
|
868
|
+
self.pipeline_uuid == pipeline_uuid,
|
|
869
|
+
self.status == self.PipelineRunStatus.COMPLETED,
|
|
872
870
|
)
|
|
873
871
|
|
|
874
872
|
if pipeline_run_id is not None:
|
|
@@ -985,7 +983,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
985
983
|
if block and block.replicated_block:
|
|
986
984
|
arr.add(block.uuid)
|
|
987
985
|
|
|
988
|
-
return arr
|
|
986
|
+
return list(arr)
|
|
989
987
|
|
|
990
988
|
completed_block_uuids = _build_block_uuids(self.completed_block_runs)
|
|
991
989
|
finished_block_uuids = _build_block_uuids(self.block_runs)
|
|
@@ -1042,6 +1040,13 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1042
1040
|
|
|
1043
1041
|
executable_block_runs = []
|
|
1044
1042
|
for block_run in self.initial_block_runs:
|
|
1043
|
+
block = pipeline.get_block(block_run.block_uuid)
|
|
1044
|
+
|
|
1045
|
+
if block is not None and block.is_dynamic_streaming:
|
|
1046
|
+
if is_ready_to_process_data(pipeline, block_run, block_runs_all):
|
|
1047
|
+
executable_block_runs.append(block_run)
|
|
1048
|
+
continue
|
|
1049
|
+
|
|
1045
1050
|
completed = False
|
|
1046
1051
|
upstream_block_uuids_override = None
|
|
1047
1052
|
|
|
@@ -1065,13 +1070,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1065
1070
|
elif metrics.get('upstream_blocks'):
|
|
1066
1071
|
upstream_block_uuids_override = metrics.get('upstream_blocks') or None
|
|
1067
1072
|
|
|
1068
|
-
block = pipeline.get_block(block_run.block_uuid)
|
|
1069
|
-
|
|
1070
1073
|
if block and is_dynamic_block_child(block):
|
|
1071
1074
|
if check_all_dynamic_upstreams_completed(
|
|
1072
|
-
block,
|
|
1073
|
-
block_runs_all,
|
|
1074
|
-
execution_partition=self.execution_partition
|
|
1075
|
+
block, block_runs_all, execution_partition=self.execution_partition
|
|
1075
1076
|
):
|
|
1076
1077
|
completed = True
|
|
1077
1078
|
else:
|
|
@@ -1086,11 +1087,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1086
1087
|
uuids_to_check.append(upstream_block_uuid)
|
|
1087
1088
|
|
|
1088
1089
|
if allow_blocks_to_fail:
|
|
1089
|
-
completed = all(uuid in finished_block_uuids
|
|
1090
|
-
for uuid in uuids_to_check)
|
|
1090
|
+
completed = all(uuid in finished_block_uuids for uuid in uuids_to_check)
|
|
1091
1091
|
else:
|
|
1092
|
-
completed = all(uuid in completed_block_uuids
|
|
1093
|
-
for uuid in uuids_to_check)
|
|
1092
|
+
completed = all(uuid in completed_block_uuids for uuid in uuids_to_check)
|
|
1094
1093
|
else:
|
|
1095
1094
|
metrics = block_run.metrics
|
|
1096
1095
|
|
|
@@ -1126,15 +1125,17 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1126
1125
|
upstream_block_uuids_override = [
|
|
1127
1126
|
controller_block_uuid,
|
|
1128
1127
|
]
|
|
1129
|
-
elif
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1128
|
+
elif (
|
|
1129
|
+
metrics.get('controller')
|
|
1130
|
+
and metrics.get('child')
|
|
1131
|
+
and not metrics.get('run_in_parallel')
|
|
1132
|
+
and metrics.get('upstream_block_uuids')
|
|
1133
|
+
):
|
|
1134
1134
|
upstream_block_uuids_override = metrics.get('upstream_block_uuids')
|
|
1135
1135
|
elif metrics and metrics.get('dynamic_upstream_block_uuids'):
|
|
1136
|
-
upstream_block_uuids_override =
|
|
1136
|
+
upstream_block_uuids_override = (
|
|
1137
1137
|
metrics.get('dynamic_upstream_block_uuids') or []
|
|
1138
|
+
)
|
|
1138
1139
|
|
|
1139
1140
|
incomplete = False
|
|
1140
1141
|
if block:
|
|
@@ -1164,15 +1165,20 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1164
1165
|
up_uuids.append(upstream_block.uuid)
|
|
1165
1166
|
|
|
1166
1167
|
if len(up_uuids_dynamic_children) >= 1:
|
|
1167
|
-
upstream_block_uuids_override =
|
|
1168
|
-
(upstream_block_uuids_override or [])
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1168
|
+
upstream_block_uuids_override = (
|
|
1169
|
+
(upstream_block_uuids_override or [])
|
|
1170
|
+
+ up_uuids
|
|
1171
|
+
+ up_uuids_dynamic_children
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
completed = (
|
|
1175
|
+
not incomplete
|
|
1176
|
+
and block is not None
|
|
1177
|
+
and block.all_upstream_blocks_completed(
|
|
1173
1178
|
completed_block_uuids,
|
|
1174
1179
|
upstream_block_uuids_override,
|
|
1175
1180
|
)
|
|
1181
|
+
)
|
|
1176
1182
|
|
|
1177
1183
|
if completed:
|
|
1178
1184
|
executable_block_runs.append(block_run)
|
|
@@ -1203,15 +1209,19 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1203
1209
|
pipeline = self.pipeline
|
|
1204
1210
|
|
|
1205
1211
|
failed_block_uuids = set(
|
|
1206
|
-
b.block_uuid
|
|
1207
|
-
|
|
1212
|
+
b.block_uuid
|
|
1213
|
+
for b in self.block_runs
|
|
1214
|
+
if b.status
|
|
1215
|
+
in [
|
|
1208
1216
|
BlockRun.BlockRunStatus.UPSTREAM_FAILED,
|
|
1209
1217
|
BlockRun.BlockRunStatus.FAILED,
|
|
1210
1218
|
]
|
|
1211
1219
|
)
|
|
1212
1220
|
condition_failed_block_uuids = set(
|
|
1213
|
-
b.block_uuid
|
|
1214
|
-
|
|
1221
|
+
b.block_uuid
|
|
1222
|
+
for b in self.block_runs
|
|
1223
|
+
if b.status
|
|
1224
|
+
in [
|
|
1215
1225
|
BlockRun.BlockRunStatus.CONDITION_FAILED,
|
|
1216
1226
|
]
|
|
1217
1227
|
)
|
|
@@ -1237,13 +1247,13 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1237
1247
|
upstream_block_uuids = block.upstream_block_uuids
|
|
1238
1248
|
# If an upstream dynamic child fails, the block_run.block_uuid won’t match.
|
|
1239
1249
|
if block_run.block_uuid == block.uuid:
|
|
1240
|
-
block_uuids = list(block_uuids) + [
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
):
|
|
1250
|
+
block_uuids = list(block_uuids) + [
|
|
1251
|
+
pipeline.get_block(
|
|
1252
|
+
block_inner,
|
|
1253
|
+
).uuid
|
|
1254
|
+
for block_inner in block_uuids
|
|
1255
|
+
]
|
|
1256
|
+
if any(b in block_uuids for b in upstream_block_uuids):
|
|
1247
1257
|
block_run.update(status=status)
|
|
1248
1258
|
updated_status = True
|
|
1249
1259
|
|
|
@@ -1299,9 +1309,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1299
1309
|
@classmethod
|
|
1300
1310
|
@safe_db_query
|
|
1301
1311
|
def batch_update_status(self, pipeline_run_ids: List[int], status):
|
|
1302
|
-
PipelineRun.query.filter(PipelineRun.id.in_(pipeline_run_ids)).update(
|
|
1303
|
-
PipelineRun.status: status
|
|
1304
|
-
|
|
1312
|
+
PipelineRun.query.filter(PipelineRun.id.in_(pipeline_run_ids)).update(
|
|
1313
|
+
{PipelineRun.status: status}, synchronize_session=False
|
|
1314
|
+
)
|
|
1305
1315
|
db_connection.session.commit()
|
|
1306
1316
|
|
|
1307
1317
|
@classmethod
|
|
@@ -1365,9 +1375,12 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1365
1375
|
)
|
|
1366
1376
|
|
|
1367
1377
|
from mage_ai.usage_statistics.logger import UsageStatisticLogger
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1378
|
+
|
|
1379
|
+
asyncio.run(
|
|
1380
|
+
UsageStatisticLogger().pipeline_runs_impression(
|
|
1381
|
+
lambda: self.query.filter(self.status == self.PipelineRunStatus.COMPLETED).count(),
|
|
1382
|
+
)
|
|
1383
|
+
)
|
|
1371
1384
|
|
|
1372
1385
|
@safe_db_query
|
|
1373
1386
|
def create_block_run(
|
|
@@ -1407,11 +1420,11 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1407
1420
|
if block.replicated_block:
|
|
1408
1421
|
replicated_block = pipeline.get_block(block.replicated_block)
|
|
1409
1422
|
if replicated_block:
|
|
1410
|
-
block_uuid =
|
|
1423
|
+
block_uuid = block.uuid_replicated
|
|
1411
1424
|
else:
|
|
1412
1425
|
raise Exception(
|
|
1413
|
-
f'Replicated block {block.replicated_block} '
|
|
1414
|
-
f'does not exist in pipeline {pipeline.uuid}.',
|
|
1426
|
+
f'Replicated block {block.replicated_block} '
|
|
1427
|
+
+ f'does not exist in pipeline {pipeline.uuid}.',
|
|
1415
1428
|
)
|
|
1416
1429
|
elif block.is_data_integration():
|
|
1417
1430
|
controller_uuid = block.controller_uuid
|
|
@@ -1422,10 +1435,12 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1422
1435
|
|
|
1423
1436
|
block_arr.append((
|
|
1424
1437
|
controller_uuid,
|
|
1425
|
-
dict(
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1438
|
+
dict(
|
|
1439
|
+
metrics=dict(
|
|
1440
|
+
controller=1,
|
|
1441
|
+
original_block_uuid=block_uuid,
|
|
1442
|
+
)
|
|
1443
|
+
),
|
|
1429
1444
|
))
|
|
1430
1445
|
|
|
1431
1446
|
flags = []
|
|
@@ -1448,9 +1463,11 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1448
1463
|
flags.append(DynamicBlockFlag.REDUCE_OUTPUT)
|
|
1449
1464
|
|
|
1450
1465
|
if len(flags) >= 1:
|
|
1451
|
-
create_options['metrics'] = dict(
|
|
1452
|
-
|
|
1453
|
-
|
|
1466
|
+
create_options['metrics'] = dict(
|
|
1467
|
+
metadata=dict(
|
|
1468
|
+
flags=flags,
|
|
1469
|
+
)
|
|
1470
|
+
)
|
|
1454
1471
|
|
|
1455
1472
|
block_arr.append((block_uuid, create_options))
|
|
1456
1473
|
|
|
@@ -1467,10 +1484,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1467
1484
|
return [self.create_block_run(block_uuid, **options) for block_uuid, options in block_arr]
|
|
1468
1485
|
|
|
1469
1486
|
def any_blocks_failed(self) -> bool:
|
|
1470
|
-
return any(
|
|
1471
|
-
b.status == BlockRun.BlockRunStatus.FAILED
|
|
1472
|
-
for b in self.block_runs
|
|
1473
|
-
)
|
|
1487
|
+
return any(b.status == BlockRun.BlockRunStatus.FAILED for b in self.block_runs)
|
|
1474
1488
|
|
|
1475
1489
|
def all_blocks_completed(self, include_failed_blocks: bool = False) -> bool:
|
|
1476
1490
|
statuses = [
|
|
@@ -1518,16 +1532,19 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1518
1532
|
variables['event'] = merge_dict(variables.get('event', {}), event_variables)
|
|
1519
1533
|
variables['execution_date'] = self.execution_date
|
|
1520
1534
|
variables['execution_partition'] = self.execution_partition
|
|
1535
|
+
variables['pipeline_run_id'] = self.id
|
|
1521
1536
|
|
|
1522
1537
|
interval_end_datetime = variables.get('interval_end_datetime')
|
|
1523
1538
|
interval_seconds = variables.get('interval_seconds')
|
|
1524
1539
|
interval_start_datetime = variables.get('interval_start_datetime')
|
|
1525
1540
|
interval_start_datetime_previous = variables.get('interval_start_datetime_previous')
|
|
1526
1541
|
|
|
1527
|
-
if
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1542
|
+
if (
|
|
1543
|
+
interval_end_datetime
|
|
1544
|
+
or interval_seconds
|
|
1545
|
+
or interval_start_datetime
|
|
1546
|
+
or interval_start_datetime_previous
|
|
1547
|
+
):
|
|
1531
1548
|
if interval_end_datetime:
|
|
1532
1549
|
try:
|
|
1533
1550
|
variables['interval_end_datetime'] = dateutil.parser.parse(
|
|
@@ -1585,9 +1602,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
|
|
|
1585
1602
|
# to call get_next again to go back to the original state
|
|
1586
1603
|
cron_itr.get_next()
|
|
1587
1604
|
interval_end_datetime = cron_itr.get_next(datetime)
|
|
1588
|
-
interval_seconds = (
|
|
1589
|
-
interval_end_datetime.timestamp() - current.timestamp()
|
|
1590
|
-
)
|
|
1605
|
+
interval_seconds = interval_end_datetime.timestamp() - current.timestamp()
|
|
1591
1606
|
except Exception:
|
|
1592
1607
|
pass
|
|
1593
1608
|
|
|
@@ -1633,7 +1648,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
|
|
|
1633
1648
|
|
|
1634
1649
|
@property
|
|
1635
1650
|
def logs(self):
|
|
1636
|
-
pipeline =
|
|
1651
|
+
pipeline = self.pipeline_run.pipeline_schedule.pipeline
|
|
1637
1652
|
return LoggerManagerFactory.get_logger_manager(
|
|
1638
1653
|
pipeline_uuid=pipeline.uuid,
|
|
1639
1654
|
block_uuid=clean_name(self.block_uuid),
|
|
@@ -1645,7 +1660,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
|
|
|
1645
1660
|
if project_platform_activated():
|
|
1646
1661
|
return await self.logs_async_project_platform(repo_path=repo_path)
|
|
1647
1662
|
|
|
1648
|
-
pipeline = await Pipeline.get_async(self.pipeline_run.pipeline_uuid)
|
|
1663
|
+
pipeline = await Pipeline.get_async(self.pipeline_run.pipeline_uuid, repo_path=repo_path)
|
|
1649
1664
|
return await LoggerManagerFactory.get_logger_manager(
|
|
1650
1665
|
pipeline_uuid=pipeline.uuid,
|
|
1651
1666
|
block_uuid=clean_name(self.block_uuid),
|
|
@@ -1656,17 +1671,15 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
|
|
|
1656
1671
|
@classmethod
|
|
1657
1672
|
@safe_db_query
|
|
1658
1673
|
def batch_update_status(self, block_run_ids: List[int], status):
|
|
1659
|
-
BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).update(
|
|
1660
|
-
BlockRun.status: status
|
|
1661
|
-
|
|
1674
|
+
BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).update(
|
|
1675
|
+
{BlockRun.status: status}, synchronize_session=False
|
|
1676
|
+
)
|
|
1662
1677
|
db_connection.session.commit()
|
|
1663
1678
|
|
|
1664
1679
|
@classmethod
|
|
1665
1680
|
@safe_db_query
|
|
1666
1681
|
def batch_delete(self, block_run_ids: List[int]):
|
|
1667
|
-
BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).delete(
|
|
1668
|
-
synchronize_session=False
|
|
1669
|
-
)
|
|
1682
|
+
BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).delete(synchronize_session=False)
|
|
1670
1683
|
db_connection.session.commit()
|
|
1671
1684
|
|
|
1672
1685
|
@classmethod
|
|
@@ -1680,8 +1693,13 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
|
|
|
1680
1693
|
return block_runs[0]
|
|
1681
1694
|
return None
|
|
1682
1695
|
|
|
1683
|
-
def get_outputs(
|
|
1696
|
+
def get_outputs(
|
|
1697
|
+
self,
|
|
1698
|
+
exclude_blank_variable_uuids: bool = False,
|
|
1699
|
+
sample_count: int = None,
|
|
1700
|
+
) -> List[Dict]:
|
|
1684
1701
|
pipeline = Pipeline.get(self.pipeline_run.pipeline_uuid)
|
|
1702
|
+
|
|
1685
1703
|
block = pipeline.get_block(self.block_uuid)
|
|
1686
1704
|
block_uuid = self.block_uuid
|
|
1687
1705
|
|
|
@@ -1755,6 +1773,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
|
|
|
1755
1773
|
]
|
|
1756
1774
|
|
|
1757
1775
|
return block.get_outputs(
|
|
1776
|
+
exclude_blank_variable_uuids=exclude_blank_variable_uuids,
|
|
1758
1777
|
execution_partition=self.pipeline_run.execution_partition,
|
|
1759
1778
|
sample_count=sample_count,
|
|
1760
1779
|
block_uuid=block_uuid,
|
|
@@ -1783,9 +1802,7 @@ class EventMatcher(BaseModel):
|
|
|
1783
1802
|
@classmethod
|
|
1784
1803
|
def active_event_matchers(self) -> List['EventMatcher']:
|
|
1785
1804
|
return self.query.filter(
|
|
1786
|
-
EventMatcher.pipeline_schedules.any(
|
|
1787
|
-
PipelineSchedule.status == ScheduleStatus.ACTIVE
|
|
1788
|
-
)
|
|
1805
|
+
EventMatcher.pipeline_schedules.any(PipelineSchedule.status == ScheduleStatus.ACTIVE)
|
|
1789
1806
|
).all()
|
|
1790
1807
|
|
|
1791
1808
|
@classmethod
|
|
@@ -1846,8 +1863,7 @@ class EventMatcher(BaseModel):
|
|
|
1846
1863
|
return [t[0] for t in event_matchers_and_pipeline_schedule_ids]
|
|
1847
1864
|
|
|
1848
1865
|
def active_pipeline_schedules(self) -> List[PipelineSchedule]:
|
|
1849
|
-
return [p for p in self.pipeline_schedules
|
|
1850
|
-
if p.status == ScheduleStatus.ACTIVE]
|
|
1866
|
+
return [p for p in self.pipeline_schedules if p.status == ScheduleStatus.ACTIVE]
|
|
1851
1867
|
|
|
1852
1868
|
def match(self, config: Dict) -> bool:
|
|
1853
1869
|
def __match_dict(sub_pattern, sub_config):
|
|
@@ -1863,6 +1879,7 @@ class EventMatcher(BaseModel):
|
|
|
1863
1879
|
elif not __match_dict(v, sub_config[k]):
|
|
1864
1880
|
return False
|
|
1865
1881
|
return True
|
|
1882
|
+
|
|
1866
1883
|
return __match_dict(self.pattern, config)
|
|
1867
1884
|
|
|
1868
1885
|
|
|
@@ -1913,3 +1930,24 @@ class Backfill(BaseModel):
|
|
|
1913
1930
|
Backfill.pipeline_schedule_id.in_(pipeline_schedule_ids),
|
|
1914
1931
|
)
|
|
1915
1932
|
return []
|
|
1933
|
+
|
|
1934
|
+
@property
|
|
1935
|
+
def pipeline_run_status_counts(self) -> Dict:
|
|
1936
|
+
status_counts = dict()
|
|
1937
|
+
execution_dates_counted = set()
|
|
1938
|
+
|
|
1939
|
+
# Sort the pipeline runs by id in reverse order so the first pipeline run
|
|
1940
|
+
# checked is the latest pipeline run created for a given execution date.
|
|
1941
|
+
pipeline_runs_sorted = sorted(
|
|
1942
|
+
self.pipeline_runs,
|
|
1943
|
+
key=lambda pr: (pr.execution_date, pr.id),
|
|
1944
|
+
reverse=True,
|
|
1945
|
+
)
|
|
1946
|
+
|
|
1947
|
+
for pr in pipeline_runs_sorted:
|
|
1948
|
+
# Only count a pipeline run once per execution date
|
|
1949
|
+
if pr.execution_date not in execution_dates_counted:
|
|
1950
|
+
status_counts[pr.status] = (status_counts.get(pr.status) or 0) + 1
|
|
1951
|
+
execution_dates_counted.add(pr.execution_date)
|
|
1952
|
+
|
|
1953
|
+
return status_counts
|