mage-ai 0.9.46__py3-none-any.whl → 0.9.48__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/operations/base.py +27 -5
- mage_ai/api/policies/GlobalHookPolicy.py +1 -1
- mage_ai/api/policies/IntegrationSourcePolicy.py +62 -0
- mage_ai/api/policies/OauthPolicy.py +6 -6
- mage_ai/api/presenters/GlobalHookPresenter.py +1 -1
- mage_ai/api/presenters/IntegrationSourcePresenter.py +9 -2
- mage_ai/api/presenters/PipelinePresenter.py +3 -0
- mage_ai/api/presenters/PipelineRunPresenter.py +8 -3
- mage_ai/api/presenters/PipelineSchedulePresenter.py +22 -1
- mage_ai/api/resources/BlockResource.py +5 -0
- mage_ai/api/resources/DataProviderResource.py +2 -0
- mage_ai/api/resources/IntegrationSourceResource.py +149 -2
- mage_ai/data_integrations/sources/constants.py +5 -0
- mage_ai/data_integrations/utils/scheduler.py +57 -2
- mage_ai/data_preparation/executors/block_executor.py +30 -2
- mage_ai/data_preparation/executors/pipeline_executor.py +19 -4
- mage_ai/data_preparation/models/block/__init__.py +75 -32
- mage_ai/data_preparation/models/block/data_integration/constants.py +3 -0
- mage_ai/data_preparation/models/block/data_integration/mixins.py +6 -6
- mage_ai/data_preparation/models/block/data_integration/utils.py +198 -39
- mage_ai/data_preparation/models/block/sql/bigquery.py +2 -2
- mage_ai/data_preparation/models/block/sql/snowflake.py +2 -2
- mage_ai/data_preparation/models/block/sql/trino.py +2 -2
- mage_ai/data_preparation/models/block/sql/utils/shared.py +20 -3
- mage_ai/data_preparation/models/block/utils.py +53 -29
- mage_ai/data_preparation/models/global_hooks/constants.py +50 -1
- mage_ai/data_preparation/models/global_hooks/models.py +148 -84
- mage_ai/data_preparation/models/global_hooks/predicates.py +316 -0
- mage_ai/data_preparation/models/pipeline.py +7 -0
- mage_ai/data_preparation/models/pipelines/integration_pipeline.py +0 -1
- mage_ai/data_preparation/models/project/__init__.py +0 -2
- mage_ai/data_preparation/preferences.py +29 -18
- mage_ai/data_preparation/repo_manager.py +12 -2
- mage_ai/data_preparation/sync/__init__.py +2 -0
- mage_ai/data_preparation/templates/constants.py +14 -0
- mage_ai/data_preparation/templates/data_exporters/chroma.py +24 -0
- mage_ai/data_preparation/templates/data_exporters/streaming/rabbitmq.yaml +7 -0
- mage_ai/data_preparation/templates/data_loaders/chroma.py +27 -0
- mage_ai/data_preparation/templates/repo/io_config.yaml +3 -0
- mage_ai/io/base.py +1 -0
- mage_ai/io/chroma.py +162 -0
- mage_ai/io/config.py +8 -0
- mage_ai/orchestration/db/models/schedules.py +169 -34
- mage_ai/orchestration/pipeline_scheduler.py +59 -89
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1952-0f9a12782f0aaae6.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-14191a781cf2f286.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3419-a7a52bcaaa687b07.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3437-e81a62f33337ca06.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3943-3cb1f765210dd7a4.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4138-2c16e6d2f22246cd.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{4366-93e09e5a4a7e182c.js → 4366-3e52497942acbafe.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{5499-76cf8f023c6b0985.js → 5499-c2853ef57d39fde8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/6285-e9b45335bfb9ccaf.js → frontend_dist/_next/static/chunks/6285-648f9a732e100b2f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/6990-303bb87fc50f1755.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7858-d9df72e95e438284.js → frontend_dist/_next/static/chunks/7858-26a5a5d04fa3c703.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{8146-92e7ccfed169ee9c.js → 8146-27f0e31f309897a5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8264-9d6a7cea289e29ff.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8487-608d62c0eef1f29a.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/1845-5ce774d5ab81ed57.js → frontend_dist/_next/static/chunks/8731-2f78ec7b7760be8f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/90-93d18aaecef0685b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9264-727704fc34e74ae0.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9624-48fba6b4e6966fb7.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/976-18c98af60b76f1a7.js → frontend_dist/_next/static/chunks/976-0a8c2c4d7acd957b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-8254de4f793643d0.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/block-layout-a24cb24b6f08bbc9.js → frontend_dist/_next/static/chunks/pages/block-layout-b926f6eb1ee9a53b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-a9402b51e9fe748e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-85cecae037fd7a70.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-cfd68e760ae00958.js → [...slug]-c3c9523ea8072c11.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-c3b79ef31007f95b.js → global-data-products-4d046f15202a1c8d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-286133386c97a2b6.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-hooks-e561ae38cf5592e8.js → global-hooks-3da370825153056c.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/files-449a022f2f0f2d94.js → frontend_dist/_next/static/chunks/pages/manage/files-39b73da5a15590f6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{settings-60845f0b59142f32.js → settings-666748ff5d101411.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-9384c5f1efa2ac18.js → frontend_dist/_next/static/chunks/pages/manage/users/[user]-be27631e67dbe070.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-abd8571907664fdf.js → frontend_dist/_next/static/chunks/pages/manage/users/new-1932ce64823b372b.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-28a930b148d99766.js → frontend_dist/_next/static/chunks/pages/manage/users-ed509c75cf23f0f5.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage-f83deb790548693b.js → frontend_dist/_next/static/chunks/pages/manage-1feebec1124123fc.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{oauth-8bb62c4f6a511c43.js → oauth-e9b8f19c30381c28.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/overview-f0c40645f385f23f.js → frontend_dist/_next/static/chunks/pages/overview-7b2ba2d5405c05fe.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-70fc3351bd11025f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-6ee3b88a5bb4ce94.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c9cf383bc13ce7b8.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-571c0962333b92f0.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-7bca6f718b939934.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-c119f630038b0685.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-146051325c92d742.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-ddddcddd2f74b4f6.js → block-runs-15d307e6ba934a56.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-4a238307feddb522.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-f6196e563b960e5c.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-25dbd73201d99e80.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-06e55db757959ef8.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d20b2cd08907afd.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-ec3c45cfa027db58.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-495e877aa7ed709e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-49adfeed5157d92b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-6143e028225390f5.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-0886f6320fef7131.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e82a763d742cc034.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-50d20fa715d454af.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-b78b1be5b9ed84b9.js → [...slug]-2bbd63b7e93a8600.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-37b78a436eeab258.js → permissions-4ea156c39608caab.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-f3c29ec53ee35795.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-db05a80d18c168e5.js → [...slug]-64ec8928d2542f3c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{roles-f55c77e4f46c8d33.js → roles-835e6ec2a48ec583.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{sync-data-2a1f8737561fdd94.js → sync-data-0769149af025de30.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-e3bf6e5d8bb250c4.js → [...slug]-612a65c42bcadef0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-20f0a050a42a015d.js → users-e3365b4029a8db33.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-99e2748e3c1d57a3.js → frontend_dist/_next/static/chunks/pages/sign-in-f3a33e8f83abdb58.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-f44ccd1499ffd23a.js → frontend_dist/_next/static/chunks/pages/templates/[...slug]-f264097bf8120f31.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{templates-1bfaa1c50e844813.js → templates-406e13cc5c4caab4.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{terminal-ed121e305169cf1c.js → terminal-ef8ad878e5e7bb2f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-a90728798f964700.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-0e0c2713a2922be7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/xxcdnITr3IkTdETH5ghqw/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/block-layout.html +2 -2
- mage_ai/server/frontend_dist/compute.html +5 -5
- mage_ai/server/frontend_dist/files.html +5 -5
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +5 -5
- mage_ai/server/frontend_dist/global-data-products.html +5 -5
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +5 -5
- mage_ai/server/frontend_dist/global-hooks.html +5 -5
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/files.html +5 -5
- mage_ai/server/frontend_dist/manage/settings.html +5 -5
- mage_ai/server/frontend_dist/manage/users/[user].html +5 -5
- mage_ai/server/frontend_dist/manage/users/new.html +5 -5
- mage_ai/server/frontend_dist/manage/users.html +5 -5
- mage_ai/server/frontend_dist/manage.html +5 -5
- mage_ai/server/frontend_dist/oauth.html +4 -4
- mage_ai/server/frontend_dist/overview.html +5 -5
- mage_ai/server/frontend_dist/pipeline-runs.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +5 -5
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist/pipelines.html +5 -5
- mage_ai/server/frontend_dist/settings/account/profile.html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/roles.html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +5 -5
- mage_ai/server/frontend_dist/settings/workspace/users.html +5 -5
- mage_ai/server/frontend_dist/settings.html +2 -2
- mage_ai/server/frontend_dist/sign-in.html +24 -24
- mage_ai/server/frontend_dist/templates/[...slug].html +5 -5
- mage_ai/server/frontend_dist/templates.html +5 -5
- mage_ai/server/frontend_dist/terminal.html +5 -5
- mage_ai/server/frontend_dist/test.html +5 -5
- mage_ai/server/frontend_dist/triggers.html +5 -5
- mage_ai/server/frontend_dist/version-control.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-0f9a12782f0aaae6.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist_base_path_template/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-14191a781cf2f286.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-a7a52bcaaa687b07.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3437-e81a62f33337ca06.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-3cb1f765210dd7a4.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4138-2c16e6d2f22246cd.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4366-93e09e5a4a7e182c.js → 4366-3e52497942acbafe.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5499-76cf8f023c6b0985.js → 5499-c2853ef57d39fde8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/6285-e9b45335bfb9ccaf.js → frontend_dist_base_path_template/_next/static/chunks/6285-648f9a732e100b2f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6990-303bb87fc50f1755.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist_base_path_template/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/7858-d9df72e95e438284.js → frontend_dist_base_path_template/_next/static/chunks/7858-26a5a5d04fa3c703.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{8146-92e7ccfed169ee9c.js → 8146-27f0e31f309897a5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-9d6a7cea289e29ff.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-608d62c0eef1f29a.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/1845-5ce774d5ab81ed57.js → frontend_dist_base_path_template/_next/static/chunks/8731-2f78ec7b7760be8f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/90-93d18aaecef0685b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-727704fc34e74ae0.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-48fba6b4e6966fb7.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/976-18c98af60b76f1a7.js → frontend_dist_base_path_template/_next/static/chunks/976-0a8c2c4d7acd957b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-8254de4f793643d0.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/block-layout-a24cb24b6f08bbc9.js → frontend_dist_base_path_template/_next/static/chunks/pages/block-layout-b926f6eb1ee9a53b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-a9402b51e9fe748e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-85cecae037fd7a70.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-cfd68e760ae00958.js → [...slug]-c3c9523ea8072c11.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-c3b79ef31007f95b.js → global-data-products-4d046f15202a1c8d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-286133386c97a2b6.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-hooks-e561ae38cf5592e8.js → global-hooks-3da370825153056c.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/files-449a022f2f0f2d94.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/files-39b73da5a15590f6.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{settings-60845f0b59142f32.js → settings-666748ff5d101411.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users/[user]-9384c5f1efa2ac18.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-be27631e67dbe070.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users/new-abd8571907664fdf.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-1932ce64823b372b.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users-28a930b148d99766.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-ed509c75cf23f0f5.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage-f83deb790548693b.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage-1feebec1124123fc.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{oauth-8bb62c4f6a511c43.js → oauth-e9b8f19c30381c28.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/overview-f0c40645f385f23f.js → frontend_dist_base_path_template/_next/static/chunks/pages/overview-7b2ba2d5405c05fe.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-70fc3351bd11025f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-6ee3b88a5bb4ce94.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c9cf383bc13ce7b8.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-571c0962333b92f0.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-7bca6f718b939934.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-c119f630038b0685.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-146051325c92d742.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-ddddcddd2f74b4f6.js → block-runs-15d307e6ba934a56.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-4a238307feddb522.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-f6196e563b960e5c.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-25dbd73201d99e80.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-06e55db757959ef8.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d20b2cd08907afd.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-ec3c45cfa027db58.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-495e877aa7ed709e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-49adfeed5157d92b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-6143e028225390f5.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-0886f6320fef7131.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e82a763d742cc034.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-50d20fa715d454af.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-b78b1be5b9ed84b9.js → [...slug]-2bbd63b7e93a8600.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-37b78a436eeab258.js → permissions-4ea156c39608caab.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-f3c29ec53ee35795.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-db05a80d18c168e5.js → [...slug]-64ec8928d2542f3c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{roles-f55c77e4f46c8d33.js → roles-835e6ec2a48ec583.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{sync-data-2a1f8737561fdd94.js → sync-data-0769149af025de30.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-e3bf6e5d8bb250c4.js → [...slug]-612a65c42bcadef0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-20f0a050a42a015d.js → users-e3365b4029a8db33.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/sign-in-99e2748e3c1d57a3.js → frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-f3a33e8f83abdb58.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates/[...slug]-f44ccd1499ffd23a.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-f264097bf8120f31.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{templates-1bfaa1c50e844813.js → templates-406e13cc5c4caab4.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{terminal-ed121e305169cf1c.js → terminal-ef8ad878e5e7bb2f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-a90728798f964700.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-0e0c2713a2922be7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/gDn6inKdLyj35NvURBSCV/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/compute.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/files.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/manage.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/oauth.html +4 -4
- mage_ai/server/frontend_dist_base_path_template/overview.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +5 -5
- 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 +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +20 -20
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +5 -5
- mage_ai/server/frontend_dist_base_path_template/templates.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/terminal.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/test.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/triggers.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/version-control.html +5 -5
- mage_ai/server/server.py +11 -3
- mage_ai/services/k8s/job_manager.py +1 -0
- mage_ai/settings/repo.py +3 -0
- mage_ai/shared/files.py +47 -0
- mage_ai/shared/models.py +1 -0
- mage_ai/streaming/constants.py +1 -0
- mage_ai/streaming/sinks/postgres.py +2 -0
- mage_ai/streaming/sinks/rabbitmq.py +76 -0
- mage_ai/streaming/sinks/sink_factory.py +4 -0
- mage_ai/streaming/sources/nats_js.py +12 -1
- mage_ai/tests/api/operations/test_operations_with_hooks.py +136 -91
- mage_ai/tests/api/policies/test_oauth_policy.py +38 -0
- mage_ai/tests/data_preparation/executors/test_block_executor.py +2 -0
- mage_ai/tests/data_preparation/models/global_hooks/test_global_hooks.py +33 -8
- mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +82 -38
- mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +803 -0
- mage_ai/tests/data_preparation/models/global_hooks/test_utils.py +6 -1
- mage_ai/tests/data_preparation/models/test_block.py +26 -0
- mage_ai/tests/data_preparation/models/test_pipeline.py +15 -0
- mage_ai/tests/factory.py +40 -2
- mage_ai/tests/orchestration/test_pipeline_scheduler.py +82 -1
- mage_ai/tests/services/k8s/test_job_manager.py +16 -0
- mage_ai/tests/shared/mixins.py +60 -23
- mage_ai/tests/streaming/sinks/test_rabbitmq.py +36 -0
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/METADATA +7 -4
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/RECORD +335 -321
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/WHEEL +1 -1
- mage_ai/server/frontend_dist/_next/static/9jB4XPuz6BzxBcG9VNao5/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1952-ac7722e8b1ab88fe.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3419-f8d518d024e7b5c8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/600-705fe234320ec5de.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/722-a1584445357a276c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8264-0d582a6ca33c3dfa.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/90-a7308bae028d7001.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9624-334e7db5c84cb4ea.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-419775ca1293b354.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-ef680455ae54ccbe.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-ac7722e8b1ab88fe.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-f8d518d024e7b5c8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/600-705fe234320ec5de.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/722-a1584445357a276c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-0d582a6ca33c3dfa.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/90-a7308bae028d7001.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-334e7db5c84cb4ea.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-419775ca1293b354.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-ef680455ae54ccbe.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/uPDjJYpJMst1q6psbRyte/_buildManifest.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{9jB4XPuz6BzxBcG9VNao5 → xxcdnITr3IkTdETH5ghqw}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{uPDjJYpJMst1q6psbRyte → gDn6inKdLyj35NvURBSCV}/_ssgManifest.js +0 -0
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/top_level.txt +0 -0
mage_ai/io/chroma.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
import chromadb
|
|
5
|
+
from pandas import DataFrame
|
|
6
|
+
|
|
7
|
+
from mage_ai.io.base import BaseIO
|
|
8
|
+
from mage_ai.io.config import BaseConfigLoader, ConfigKey
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Chroma(BaseIO):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
collection: str,
|
|
17
|
+
path: str = None,
|
|
18
|
+
verbose: bool = True,
|
|
19
|
+
**kwargs,) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initializes settings to connect to chroma db.
|
|
22
|
+
"""
|
|
23
|
+
super().__init__(verbose=verbose)
|
|
24
|
+
self.collection = collection
|
|
25
|
+
if path is None:
|
|
26
|
+
self.client = chromadb.Client()
|
|
27
|
+
else:
|
|
28
|
+
self.client = chromadb.PersistentClient(path=path)
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def with_config(cls, config: BaseConfigLoader) -> 'Chroma':
|
|
32
|
+
return cls(
|
|
33
|
+
collection=config[ConfigKey.CHROMA_COLLECTION],
|
|
34
|
+
path=config[ConfigKey.CHROMA_PATH],
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def __convert_to_multiple_rows(self, data: Dict, column_name: str, item_length: int):
|
|
38
|
+
"""
|
|
39
|
+
Convert the data from chroma query into multiple rows.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
data (Dict): Data returned from chroma query.
|
|
43
|
+
Example format:
|
|
44
|
+
{
|
|
45
|
+
'ids': [['id1', '0', 'id2']],
|
|
46
|
+
'distances': [[0.6036068181428754, 0.6036068181428754, 1.267588382105355]],
|
|
47
|
+
'metadatas': [[
|
|
48
|
+
{'chapter': '3', 'verse': '16'},
|
|
49
|
+
None,
|
|
50
|
+
{'chapter': '3', 'verse': '5'}
|
|
51
|
+
]],
|
|
52
|
+
'embeddings': None,
|
|
53
|
+
'documents': [['abc', 'abc', 'def']],
|
|
54
|
+
'uris': None,
|
|
55
|
+
'data': None
|
|
56
|
+
}
|
|
57
|
+
column_name (str): Name of the field in data to convert.
|
|
58
|
+
item_length (int): Number of expected items in the list.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
DataFrame: Data frame object loaded from the chroma query fuction.
|
|
62
|
+
Chroma query function requries dictionary contains number of results matched.
|
|
63
|
+
"""
|
|
64
|
+
converted_array = []
|
|
65
|
+
if data[column_name] is None:
|
|
66
|
+
for _ in range(item_length):
|
|
67
|
+
converted_array.append('')
|
|
68
|
+
else:
|
|
69
|
+
for list_items in data[column_name]:
|
|
70
|
+
for item in list_items:
|
|
71
|
+
if item is None:
|
|
72
|
+
converted_array.append('')
|
|
73
|
+
else:
|
|
74
|
+
converted_array.append(item)
|
|
75
|
+
return converted_array
|
|
76
|
+
|
|
77
|
+
def load(
|
|
78
|
+
self,
|
|
79
|
+
n_results: int,
|
|
80
|
+
collection: str = None,
|
|
81
|
+
query_embeddings: str = None,
|
|
82
|
+
query_texts: str = None,
|
|
83
|
+
**kwargs,
|
|
84
|
+
) -> DataFrame:
|
|
85
|
+
"""
|
|
86
|
+
Loads the data from Chroma with embeddings or query_texts.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
n_results (int): Number of results to return.
|
|
90
|
+
query_embeddings (str): Embeddings to query.
|
|
91
|
+
query_texts (str): Texts to query.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
DataFrame: Data frame object loaded from the chroma query fuction.
|
|
95
|
+
Chroma query function requries dictionary contains number of results matched.
|
|
96
|
+
"""
|
|
97
|
+
collection_client = self.client.get_or_create_collection(
|
|
98
|
+
name=self.collection if collection is None else collection)
|
|
99
|
+
# Chroma supports query by embeddings or query texts
|
|
100
|
+
if query_embeddings is not None:
|
|
101
|
+
data = collection_client.query(
|
|
102
|
+
query_embeddings=query_embeddings,
|
|
103
|
+
n_results=n_results
|
|
104
|
+
)
|
|
105
|
+
elif query_texts is not None:
|
|
106
|
+
data = collection_client.query(
|
|
107
|
+
query_texts=query_texts,
|
|
108
|
+
n_results=n_results
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
raise ValueError("query_embeddings or query_texts must be specified")
|
|
112
|
+
# Flatten the query results into multiple rows
|
|
113
|
+
flatten_data = {}
|
|
114
|
+
item_length = len(data['ids'][0])
|
|
115
|
+
flatten_data['ids'] = self.__convert_to_multiple_rows(
|
|
116
|
+
data, 'ids', item_length)
|
|
117
|
+
flatten_data['distances'] = self.__convert_to_multiple_rows(
|
|
118
|
+
data, 'distances', item_length)
|
|
119
|
+
flatten_data['metadatas'] = self.__convert_to_multiple_rows(
|
|
120
|
+
data, 'metadatas', item_length)
|
|
121
|
+
flatten_data['embeddings'] = self.__convert_to_multiple_rows(
|
|
122
|
+
data, 'embeddings', item_length)
|
|
123
|
+
flatten_data['documents'] = self.__convert_to_multiple_rows(
|
|
124
|
+
data, 'documents', item_length)
|
|
125
|
+
flatten_data['data'] = self.__convert_to_multiple_rows(
|
|
126
|
+
data, 'data', item_length)
|
|
127
|
+
return DataFrame.from_dict(flatten_data)
|
|
128
|
+
|
|
129
|
+
def export(
|
|
130
|
+
self,
|
|
131
|
+
df: DataFrame,
|
|
132
|
+
document_column: str,
|
|
133
|
+
collection: str = None,
|
|
134
|
+
id_column: str = None,
|
|
135
|
+
metadata_column: str = None,
|
|
136
|
+
**kwargs,
|
|
137
|
+
) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Exports the input dataframe to the chroma collection.
|
|
140
|
+
The column required is document_column.
|
|
141
|
+
It contains the contextual prompt for query and search.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
df (DataFrame): Data frame to export.
|
|
145
|
+
document_column (str): name of the document.
|
|
146
|
+
"""
|
|
147
|
+
docs = df[document_column].tolist()
|
|
148
|
+
if id_column is None:
|
|
149
|
+
ids = [str(x) for x in df.index.tolist()]
|
|
150
|
+
else:
|
|
151
|
+
ids = df[id_column].apply(str).tolist()
|
|
152
|
+
collection_client = self.client.get_or_create_collection(
|
|
153
|
+
name=self.collection if collection is None else collection)
|
|
154
|
+
insert_kwargs = dict(
|
|
155
|
+
documents=docs,
|
|
156
|
+
ids=ids,
|
|
157
|
+
)
|
|
158
|
+
if metadata_column:
|
|
159
|
+
insert_kwargs['metadatas'] = df[metadata_column].tolist()
|
|
160
|
+
return collection_client.add(
|
|
161
|
+
**insert_kwargs
|
|
162
|
+
)
|
mage_ai/io/config.py
CHANGED
|
@@ -27,6 +27,9 @@ class ConfigKey(str, Enum):
|
|
|
27
27
|
AZURE_STORAGE_ACCOUNT_NAME = 'AZURE_STORAGE_ACCOUNT_NAME'
|
|
28
28
|
AZURE_TENANT_ID = 'AZURE_TENANT_ID'
|
|
29
29
|
|
|
30
|
+
CHROMA_COLLECTION = 'CHROMA_COLLECTION'
|
|
31
|
+
CHROMA_PATH = 'CHROMA_PATH'
|
|
32
|
+
|
|
30
33
|
CLICKHOUSE_DATABASE = 'CLICKHOUSE_DATABASE'
|
|
31
34
|
CLICKHOUSE_HOST = 'CLICKHOUSE_HOST'
|
|
32
35
|
CLICKHOUSE_INTERFACE = 'CLICKHOUSE_INTERFACE'
|
|
@@ -323,6 +326,7 @@ class VerboseConfigKey(str, Enum):
|
|
|
323
326
|
|
|
324
327
|
AWS = 'AWS'
|
|
325
328
|
BIGQUERY = 'BigQuery'
|
|
329
|
+
CHROMA = 'Chroma'
|
|
326
330
|
CLICKHOUSE = 'ClickHouse'
|
|
327
331
|
DRUID = 'Druid'
|
|
328
332
|
DUCKDB = 'Duck DB'
|
|
@@ -370,6 +374,10 @@ class ConfigFileLoader(BaseConfigLoader):
|
|
|
370
374
|
VerboseConfigKey.REDSHIFT,
|
|
371
375
|
'user',
|
|
372
376
|
),
|
|
377
|
+
ConfigKey.CHROMA_COLLECTION: (
|
|
378
|
+
VerboseConfigKey.CHROMA, 'collection'),
|
|
379
|
+
ConfigKey.CHROMA_PATH: (
|
|
380
|
+
VerboseConfigKey.CHROMA, 'path'),
|
|
373
381
|
ConfigKey.CLICKHOUSE_DATABASE: (
|
|
374
382
|
VerboseConfigKey.CLICKHOUSE, 'database'),
|
|
375
383
|
ConfigKey.CLICKHOUSE_HOST: (
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import collections
|
|
2
3
|
import enum
|
|
3
4
|
import traceback
|
|
4
5
|
import uuid
|
|
5
6
|
from datetime import datetime, timedelta, timezone
|
|
6
|
-
from itertools import groupby
|
|
7
7
|
from math import ceil
|
|
8
8
|
from statistics import stdev
|
|
9
|
-
from typing import Dict, List
|
|
9
|
+
from typing import DefaultDict, Dict, List
|
|
10
10
|
|
|
11
11
|
import dateutil.parser
|
|
12
12
|
import pytz
|
|
@@ -119,6 +119,18 @@ class PipelineSchedule(BaseModel):
|
|
|
119
119
|
query = query.filter(PipelineRun.pipeline_schedule_id.in_(ids))
|
|
120
120
|
return query.all()
|
|
121
121
|
|
|
122
|
+
@classmethod
|
|
123
|
+
def fetch_latest_pipeline_runs_without_retries(self, ids: List[int]) -> List:
|
|
124
|
+
query = PipelineRun.query
|
|
125
|
+
query.cache = True
|
|
126
|
+
query = (
|
|
127
|
+
query.
|
|
128
|
+
filter(PipelineRun.pipeline_schedule_id.in_(ids)).
|
|
129
|
+
group_by(PipelineRun.execution_date).
|
|
130
|
+
order_by(func.max(PipelineRun.started_at))
|
|
131
|
+
)
|
|
132
|
+
return query.all()
|
|
133
|
+
|
|
122
134
|
def get_settings(self) -> 'SettingsConfig':
|
|
123
135
|
settings = self.settings if self.settings else dict()
|
|
124
136
|
return SettingsConfig.load(config=settings)
|
|
@@ -491,46 +503,61 @@ class PipelineSchedule(BaseModel):
|
|
|
491
503
|
|
|
492
504
|
return (self.settings or {}).get('landing_time_enabled', False)
|
|
493
505
|
|
|
494
|
-
def
|
|
506
|
+
def recently_completed_pipeline_runs(
|
|
495
507
|
self,
|
|
496
508
|
pipeline_run=None,
|
|
497
509
|
sample_size: int = None,
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
|
|
510
|
+
):
|
|
511
|
+
pipeline_runs = (
|
|
512
|
+
PipelineRun.
|
|
513
|
+
query.
|
|
514
|
+
filter(
|
|
515
|
+
PipelineRun.pipeline_schedule_id == self.id,
|
|
516
|
+
PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
|
|
517
|
+
)
|
|
518
|
+
)
|
|
501
519
|
|
|
502
520
|
if pipeline_run:
|
|
503
|
-
previous_runtimes += (pipeline_run.metrics or {}).get('previous_runtimes', [])
|
|
504
|
-
|
|
505
|
-
if len(previous_runtimes) < sample_size_to_use - 1 if pipeline_run else sample_size_to_use:
|
|
506
521
|
pipeline_runs = (
|
|
507
|
-
|
|
508
|
-
query.
|
|
522
|
+
pipeline_runs.
|
|
509
523
|
filter(
|
|
510
|
-
PipelineRun.
|
|
511
|
-
PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
|
|
524
|
+
PipelineRun.id != pipeline_run.id,
|
|
512
525
|
)
|
|
513
526
|
)
|
|
514
527
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
PipelineRun.id != pipeline_run.id,
|
|
520
|
-
)
|
|
521
|
-
)
|
|
528
|
+
pipeline_runs = (
|
|
529
|
+
pipeline_runs.
|
|
530
|
+
order_by(PipelineRun.execution_date.desc())
|
|
531
|
+
)
|
|
522
532
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
533
|
+
if sample_size:
|
|
534
|
+
pipeline_runs = pipeline_runs.limit(sample_size)
|
|
535
|
+
|
|
536
|
+
pipeline_runs = pipeline_runs.all()
|
|
537
|
+
|
|
538
|
+
pipeline_runs = sorted(
|
|
539
|
+
pipeline_runs,
|
|
540
|
+
key=lambda pr: pr.execution_date,
|
|
541
|
+
reverse=True,
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
return pipeline_runs
|
|
545
|
+
|
|
546
|
+
def runtime_history(
|
|
547
|
+
self,
|
|
548
|
+
pipeline_run=None,
|
|
549
|
+
sample_size: int = None,
|
|
550
|
+
) -> List[float]:
|
|
551
|
+
sample_size_to_use = sample_size if sample_size else 7
|
|
552
|
+
previous_runtimes = []
|
|
553
|
+
|
|
554
|
+
if pipeline_run:
|
|
555
|
+
previous_runtimes += (pipeline_run.metrics or {}).get('previous_runtimes', [])
|
|
529
556
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
557
|
+
if len(previous_runtimes) < sample_size_to_use - 1 if pipeline_run else sample_size_to_use:
|
|
558
|
+
pipeline_runs = self.recently_completed_pipeline_runs(
|
|
559
|
+
pipeline_run=pipeline_run,
|
|
560
|
+
sample_size=sample_size_to_use,
|
|
534
561
|
)
|
|
535
562
|
|
|
536
563
|
for pr in pipeline_runs:
|
|
@@ -667,6 +694,43 @@ class PipelineRun(BaseModel):
|
|
|
667
694
|
repo_config=self.pipeline.repo_config,
|
|
668
695
|
).get_logs()
|
|
669
696
|
|
|
697
|
+
@classmethod
|
|
698
|
+
def recently_completed_pipeline_runs(
|
|
699
|
+
self,
|
|
700
|
+
pipeline_uuid: str,
|
|
701
|
+
pipeline_run_id: int = None,
|
|
702
|
+
pipeline_schedule_id: int = None,
|
|
703
|
+
sample_size: int = None,
|
|
704
|
+
):
|
|
705
|
+
pipeline_runs = (
|
|
706
|
+
self.
|
|
707
|
+
query.
|
|
708
|
+
filter(
|
|
709
|
+
self.pipeline_uuid == pipeline_uuid,
|
|
710
|
+
self.status == self.PipelineRunStatus.COMPLETED,
|
|
711
|
+
)
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
if pipeline_run_id is not None:
|
|
715
|
+
pipeline_runs = pipeline_runs.filter(self.id != pipeline_run_id)
|
|
716
|
+
|
|
717
|
+
if pipeline_schedule_id is not None:
|
|
718
|
+
pipeline_runs = pipeline_runs.filter(self.pipeline_schedule_id == pipeline_schedule_id)
|
|
719
|
+
|
|
720
|
+
pipeline_runs = pipeline_runs.order_by(PipelineRun.execution_date.desc())
|
|
721
|
+
|
|
722
|
+
if sample_size:
|
|
723
|
+
pipeline_runs = pipeline_runs.limit(sample_size)
|
|
724
|
+
|
|
725
|
+
pipeline_runs = pipeline_runs.all()
|
|
726
|
+
pipeline_runs = sorted(
|
|
727
|
+
pipeline_runs,
|
|
728
|
+
key=lambda pr: pr.execution_date,
|
|
729
|
+
reverse=True,
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
return pipeline_runs
|
|
733
|
+
|
|
670
734
|
async def logs_async(self):
|
|
671
735
|
return await LoggerManagerFactory.get_logger_manager(
|
|
672
736
|
pipeline_uuid=self.pipeline_uuid,
|
|
@@ -838,6 +902,77 @@ class PipelineRun(BaseModel):
|
|
|
838
902
|
|
|
839
903
|
return executable_block_runs
|
|
840
904
|
|
|
905
|
+
def update_block_run_statuses(self, block_runs: List['BlockRun']) -> None:
|
|
906
|
+
"""Update the statuses of the block runs to CONDITION_FAILED or UPSTREAM_FAILED.
|
|
907
|
+
|
|
908
|
+
This method updates the statuses of the block runs based on the pipeline run's block runs.
|
|
909
|
+
It retrieves the block UUIDs for failed block runs and conditionally failed block runs.
|
|
910
|
+
It maps the block run statuses to their corresponding block UUIDs.
|
|
911
|
+
|
|
912
|
+
The method iterates overthe provided block runs and checks if their dynamic upstream block
|
|
913
|
+
UUIDs or upstream block UUIDs match the failed or conditionally failed block UUIDs.
|
|
914
|
+
* If there is a match, the block run's status is updated accordingly.
|
|
915
|
+
* If no updates are made for a block run, it is added to the list of not updated block runs.
|
|
916
|
+
|
|
917
|
+
The method refreshes the pipeline run and continues iterating through block runs until no
|
|
918
|
+
more updates can be made.
|
|
919
|
+
|
|
920
|
+
Args:
|
|
921
|
+
block_runs (List[BlockRun]): A list of block runs to update.
|
|
922
|
+
|
|
923
|
+
Returns:
|
|
924
|
+
None
|
|
925
|
+
"""
|
|
926
|
+
pipeline = self.pipeline
|
|
927
|
+
|
|
928
|
+
failed_block_uuids = set(
|
|
929
|
+
b.block_uuid for b in self.block_runs
|
|
930
|
+
if b.status in [
|
|
931
|
+
BlockRun.BlockRunStatus.UPSTREAM_FAILED,
|
|
932
|
+
BlockRun.BlockRunStatus.FAILED,
|
|
933
|
+
]
|
|
934
|
+
)
|
|
935
|
+
condition_failed_block_uuids = set(
|
|
936
|
+
b.block_uuid for b in self.block_runs
|
|
937
|
+
if b.status in [
|
|
938
|
+
BlockRun.BlockRunStatus.CONDITION_FAILED,
|
|
939
|
+
]
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
statuses = {
|
|
943
|
+
BlockRun.BlockRunStatus.CONDITION_FAILED: condition_failed_block_uuids,
|
|
944
|
+
BlockRun.BlockRunStatus.UPSTREAM_FAILED: failed_block_uuids,
|
|
945
|
+
}
|
|
946
|
+
not_updated_block_runs = []
|
|
947
|
+
for block_run in block_runs:
|
|
948
|
+
updated_status = False
|
|
949
|
+
dynamic_upstream_block_uuids = block_run.metrics and block_run.metrics.get(
|
|
950
|
+
'dynamic_upstream_block_uuids',
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
for status, block_uuids in statuses.items():
|
|
954
|
+
upstream_block_uuids = []
|
|
955
|
+
if dynamic_upstream_block_uuids:
|
|
956
|
+
upstream_block_uuids = dynamic_upstream_block_uuids
|
|
957
|
+
else:
|
|
958
|
+
block = pipeline.get_block(block_run.block_uuid)
|
|
959
|
+
if block:
|
|
960
|
+
upstream_block_uuids = block.upstream_block_uuids
|
|
961
|
+
if any(
|
|
962
|
+
b in block_uuids
|
|
963
|
+
for b in upstream_block_uuids
|
|
964
|
+
):
|
|
965
|
+
block_run.update(status=status)
|
|
966
|
+
updated_status = True
|
|
967
|
+
|
|
968
|
+
if not updated_status:
|
|
969
|
+
not_updated_block_runs.append(block_run)
|
|
970
|
+
|
|
971
|
+
self.refresh()
|
|
972
|
+
# keep iterating through block runs until no more updates can be made
|
|
973
|
+
if len(block_runs) != len(not_updated_block_runs):
|
|
974
|
+
self.update_block_run_statuses(not_updated_block_runs)
|
|
975
|
+
|
|
841
976
|
@classmethod
|
|
842
977
|
@safe_db_query
|
|
843
978
|
def active_runs_for_pipelines(
|
|
@@ -865,7 +1000,7 @@ class PipelineRun(BaseModel):
|
|
|
865
1000
|
self,
|
|
866
1001
|
pipeline_uuids: List[str],
|
|
867
1002
|
include_block_runs: bool = False,
|
|
868
|
-
) ->
|
|
1003
|
+
) -> DefaultDict[str, List['PipelineRun']]:
|
|
869
1004
|
"""
|
|
870
1005
|
Get a dictionary of active pipeline runs grouped by pipeline uuid.
|
|
871
1006
|
"""
|
|
@@ -874,9 +1009,9 @@ class PipelineRun(BaseModel):
|
|
|
874
1009
|
pipeline_uuids,
|
|
875
1010
|
include_block_runs=include_block_runs,
|
|
876
1011
|
)
|
|
877
|
-
grouped =
|
|
878
|
-
for
|
|
879
|
-
grouped[
|
|
1012
|
+
grouped = collections.defaultdict(list)
|
|
1013
|
+
for run in active_runs:
|
|
1014
|
+
grouped[run.pipeline_uuid].append(run)
|
|
880
1015
|
return grouped
|
|
881
1016
|
|
|
882
1017
|
@classmethod
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import collections
|
|
2
3
|
import os
|
|
3
4
|
import traceback
|
|
4
5
|
from datetime import datetime, timedelta
|
|
5
|
-
from itertools import groupby
|
|
6
6
|
from typing import Any, Dict, List, Set, Tuple
|
|
7
7
|
|
|
8
8
|
import pytz
|
|
@@ -75,11 +75,15 @@ class PipelineScheduler:
|
|
|
75
75
|
# Get the list of integration stream if the pipeline is data integration pipeline
|
|
76
76
|
self.streams = []
|
|
77
77
|
if self.pipeline.type == PipelineType.INTEGRATION:
|
|
78
|
-
|
|
79
|
-
self.
|
|
80
|
-
|
|
78
|
+
try:
|
|
79
|
+
self.streams = self.pipeline.streams(
|
|
80
|
+
self.pipeline_run.get_variables(
|
|
81
|
+
extra_variables=get_extra_variables(self.pipeline)
|
|
82
|
+
)
|
|
81
83
|
)
|
|
82
|
-
|
|
84
|
+
except Exception:
|
|
85
|
+
logger.exception(f'Fail to get streams for {pipeline_run}')
|
|
86
|
+
traceback.print_exc()
|
|
83
87
|
|
|
84
88
|
# Initialize the logger
|
|
85
89
|
self.logger_manager = LoggerManagerFactory.get_logger_manager(
|
|
@@ -192,6 +196,19 @@ class PipelineScheduler:
|
|
|
192
196
|
if PipelineType.STREAMING == self.pipeline.type:
|
|
193
197
|
self.__schedule_pipeline()
|
|
194
198
|
else:
|
|
199
|
+
schedule = PipelineSchedule.get(
|
|
200
|
+
self.pipeline_run.pipeline_schedule_id,
|
|
201
|
+
)
|
|
202
|
+
backfills = schedule.backfills if schedule else []
|
|
203
|
+
backfill = backfills[0] if len(backfills) >= 1 else None
|
|
204
|
+
|
|
205
|
+
if backfill is not None and \
|
|
206
|
+
backfill.status == Backfill.Status.INITIAL and \
|
|
207
|
+
self.pipeline_run.status == PipelineRun.PipelineRunStatus.RUNNING:
|
|
208
|
+
backfill.update(
|
|
209
|
+
status=Backfill.Status.RUNNING,
|
|
210
|
+
)
|
|
211
|
+
|
|
195
212
|
if self.pipeline_run.all_blocks_completed(self.allow_blocks_to_fail):
|
|
196
213
|
if PipelineType.INTEGRATION == self.pipeline.type:
|
|
197
214
|
tags = self.build_tags()
|
|
@@ -221,17 +238,20 @@ class PipelineScheduler:
|
|
|
221
238
|
|
|
222
239
|
self.logger_manager.output_logs_to_destination()
|
|
223
240
|
|
|
224
|
-
schedule = PipelineSchedule.get(
|
|
225
|
-
self.pipeline_run.pipeline_schedule_id,
|
|
226
|
-
)
|
|
227
|
-
|
|
228
241
|
if schedule:
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
backfill
|
|
242
|
+
if backfill is not None:
|
|
243
|
+
"""
|
|
244
|
+
Exclude old pipeline run retries associated with the backfill
|
|
245
|
+
(if a backfill's runs had failed and the backfill was retried, those
|
|
246
|
+
previous runs are no longer relevant) and check if the backfill's
|
|
247
|
+
latest pipeline runs with different execution dates were successfull.
|
|
248
|
+
"""
|
|
249
|
+
latest_pipeline_runs = \
|
|
250
|
+
PipelineSchedule.fetch_latest_pipeline_runs_without_retries(
|
|
251
|
+
[backfill.pipeline_schedule_id]
|
|
252
|
+
)
|
|
233
253
|
if all([PipelineRun.PipelineRunStatus.COMPLETED == pr.status
|
|
234
|
-
for pr in
|
|
254
|
+
for pr in latest_pipeline_runs]):
|
|
235
255
|
backfill.update(
|
|
236
256
|
completed_at=datetime.now(tz=pytz.UTC),
|
|
237
257
|
status=Backfill.Status.COMPLETED,
|
|
@@ -251,6 +271,20 @@ class PipelineScheduler:
|
|
|
251
271
|
self.pipeline_run.update(
|
|
252
272
|
status=PipelineRun.PipelineRunStatus.FAILED)
|
|
253
273
|
|
|
274
|
+
# Backfill status updated to "failed" if at least 1 of its pipeline runs failed
|
|
275
|
+
if backfill is not None:
|
|
276
|
+
latest_pipeline_runs = \
|
|
277
|
+
PipelineSchedule.fetch_latest_pipeline_runs_without_retries(
|
|
278
|
+
[backfill.pipeline_schedule_id]
|
|
279
|
+
)
|
|
280
|
+
if any(
|
|
281
|
+
[PipelineRun.PipelineRunStatus.FAILED == pr.status
|
|
282
|
+
for pr in latest_pipeline_runs]
|
|
283
|
+
):
|
|
284
|
+
backfill.update(
|
|
285
|
+
status=Backfill.Status.FAILED,
|
|
286
|
+
)
|
|
287
|
+
|
|
254
288
|
asyncio.run(UsageStatisticLogger().pipeline_run_ended(self.pipeline_run))
|
|
255
289
|
|
|
256
290
|
failed_block_runs = self.pipeline_run.failed_block_runs
|
|
@@ -472,75 +506,6 @@ class PipelineScheduler:
|
|
|
472
506
|
pass
|
|
473
507
|
return any_block_run_timed_out
|
|
474
508
|
|
|
475
|
-
def __update_block_run_statuses(self, block_runs: List[BlockRun]) -> None:
|
|
476
|
-
"""Update the statuses of the block runs to CONDITION_FAILED or UPSTREAM_FAILED.
|
|
477
|
-
|
|
478
|
-
This method updates the statuses of the block runs based on the pipeline run's block runs.
|
|
479
|
-
It retrieves the block UUIDs for failed block runs and conditionally failed block runs.
|
|
480
|
-
It maps the block run statuses to their corresponding block UUIDs.
|
|
481
|
-
|
|
482
|
-
The method iterates overthe provided block runs and checks if their dynamic upstream block
|
|
483
|
-
UUIDs or upstream block UUIDs match the failed or conditionally failed block UUIDs.
|
|
484
|
-
* If there is a match, the block run's status is updated accordingly.
|
|
485
|
-
* If no updates are made for a block run, it is added to the list of not updated block runs.
|
|
486
|
-
|
|
487
|
-
The method refreshes the pipeline run and continues iterating through block runs until no
|
|
488
|
-
more updates can be made.
|
|
489
|
-
|
|
490
|
-
Args:
|
|
491
|
-
block_runs (List[BlockRun]): A list of block runs to update.
|
|
492
|
-
|
|
493
|
-
Returns:
|
|
494
|
-
None
|
|
495
|
-
"""
|
|
496
|
-
failed_block_uuids = set(
|
|
497
|
-
b.block_uuid for b in self.pipeline_run.block_runs
|
|
498
|
-
if b.status in [
|
|
499
|
-
BlockRun.BlockRunStatus.UPSTREAM_FAILED,
|
|
500
|
-
BlockRun.BlockRunStatus.FAILED,
|
|
501
|
-
]
|
|
502
|
-
)
|
|
503
|
-
condition_failed_block_uuids = set(
|
|
504
|
-
b.block_uuid for b in self.pipeline_run.block_runs
|
|
505
|
-
if b.status in [
|
|
506
|
-
BlockRun.BlockRunStatus.CONDITION_FAILED,
|
|
507
|
-
]
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
statuses = {
|
|
511
|
-
BlockRun.BlockRunStatus.CONDITION_FAILED: condition_failed_block_uuids,
|
|
512
|
-
BlockRun.BlockRunStatus.UPSTREAM_FAILED: failed_block_uuids,
|
|
513
|
-
}
|
|
514
|
-
not_updated_block_runs = []
|
|
515
|
-
for block_run in block_runs:
|
|
516
|
-
updated_status = False
|
|
517
|
-
dynamic_upstream_block_uuids = block_run.metrics and block_run.metrics.get(
|
|
518
|
-
'dynamic_upstream_block_uuids',
|
|
519
|
-
)
|
|
520
|
-
|
|
521
|
-
for status, block_uuids in statuses.items():
|
|
522
|
-
upstream_block_uuids = []
|
|
523
|
-
if dynamic_upstream_block_uuids:
|
|
524
|
-
upstream_block_uuids = dynamic_upstream_block_uuids
|
|
525
|
-
else:
|
|
526
|
-
block = self.pipeline.get_block(block_run.block_uuid)
|
|
527
|
-
if block:
|
|
528
|
-
upstream_block_uuids = block.upstream_block_uuids
|
|
529
|
-
if any(
|
|
530
|
-
b in block_uuids
|
|
531
|
-
for b in upstream_block_uuids
|
|
532
|
-
):
|
|
533
|
-
block_run.update(status=status)
|
|
534
|
-
updated_status = True
|
|
535
|
-
|
|
536
|
-
if not updated_status:
|
|
537
|
-
not_updated_block_runs.append(block_run)
|
|
538
|
-
|
|
539
|
-
self.pipeline_run.refresh()
|
|
540
|
-
# keep iterating through block runs until no more updates can be made
|
|
541
|
-
if len(block_runs) != len(not_updated_block_runs):
|
|
542
|
-
self.__update_block_run_statuses(not_updated_block_runs)
|
|
543
|
-
|
|
544
509
|
def __schedule_blocks(self, block_runs: List[BlockRun] = None) -> None:
|
|
545
510
|
"""Schedule the block runs for execution.
|
|
546
511
|
|
|
@@ -557,7 +522,7 @@ class PipelineScheduler:
|
|
|
557
522
|
Returns:
|
|
558
523
|
None
|
|
559
524
|
"""
|
|
560
|
-
self.
|
|
525
|
+
self.pipeline_run.update_block_run_statuses(self.pipeline_run.initial_block_runs)
|
|
561
526
|
if block_runs is None:
|
|
562
527
|
block_runs_to_schedule = self.pipeline_run.executable_block_runs(
|
|
563
528
|
allow_blocks_to_fail=self.allow_blocks_to_fail,
|
|
@@ -1417,10 +1382,9 @@ def schedule_all():
|
|
|
1417
1382
|
active_pipeline_uuids = list(set([s.pipeline_uuid for s in active_pipeline_schedules]))
|
|
1418
1383
|
pipeline_runs_by_pipeline = PipelineRun.active_runs_for_pipelines_grouped(active_pipeline_uuids)
|
|
1419
1384
|
|
|
1420
|
-
pipeline_schedules_by_pipeline =
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
}
|
|
1385
|
+
pipeline_schedules_by_pipeline = collections.defaultdict(list)
|
|
1386
|
+
for schedule in active_pipeline_schedules:
|
|
1387
|
+
pipeline_schedules_by_pipeline[schedule.pipeline_uuid].append(schedule)
|
|
1424
1388
|
|
|
1425
1389
|
# Iterate through pipeline schedules by pipeline to handle pipeline run limits for
|
|
1426
1390
|
# each pipeline.
|
|
@@ -1546,7 +1510,13 @@ def schedule_all():
|
|
|
1546
1510
|
)
|
|
1547
1511
|
|
|
1548
1512
|
for r in quota_filtered_runs:
|
|
1549
|
-
|
|
1513
|
+
try:
|
|
1514
|
+
PipelineScheduler(r).start()
|
|
1515
|
+
except Exception:
|
|
1516
|
+
logger.exception(f'Failed to start {r}')
|
|
1517
|
+
traceback.print_exc()
|
|
1518
|
+
r.update(status=PipelineRun.PipelineRunStatus.FAILED)
|
|
1519
|
+
continue
|
|
1550
1520
|
|
|
1551
1521
|
# If on_pipeline_run_limit_reached is set as SKIP, cancel the pipeline runs that
|
|
1552
1522
|
# were not scheduled due to pipeline run limits.
|
mage_ai/server/constants.py
CHANGED