mage-ai 0.9.74__py3-none-any.whl → 0.9.79__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.
- mage_ai/ai/llm_pipeline_wizard.py +6 -4
- mage_ai/ai/openai_client.py +7 -5
- mage_ai/api/policies/PipelineSchedulePolicy.py +1 -0
- mage_ai/api/presenters/PipelineSchedulePresenter.py +11 -2
- mage_ai/api/resources/GitFileResource.py +8 -0
- mage_ai/api/resources/PipelineScheduleResource.py +20 -14
- mage_ai/api/resources/PipelineTriggerResource.py +3 -1
- mage_ai/api/resources/SessionResource.py +2 -2
- mage_ai/api/resources/SyncResource.py +1 -1
- mage_ai/api/resources/UserResource.py +1 -1
- mage_ai/cli/main.py +8 -1
- mage_ai/data_cleaner/analysis/charts.py +1 -1
- mage_ai/data_cleaner/cleaning_rules/reformat_values.py +1 -1
- mage_ai/data_integrations/destinations/constants.py +3 -0
- mage_ai/data_integrations/sources/constants.py +2 -0
- mage_ai/data_preparation/executors/block_executor.py +8 -3
- mage_ai/data_preparation/executors/pipeline_executor.py +35 -19
- mage_ai/data_preparation/git/utils.py +2 -2
- mage_ai/data_preparation/logging/logger_manager.py +31 -2
- mage_ai/data_preparation/models/block/__init__.py +33 -27
- mage_ai/data_preparation/models/block/dbt/dbt_adapter.py +20 -8
- mage_ai/data_preparation/models/block/dynamic/constants.py +0 -1
- mage_ai/data_preparation/models/block/dynamic/counter.py +1 -3
- mage_ai/data_preparation/models/block/outputs.py +7 -1
- mage_ai/data_preparation/models/block/r/__init__.py +16 -5
- mage_ai/data_preparation/models/block/sql/__init__.py +2 -0
- mage_ai/data_preparation/models/block/sql/mssql.py +8 -0
- mage_ai/data_preparation/models/block/sql/utils/shared.py +6 -2
- mage_ai/data_preparation/models/constants.py +4 -1
- mage_ai/data_preparation/models/pipeline.py +11 -2
- mage_ai/data_preparation/models/project/__init__.py +3 -1
- mage_ai/data_preparation/models/triggers/__init__.py +1 -1
- mage_ai/data_preparation/storage/local_storage.py +4 -1
- mage_ai/data_preparation/templates/constants.py +7 -0
- mage_ai/data_preparation/templates/data_exporters/streaming/elasticsearch.yaml +3 -0
- mage_ai/data_preparation/templates/data_loaders/airtable.py +28 -0
- mage_ai/data_preparation/templates/data_loaders/streaming/nats.yaml +6 -3
- mage_ai/data_preparation/templates/repo/io_config.yaml +2 -0
- mage_ai/io/airtable.py +104 -0
- mage_ai/io/base.py +30 -1
- mage_ai/io/bigquery.py +36 -0
- mage_ai/io/config.py +6 -0
- mage_ai/io/mssql.py +21 -9
- mage_ai/io/mysql.py +6 -1
- mage_ai/io/oracledb.py +2 -4
- mage_ai/io/postgres.py +41 -19
- mage_ai/io/qdrant.py +1 -1
- mage_ai/io/redshift.py +13 -0
- mage_ai/io/sql.py +1 -0
- mage_ai/io/utils.py +18 -0
- mage_ai/orchestration/db/__init__.py +23 -3
- mage_ai/orchestration/db/migrations/versions/39d36f1dab73_create_genericjob.py +47 -0
- mage_ai/orchestration/db/models/oauth.py +2 -1
- mage_ai/orchestration/db/models/schedules.py +108 -6
- mage_ai/orchestration/db/models/schedules_project_platform.py +1 -1
- mage_ai/orchestration/db/models/secrets.py +11 -1
- mage_ai/orchestration/job_manager.py +19 -0
- mage_ai/orchestration/metrics/pipeline_run.py +1 -1
- mage_ai/orchestration/notification/sender.py +2 -2
- mage_ai/orchestration/pipeline_scheduler_original.py +150 -6
- mage_ai/orchestration/pipeline_scheduler_project_platform.py +4 -5
- mage_ai/orchestration/queue/config.py +11 -1
- mage_ai/orchestration/queue/process_queue.py +4 -0
- mage_ai/orchestration/utils/distributed_lock.py +8 -1
- mage_ai/orchestration/utils/resources.py +56 -2
- mage_ai/sample_datasets/salary_survey.csv +52 -52
- mage_ai/server/api/base.py +41 -0
- mage_ai/server/api/constants.py +1 -0
- mage_ai/server/api/triggers.py +9 -0
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +3 -3
- mage_ai/server/frontend_dist/_next/static/TUo4RceCdMufBTBTq8CAq/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{1187-839336d276186105.js → 1187-4560c3895e1d7099.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{1598-0adca9dce3ba4c60.js → 1598-cbf3f5a6078fc3f5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-638a944d24d5abde.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3548-36f746b1824004f2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{3763-39a5174f6a3924db.js → 3763-aabe2703076636b0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-3e2acb5ed45b582b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/5627-d5e559859dd0e1e0.js → frontend_dist/_next/static/chunks/5627-10e76bafa5a26f5f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{5699-e49718dfc9eb2854.js → 5699-e99379e332bd0b41.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{7966-163da2621b8c987c.js → 7966-a5a7db345ce81263.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-b697b35dfc4e6e26.js +2 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/compute-ed67fa8e81662e8b.js → frontend_dist/_next/static/chunks/pages/compute-9e2dea78024e3bb4.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/files-e0ecd7ced09a63b2.js → frontend_dist/_next/static/chunks/pages/files-e08c7fe76f968f9c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-c7a729477ecda50e.js → [...slug]-30c3807057a4e65b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-fd6ae6a358a60a0c.js → global-data-products-8dcb3b31af9e0e39.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-8e50243797a7fe59.js → frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-85a64b64d27214b6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-hooks-d0c003446332dc0d.js → global-hooks-4ff959d51b8a9502.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{files-a69ed8e9f814490c.js → files-d08a460641d0efaa.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{overview-1aad7093c6d39257.js → overview-aae747f487e08d51.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{pipeline-runs-528d30e0d13b0cc7.js → pipeline-runs-09a842d64a6ada62.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{settings-fb9201d9cf63031d.js → settings-2e98e57d9376a458.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/{[user]-000f5a980a07da39.js → [user]-7be6e41ad66089bb.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-e4e613f6e817a733.js → frontend_dist/_next/static/chunks/pages/manage/users/new-4c088833063bfa07.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage-34d718b8a4066c23.js → frontend_dist/_next/static/chunks/pages/manage-868fcd8cbeb265f0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{oauth-3bfd1b8d7f036726.js → oauth-6ceceb62191dfe8a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{pipeline-runs-5f8c100e648efa8a.js → pipeline-runs-2d0136b51b57de93.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-688c652f3296bb9c.js → [...slug]-1ad5238742e25b4c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-bd11e87d026bfbf9.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{dashboard-1236e36d39b1637d.js → dashboard-0f4f47f721b0723f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-5ae8efe9e0530212.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-fe91dfb0091f6bc6.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-0d68d4bf6290fefb.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-cf794b2d22a80f31.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-9254358d58f07714.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-a964caef91bed9e1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-821001e690caebe2.js → monitors-80bebb4401eefe25.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-2eae7cb017027682.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d4b2a0800a66b33.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-776b2e5b0b6ceba8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-707ed8ca942ca802.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/{[...slug]-259143ed3cf59e31.js → [...slug]-8429f17d4146e1ec.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-193045d9836d8d80.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/platform/global-hooks/{[...slug]-5eeec927e4202b63.js → [...slug]-6834ae87bd668cb2.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks-fbe9ad995d46d837.js → frontend_dist/_next/static/chunks/pages/platform/global-hooks-b3f7309a23e592b2.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/{profile-fc659962d4015cb3.js → profile-f8b7374385e1f1bf.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-8de68502a9afa299.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-a4f88c334414402b.js → frontend_dist/_next/static/chunks/pages/settings/platform/settings-50fb6a34f3913f1f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-4deb9579ef99a3c6.js → [...slug]-2e5c098c21ea32b7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-e0cda2f2bfce8d61.js → permissions-54e4b15b9585bfc4.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-040f83d75d0f6537.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-910257d16c604ebd.js → [...slug]-95088f43034e3c95.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{roles-4f7a0756806cee34.js → roles-e9149e1fcf218f42.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{sync-data-208d6f955204d704.js → sync-data-75b67ae4a00818ef.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-c89dc67e5a1706a8.js → [...slug]-557dda05ca6c6124.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{sign-in-054b33312d3193c3.js → sign-in-593c40985d63fcf7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/{[...slug]-b6ed6a5d818bfd20.js → [...slug]-252c4b6b818345d5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{templates-852357bc983af2ea.js → templates-ca528bc607753ab8.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/terminal-1f9c56d671bbc67d.js → frontend_dist/_next/static/chunks/pages/terminal-287362c1defcc96b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/test-2f83af8c9f1378fe.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-d9de73fb799efed8.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/version-control-ae3469b992a341d6.js → frontend_dist/_next/static/chunks/pages/version-control-573f0225d7a703ed.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/overview.html +6 -6
- mage_ai/server/frontend_dist/manage/pipeline-runs.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 +7 -7
- 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/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist/v2.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/404.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/_next/static/2QL-FT4lFR0a9bDZ7lNd9/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1187-839336d276186105.js → 1187-4560c3895e1d7099.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1598-0adca9dce3ba4c60.js → 1598-cbf3f5a6078fc3f5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-638a944d24d5abde.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-36f746b1824004f2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3763-39a5174f6a3924db.js → 3763-aabe2703076636b0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-3e2acb5ed45b582b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/5627-d5e559859dd0e1e0.js → frontend_dist_base_path_template/_next/static/chunks/5627-10e76bafa5a26f5f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5699-e49718dfc9eb2854.js → 5699-e99379e332bd0b41.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7966-163da2621b8c987c.js → 7966-a5a7db345ce81263.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-f205accb03b9ff43.js +2 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/compute-ed67fa8e81662e8b.js → frontend_dist_base_path_template/_next/static/chunks/pages/compute-9e2dea78024e3bb4.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/files-e0ecd7ced09a63b2.js → frontend_dist_base_path_template/_next/static/chunks/pages/files-e08c7fe76f968f9c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-c7a729477ecda50e.js → [...slug]-30c3807057a4e65b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-fd6ae6a358a60a0c.js → global-data-products-8dcb3b31af9e0e39.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-8e50243797a7fe59.js → frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-85a64b64d27214b6.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-hooks-d0c003446332dc0d.js → global-hooks-4ff959d51b8a9502.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{files-a69ed8e9f814490c.js → files-d08a460641d0efaa.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{overview-1aad7093c6d39257.js → overview-aae747f487e08d51.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{pipeline-runs-528d30e0d13b0cc7.js → pipeline-runs-09a842d64a6ada62.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{settings-fb9201d9cf63031d.js → settings-2e98e57d9376a458.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/{[user]-000f5a980a07da39.js → [user]-7be6e41ad66089bb.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users/new-e4e613f6e817a733.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-4c088833063bfa07.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage-34d718b8a4066c23.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage-868fcd8cbeb265f0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{oauth-3bfd1b8d7f036726.js → oauth-6ceceb62191dfe8a.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{pipeline-runs-5f8c100e648efa8a.js → pipeline-runs-2d0136b51b57de93.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-688c652f3296bb9c.js → [...slug]-1ad5238742e25b4c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-bd11e87d026bfbf9.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{dashboard-1236e36d39b1637d.js → dashboard-0f4f47f721b0723f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-5ae8efe9e0530212.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-fe91dfb0091f6bc6.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-0d68d4bf6290fefb.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-cf794b2d22a80f31.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-9254358d58f07714.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-a964caef91bed9e1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-821001e690caebe2.js → monitors-80bebb4401eefe25.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-2eae7cb017027682.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d4b2a0800a66b33.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-776b2e5b0b6ceba8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-707ed8ca942ca802.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/{[...slug]-259143ed3cf59e31.js → [...slug]-8429f17d4146e1ec.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-193045d9836d8d80.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks/{[...slug]-5eeec927e4202b63.js → [...slug]-6834ae87bd668cb2.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/platform/global-hooks-fbe9ad995d46d837.js → frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks-b3f7309a23e592b2.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/{profile-fc659962d4015cb3.js → profile-f8b7374385e1f1bf.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-8de68502a9afa299.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/platform/settings-a4f88c334414402b.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-50fb6a34f3913f1f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-4deb9579ef99a3c6.js → [...slug]-2e5c098c21ea32b7.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-e0cda2f2bfce8d61.js → permissions-54e4b15b9585bfc4.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-040f83d75d0f6537.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-910257d16c604ebd.js → [...slug]-95088f43034e3c95.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{roles-4f7a0756806cee34.js → roles-e9149e1fcf218f42.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{sync-data-208d6f955204d704.js → sync-data-75b67ae4a00818ef.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-c89dc67e5a1706a8.js → [...slug]-557dda05ca6c6124.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{sign-in-054b33312d3193c3.js → sign-in-593c40985d63fcf7.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/{[...slug]-b6ed6a5d818bfd20.js → [...slug]-252c4b6b818345d5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{templates-852357bc983af2ea.js → templates-ca528bc607753ab8.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/terminal-1f9c56d671bbc67d.js → frontend_dist_base_path_template/_next/static/chunks/pages/terminal-287362c1defcc96b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-2f83af8c9f1378fe.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-d9de73fb799efed8.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/version-control-ae3469b992a341d6.js → frontend_dist_base_path_template/_next/static/chunks/pages/version-control-573f0225d7a703ed.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-12ad70eb5c31aa92.js → webpack-5f4be622608d9267.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/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/overview.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/pipeline-runs.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 +7 -7
- 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/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/v2.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/version-control.html +6 -6
- mage_ai/server/scheduler_manager.py +2 -0
- mage_ai/server/server.py +13 -0
- mage_ai/server/terminal_server.py +3 -0
- mage_ai/server/utils/output_display.py +5 -3
- mage_ai/services/aws/events/events.py +2 -2
- mage_ai/services/gcp/cloud_run/cloud_run.py +1 -1
- mage_ai/services/teams/config.py +13 -2
- mage_ai/services/teams/teams.py +13 -11
- mage_ai/settings/server.py +12 -1
- mage_ai/shared/constants.py +3 -1
- mage_ai/shared/croniter.py +1398 -0
- mage_ai/shared/enum.py +2 -5
- mage_ai/shared/environments.py +27 -3
- mage_ai/streaming/sinks/elasticsearch.py +15 -5
- mage_ai/streaming/sinks/kafka.py +21 -3
- mage_ai/streaming/sources/kafka.py +64 -7
- mage_ai/streaming/sources/kafka_oauth.py +182 -0
- mage_ai/tests/api/endpoints/test_blocks.py +1 -101
- mage_ai/tests/api/endpoints/test_configuration_options.py +1 -48
- mage_ai/tests/api/endpoints/test_configuration_options_project_platform.py +68 -0
- mage_ai/tests/api/endpoints/test_custom_designs.py +1 -106
- mage_ai/tests/api/endpoints/test_custom_designs_project_platform.py +132 -0
- mage_ai/tests/api/endpoints/test_dbt_blocks.py +111 -0
- mage_ai/tests/api/endpoints/test_file_contents.py +0 -48
- mage_ai/tests/api/endpoints/test_file_contents_with_project_platform.py +66 -0
- mage_ai/tests/api/endpoints/test_pipelines.py +0 -134
- mage_ai/tests/api/endpoints/test_pipelines_with_project_platform.py +143 -0
- mage_ai/tests/data_preparation/executors/test_block_executor.py +3 -3
- mage_ai/tests/data_preparation/logging/test_logger_manager.py +24 -5
- mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +1 -3
- mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +3 -3
- mage_ai/tests/data_preparation/models/test_block.py +7 -0
- mage_ai/tests/data_preparation/models/test_pipeline.py +55 -0
- mage_ai/tests/data_preparation/models/test_variable.py +2 -0
- mage_ai/tests/data_preparation/test_repo_manager.py +0 -63
- mage_ai/tests/data_preparation/test_repo_manager_project_platform.py +67 -0
- mage_ai/tests/data_preparation/test_variable_manager.py +0 -51
- mage_ai/tests/data_preparation/test_variable_manager_project_platform.py +41 -0
- mage_ai/tests/io/create_table/test_postgresql.py +28 -0
- mage_ai/tests/orchestration/db/models/test_schedules.py +1 -1
- mage_ai/tests/orchestration/notification/test_config.py +3 -3
- mage_ai/tests/orchestration/notification/test_sender.py +5 -1
- mage_ai/tests/orchestration/utils/__init__.py +0 -0
- mage_ai/tests/orchestration/utils/test_resources.py +235 -0
- mage_ai/tests/shared/test_croniter.py +2541 -0
- mage_ai/tests/streaming/sinks/test_kafka.py +130 -0
- mage_ai/tests/streaming/sources/test_kafka.py +125 -3
- mage_ai/tests/streaming/sources/test_kafka_oauth.py +208 -0
- mage_ai/tests/streaming/sources/test_kafka_raw_value.py +105 -0
- mage_ai/usage_statistics/logger.py +99 -15
- mage_ai-0.9.79.dist-info/METADATA +358 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/RECORD +377 -359
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/WHEEL +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1557-1ad0c64c2d08e569.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-d65056b6b5e124eb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3548-b2c5edfb710886a6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-4b3091e550f809a2.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-5bdff745074fb350.js +0 -2
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-a5e9d77ed5b50205.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-69af3253ad0d0d89.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-fe112809feb25b05.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e9ca358209cdf93d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-a29f1615d2e7d330.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-6d382ae5bad9745c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-cd49372ae1702963.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-135be8974f7f5f2b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-3af13e89adff4d6c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-b578b075a8d857e3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-058d283ee178c038.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-7b02bb70462144cb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-5212c01a9dc558da.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/test-86b12cc12d4a625f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-2481c40b18d5b6d4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/pLWT6Sqd09xYpufCVIqnz/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/JQewSAObpbhO0wrdAM6Ng/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-1ad0c64c2d08e569.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-d65056b6b5e124eb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-b2c5edfb710886a6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-4b3091e550f809a2.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-90de19bc03f1484b.js +0 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-a5e9d77ed5b50205.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-69af3253ad0d0d89.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-fe112809feb25b05.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e9ca358209cdf93d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-a29f1615d2e7d330.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-6d382ae5bad9745c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-cd49372ae1702963.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-135be8974f7f5f2b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-3af13e89adff4d6c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-b578b075a8d857e3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-058d283ee178c038.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-7b02bb70462144cb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-5212c01a9dc558da.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-86b12cc12d4a625f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-2481c40b18d5b6d4.js +0 -1
- mage_ai-0.9.74.dist-info/METADATA +0 -544
- /mage_ai/server/frontend_dist/_next/static/{pLWT6Sqd09xYpufCVIqnz → TUo4RceCdMufBTBTq8CAq}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-5bdff745074fb350.js.LICENSE.txt → _app-b697b35dfc4e6e26.js.LICENSE.txt} +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{JQewSAObpbhO0wrdAM6Ng → 2QL-FT4lFR0a9bDZ7lNd9}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-90de19bc03f1484b.js.LICENSE.txt → _app-f205accb03b9ff43.js.LICENSE.txt} +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info/licenses}/LICENSE +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,7 @@ class JobType(StrEnum):
|
|
|
8
8
|
BLOCK_RUN = 'block_run'
|
|
9
9
|
PIPELINE_RUN = 'pipeline_run'
|
|
10
10
|
INTEGRATION_STREAM = 'integration_stream'
|
|
11
|
+
GENERIC_JOB = 'generic_job'
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class JobManager:
|
|
@@ -62,6 +63,19 @@ class JobManager:
|
|
|
62
63
|
logging_tags=logging_tags,
|
|
63
64
|
)
|
|
64
65
|
|
|
66
|
+
def has_generic_job(
|
|
67
|
+
self,
|
|
68
|
+
generic_job_id: int,
|
|
69
|
+
logger=None,
|
|
70
|
+
logging_tags: Dict = None,
|
|
71
|
+
) -> bool:
|
|
72
|
+
job_id = self.__job_id(JobType.GENERIC_JOB, generic_job_id)
|
|
73
|
+
return self.queue.has_job(
|
|
74
|
+
job_id,
|
|
75
|
+
logger=logger,
|
|
76
|
+
logging_tags=logging_tags,
|
|
77
|
+
)
|
|
78
|
+
|
|
65
79
|
def kill_block_run_job(self, block_run_id):
|
|
66
80
|
print(f'Kill block run id: {block_run_id}')
|
|
67
81
|
job_id = self.__job_id(JobType.BLOCK_RUN, block_run_id)
|
|
@@ -78,6 +92,11 @@ class JobManager:
|
|
|
78
92
|
job_id = self.__job_id(JobType.INTEGRATION_STREAM, id)
|
|
79
93
|
return self.queue.kill_job(job_id)
|
|
80
94
|
|
|
95
|
+
def kill_generic_job(self, generic_job_id):
|
|
96
|
+
print(f'Kill generic job id: {generic_job_id}')
|
|
97
|
+
job_id = self.__job_id(JobType.GENERIC_JOB, generic_job_id)
|
|
98
|
+
return self.queue.kill_job(job_id)
|
|
99
|
+
|
|
81
100
|
def start(self):
|
|
82
101
|
self.queue.start()
|
|
83
102
|
|
|
@@ -220,7 +220,7 @@ def __calculate_metrics(pipeline_run: PipelineRun, pipeline) -> Dict:
|
|
|
220
220
|
|
|
221
221
|
pipeline_metrics_by_stream = {}
|
|
222
222
|
pipeline_logs_by_stream = {}
|
|
223
|
-
pipeline_logs = pipeline_run.logs['content'].split('\n')
|
|
223
|
+
pipeline_logs = pipeline_run.logs[0]['content'].split('\n')
|
|
224
224
|
for pipeline_log in pipeline_logs:
|
|
225
225
|
tags = parse_line(pipeline_log)
|
|
226
226
|
stream = tags.get('stream')
|
|
@@ -69,7 +69,7 @@ class NotificationSender:
|
|
|
69
69
|
|
|
70
70
|
if self.config.teams_config is not None and self.config.teams_config.is_valid:
|
|
71
71
|
try:
|
|
72
|
-
send_teams_message(self.config.teams_config, summary)
|
|
72
|
+
send_teams_message(self.config.teams_config, summary, title)
|
|
73
73
|
except Exception:
|
|
74
74
|
traceback.print_exc()
|
|
75
75
|
|
|
@@ -87,7 +87,7 @@ class NotificationSender:
|
|
|
87
87
|
|
|
88
88
|
if self.config.google_chat_config is not None and self.config.google_chat_config.is_valid:
|
|
89
89
|
try:
|
|
90
|
-
send_google_chat_message(self.config.google_chat_config, summary)
|
|
90
|
+
send_google_chat_message(self.config.google_chat_config, summary, title)
|
|
91
91
|
except Exception:
|
|
92
92
|
traceback.print_exc()
|
|
93
93
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import collections
|
|
3
2
|
import os
|
|
4
3
|
import traceback
|
|
@@ -33,6 +32,7 @@ from mage_ai.orchestration.db.models.schedules import (
|
|
|
33
32
|
Backfill,
|
|
34
33
|
BlockRun,
|
|
35
34
|
EventMatcher,
|
|
35
|
+
GenericJob,
|
|
36
36
|
PipelineRun,
|
|
37
37
|
PipelineSchedule,
|
|
38
38
|
)
|
|
@@ -260,7 +260,7 @@ class PipelineScheduler:
|
|
|
260
260
|
pipeline=self.pipeline,
|
|
261
261
|
pipeline_run=self.pipeline_run,
|
|
262
262
|
)
|
|
263
|
-
|
|
263
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
264
264
|
|
|
265
265
|
self.logger_manager.output_logs_to_destination()
|
|
266
266
|
|
|
@@ -339,7 +339,7 @@ class PipelineScheduler:
|
|
|
339
339
|
error_msg: str,
|
|
340
340
|
status=PipelineRun.PipelineRunStatus.FAILED,
|
|
341
341
|
) -> None:
|
|
342
|
-
|
|
342
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
343
343
|
|
|
344
344
|
if status == PipelineRun.PipelineRunStatus.FAILED:
|
|
345
345
|
# Only send notification when pipeline run status is FAILED
|
|
@@ -929,6 +929,81 @@ class PipelineScheduler:
|
|
|
929
929
|
self.memory_usage_failure(tags=tags)
|
|
930
930
|
|
|
931
931
|
|
|
932
|
+
def on_pipeline_run_cancelled(
|
|
933
|
+
job_id: int,
|
|
934
|
+
pipeline_run_id: int,
|
|
935
|
+
cancelled_block_run_ids: List,
|
|
936
|
+
):
|
|
937
|
+
job = GenericJob.query.get(job_id)
|
|
938
|
+
if job.status not in [
|
|
939
|
+
GenericJob.JobStatus.INITIAL,
|
|
940
|
+
GenericJob.JobStatus.QUEUED,
|
|
941
|
+
GenericJob.JobStatus.RUNNING,
|
|
942
|
+
]:
|
|
943
|
+
return
|
|
944
|
+
job.mark_running()
|
|
945
|
+
|
|
946
|
+
if not pipeline_run_id:
|
|
947
|
+
job.mark_failed(
|
|
948
|
+
metadata=dict(
|
|
949
|
+
error_message='Pipeline run id is not provided in the job.',
|
|
950
|
+
),
|
|
951
|
+
)
|
|
952
|
+
return
|
|
953
|
+
if not cancelled_block_run_ids:
|
|
954
|
+
job.mark_failed(
|
|
955
|
+
metadata=dict(
|
|
956
|
+
error_message='Cancelled block run ids are not provided in the job.',
|
|
957
|
+
),
|
|
958
|
+
)
|
|
959
|
+
return
|
|
960
|
+
|
|
961
|
+
try:
|
|
962
|
+
# Run callback blocks for cancelled block runs
|
|
963
|
+
pipeline_run = PipelineRun.query.get(pipeline_run_id)
|
|
964
|
+
if not pipeline_run:
|
|
965
|
+
raise Exception(f'Fail to retrieve pipeline run with id {pipeline_run_id}')
|
|
966
|
+
pipeline_schedule = pipeline_run.pipeline_schedule
|
|
967
|
+
pipeline = get_pipeline_from_platform(
|
|
968
|
+
pipeline_run.pipeline_uuid,
|
|
969
|
+
repo_path=pipeline_schedule.repo_path if pipeline_schedule else None,
|
|
970
|
+
)
|
|
971
|
+
if pipeline_run.status != PipelineRun.PipelineRunStatus.CANCELLED:
|
|
972
|
+
job.mark_failed(
|
|
973
|
+
metadata=dict(
|
|
974
|
+
error_message=f'Pipeline run {pipeline_run_id} is not in cancelled status.',
|
|
975
|
+
),
|
|
976
|
+
)
|
|
977
|
+
return
|
|
978
|
+
for block_run_id in cancelled_block_run_ids:
|
|
979
|
+
block_run = BlockRun.query.get(block_run_id)
|
|
980
|
+
if not block_run:
|
|
981
|
+
continue
|
|
982
|
+
if block_run.status != BlockRun.BlockRunStatus.CANCELLED:
|
|
983
|
+
continue
|
|
984
|
+
ExecutorFactory.get_block_executor(
|
|
985
|
+
pipeline,
|
|
986
|
+
block_run.block_uuid,
|
|
987
|
+
block_run_id=block_run.id,
|
|
988
|
+
execution_partition=pipeline_run.execution_partition,
|
|
989
|
+
executor_type=ExecutorType.LOCAL_PYTHON,
|
|
990
|
+
).execute_callback(
|
|
991
|
+
callback='on_cancelled',
|
|
992
|
+
global_vars=pipeline_run.get_variables(),
|
|
993
|
+
logging_tags=None,
|
|
994
|
+
pipeline_run=pipeline_run,
|
|
995
|
+
block_run_id=block_run_id,
|
|
996
|
+
)
|
|
997
|
+
except Exception as e:
|
|
998
|
+
job.mark_failed(
|
|
999
|
+
metadata=dict(
|
|
1000
|
+
error_message=f'Failed to run pipeline run cancellation hook: {e}.',
|
|
1001
|
+
),
|
|
1002
|
+
)
|
|
1003
|
+
return
|
|
1004
|
+
job.mark_completed()
|
|
1005
|
+
|
|
1006
|
+
|
|
932
1007
|
def run_integration_streams(
|
|
933
1008
|
streams: List[Dict],
|
|
934
1009
|
*args,
|
|
@@ -1372,7 +1447,7 @@ def stop_pipeline_run(
|
|
|
1372
1447
|
# Update pipeline run status to cancelled
|
|
1373
1448
|
pipeline_run.update(status=status)
|
|
1374
1449
|
|
|
1375
|
-
|
|
1450
|
+
UsageStatisticLogger().pipeline_run_ended_sync(pipeline_run)
|
|
1376
1451
|
|
|
1377
1452
|
# Cancel all the block runs
|
|
1378
1453
|
cancel_block_runs_and_jobs(pipeline_run, pipeline)
|
|
@@ -1407,8 +1482,9 @@ def cancel_block_runs_and_jobs(
|
|
|
1407
1482
|
block_runs_to_cancel.append(b)
|
|
1408
1483
|
if b.status == BlockRun.BlockRunStatus.RUNNING:
|
|
1409
1484
|
running_blocks.append(b)
|
|
1485
|
+
cancelled_block_run_ids = [b.id for b in block_runs_to_cancel]
|
|
1410
1486
|
BlockRun.batch_update_status(
|
|
1411
|
-
|
|
1487
|
+
cancelled_block_run_ids,
|
|
1412
1488
|
BlockRun.BlockRunStatus.CANCELLED,
|
|
1413
1489
|
)
|
|
1414
1490
|
|
|
@@ -1436,6 +1512,18 @@ def cancel_block_runs_and_jobs(
|
|
|
1436
1512
|
for b in running_blocks:
|
|
1437
1513
|
job_manager.kill_block_run_job(b.id)
|
|
1438
1514
|
|
|
1515
|
+
GenericJob.enqueue_cancel_pipeline_run(pipeline_run.id, cancelled_block_run_ids)
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
def kill_cancelled_runs(pipeline_run_id: int, cancelled_block_run_ids: List):
|
|
1519
|
+
job_manager = get_job_manager()
|
|
1520
|
+
if pipeline_run_id and job_manager.has_pipeline_run_job(pipeline_run_id):
|
|
1521
|
+
job_manager.kill_pipeline_run_job(pipeline_run_id)
|
|
1522
|
+
if cancelled_block_run_ids:
|
|
1523
|
+
for block_run_id in cancelled_block_run_ids:
|
|
1524
|
+
if job_manager.has_block_run_job(block_run_id):
|
|
1525
|
+
job_manager.kill_block_run_job(block_run_id)
|
|
1526
|
+
|
|
1439
1527
|
|
|
1440
1528
|
def check_sla():
|
|
1441
1529
|
repo_pipelines = set(
|
|
@@ -1584,7 +1672,7 @@ def schedule_all():
|
|
|
1584
1672
|
pipeline_runs_excluded_by_limit = []
|
|
1585
1673
|
for pipeline_schedule in active_schedules:
|
|
1586
1674
|
lock_key = f'pipeline_schedule_{pipeline_schedule.id}'
|
|
1587
|
-
if not lock.try_acquire_lock(lock_key):
|
|
1675
|
+
if not lock.try_acquire_lock(lock_key, timeout=30):
|
|
1588
1676
|
continue
|
|
1589
1677
|
|
|
1590
1678
|
trigger_pipeline_run_limit = pipeline_schedule.get_settings().pipeline_run_limit
|
|
@@ -1733,6 +1821,13 @@ def schedule_all():
|
|
|
1733
1821
|
logger.exception(f'Failed to schedule {r}')
|
|
1734
1822
|
traceback.print_exc()
|
|
1735
1823
|
continue
|
|
1824
|
+
|
|
1825
|
+
try:
|
|
1826
|
+
schedule_generic_jobs()
|
|
1827
|
+
except Exception as e:
|
|
1828
|
+
logger.exception(f'Failed to schedule generic jobs {e}')
|
|
1829
|
+
traceback.print_exc()
|
|
1830
|
+
|
|
1736
1831
|
job_manager = get_job_manager()
|
|
1737
1832
|
if job_manager is None:
|
|
1738
1833
|
logger.info('Job manager is None.')
|
|
@@ -1913,3 +2008,52 @@ def sync_schedules(pipeline_uuids: List[str]):
|
|
|
1913
2008
|
trigger_configs.append(pipeline_trigger)
|
|
1914
2009
|
|
|
1915
2010
|
PipelineSchedule.create_or_update_batch(trigger_configs)
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
def schedule_generic_jobs():
|
|
2014
|
+
"""
|
|
2015
|
+
Schedule generic jobs that are in INITIAL status.
|
|
2016
|
+
|
|
2017
|
+
This method schedules jobs like cancel_pipeline_run that have been enqueued
|
|
2018
|
+
by the server process and are waiting to be executed by the job manager.
|
|
2019
|
+
"""
|
|
2020
|
+
try:
|
|
2021
|
+
# Get all jobs with INITIAL status across all repositories
|
|
2022
|
+
jobs = GenericJob.get_jobs_with_initial_status()
|
|
2023
|
+
job_manager = get_job_manager()
|
|
2024
|
+
|
|
2025
|
+
if not jobs:
|
|
2026
|
+
return
|
|
2027
|
+
|
|
2028
|
+
logger.info(f'Scheduling {len(jobs)} generic jobs')
|
|
2029
|
+
|
|
2030
|
+
# Schedule each job with the job manager
|
|
2031
|
+
for job in jobs:
|
|
2032
|
+
try:
|
|
2033
|
+
if job.job_type == GenericJob.JobType.CANCEL_PIPELINE_RUN:
|
|
2034
|
+
pipeline_run_id = job.payload.get('pipeline_run_id')
|
|
2035
|
+
cancelled_block_run_ids = job.payload.get('cancelled_block_run_ids')
|
|
2036
|
+
try:
|
|
2037
|
+
kill_cancelled_runs(pipeline_run_id, cancelled_block_run_ids)
|
|
2038
|
+
except Exception:
|
|
2039
|
+
pass
|
|
2040
|
+
# Add job to job manager for execution
|
|
2041
|
+
job_manager.add_job(
|
|
2042
|
+
JobType.GENERIC_JOB,
|
|
2043
|
+
job.id,
|
|
2044
|
+
on_pipeline_run_cancelled,
|
|
2045
|
+
# args
|
|
2046
|
+
job.id,
|
|
2047
|
+
pipeline_run_id,
|
|
2048
|
+
cancelled_block_run_ids,
|
|
2049
|
+
)
|
|
2050
|
+
job.mark_queued()
|
|
2051
|
+
logger.info(f'Scheduled generic job {job.id} ({job.job_type})')
|
|
2052
|
+
else:
|
|
2053
|
+
raise ValueError(f"Unknown job type: {job.job_type}")
|
|
2054
|
+
except Exception as e:
|
|
2055
|
+
error_message = f"Failed to schedule generic job: {str(e)}"
|
|
2056
|
+
logger.exception(f'Failed to schedule generic job {job.id}: {error_message}')
|
|
2057
|
+
job.mark_failed({'error': error_message})
|
|
2058
|
+
except Exception as e:
|
|
2059
|
+
logger.exception(f'Failed to schedule generic jobs: {e}')
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import collections
|
|
3
2
|
import os
|
|
4
3
|
import traceback
|
|
@@ -262,7 +261,7 @@ class PipelineScheduler:
|
|
|
262
261
|
pipeline_run=self.pipeline_run,
|
|
263
262
|
)
|
|
264
263
|
|
|
265
|
-
|
|
264
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
266
265
|
|
|
267
266
|
self.logger_manager.output_logs_to_destination()
|
|
268
267
|
|
|
@@ -338,7 +337,7 @@ class PipelineScheduler:
|
|
|
338
337
|
|
|
339
338
|
@safe_db_query
|
|
340
339
|
def on_pipeline_run_failure(self, error: str) -> None:
|
|
341
|
-
|
|
340
|
+
UsageStatisticLogger().pipeline_run_ended_sync(self.pipeline_run)
|
|
342
341
|
self.notification_sender.send_pipeline_run_failure_message(
|
|
343
342
|
pipeline=self.pipeline,
|
|
344
343
|
pipeline_run=self.pipeline_run,
|
|
@@ -1317,7 +1316,7 @@ def stop_pipeline_run(
|
|
|
1317
1316
|
# Update pipeline run status to cancelled
|
|
1318
1317
|
pipeline_run.update(status=status)
|
|
1319
1318
|
|
|
1320
|
-
|
|
1319
|
+
UsageStatisticLogger().pipeline_run_ended_sync(pipeline_run)
|
|
1321
1320
|
|
|
1322
1321
|
# Cancel all the block runs
|
|
1323
1322
|
cancel_block_runs_and_jobs(pipeline_run, pipeline)
|
|
@@ -1568,7 +1567,7 @@ def schedule_all():
|
|
|
1568
1567
|
concurrency_config = ConcurrencyConfig.load(config=pipeline.concurrency_config)
|
|
1569
1568
|
|
|
1570
1569
|
lock_key = f'pipeline_schedule_{pipeline_schedule.id}'
|
|
1571
|
-
if not lock.try_acquire_lock(lock_key):
|
|
1570
|
+
if not lock.try_acquire_lock(lock_key, timeout=30):
|
|
1572
1571
|
continue
|
|
1573
1572
|
|
|
1574
1573
|
try:
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import traceback
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
|
|
3
4
|
from mage_ai.shared.config import BaseConfig
|
|
4
5
|
from mage_ai.shared.enum import StrEnum
|
|
5
6
|
|
|
7
|
+
DEFAULT_CONCURRENCY = 20
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
class QueueType(StrEnum):
|
|
8
11
|
CELERY = 'celery'
|
|
@@ -17,5 +20,12 @@ class ProcessQueueConfig(BaseConfig):
|
|
|
17
20
|
@dataclass
|
|
18
21
|
class QueueConfig(BaseConfig):
|
|
19
22
|
queue_type: QueueType = QueueType.PROCESS
|
|
20
|
-
concurrency: int =
|
|
23
|
+
concurrency: int = DEFAULT_CONCURRENCY
|
|
21
24
|
process_queue_config: ProcessQueueConfig = None
|
|
25
|
+
|
|
26
|
+
def __post_init__(self):
|
|
27
|
+
try:
|
|
28
|
+
self.concurrency = int(self.concurrency)
|
|
29
|
+
except Exception:
|
|
30
|
+
traceback.print_exc()
|
|
31
|
+
self.concurrency = DEFAULT_CONCURRENCY
|
|
@@ -19,6 +19,7 @@ from mage_ai.settings import (
|
|
|
19
19
|
HOSTNAME,
|
|
20
20
|
REDIS_URL,
|
|
21
21
|
SENTRY_DSN,
|
|
22
|
+
SENTRY_SERVER_NAME,
|
|
22
23
|
SENTRY_TRACES_SAMPLE_RATE,
|
|
23
24
|
SERVER_LOGGING_FORMAT,
|
|
24
25
|
SERVER_VERBOSITY,
|
|
@@ -287,7 +288,10 @@ class Worker(mp.Process):
|
|
|
287
288
|
sentry_sdk.init(
|
|
288
289
|
self.dsn,
|
|
289
290
|
traces_sample_rate=SENTRY_TRACES_SAMPLE_RATE,
|
|
291
|
+
server_name=SENTRY_SERVER_NAME,
|
|
290
292
|
)
|
|
293
|
+
import atexit
|
|
294
|
+
atexit.register(lambda: sentry_sdk.flush(timeout=5))
|
|
291
295
|
initialize_new_relic()
|
|
292
296
|
|
|
293
297
|
set_logging_format(
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from mage_ai.services.redis.redis import init_redis_client
|
|
2
4
|
from mage_ai.settings import REDIS_URL
|
|
3
5
|
|
|
6
|
+
try:
|
|
7
|
+
REDIS_LOCK_DEFAULT_TIMEOUT = int(os.getenv('REDIS_LOCK_DEFAULT_TIMEOUT', 30) or 30)
|
|
8
|
+
except Exception:
|
|
9
|
+
REDIS_LOCK_DEFAULT_TIMEOUT = 30
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
class DistributedLock:
|
|
6
13
|
def __init__(
|
|
7
14
|
self,
|
|
8
15
|
lock_key_prefix='LOCK_KEY',
|
|
9
|
-
lock_timeout=
|
|
16
|
+
lock_timeout=REDIS_LOCK_DEFAULT_TIMEOUT,
|
|
10
17
|
):
|
|
11
18
|
self.lock_key_prefix = lock_key_prefix
|
|
12
19
|
self.lock_timeout = lock_timeout
|
|
@@ -4,6 +4,9 @@ from typing import Tuple
|
|
|
4
4
|
|
|
5
5
|
import psutil
|
|
6
6
|
|
|
7
|
+
# Threshold value for cgroup memory limit indicating no limit is set
|
|
8
|
+
NO_LIMIT_THRESHOLD = 9e18
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
def get_compute() -> Tuple[float, float, float, float]:
|
|
9
12
|
# Getting loadover15 minutes
|
|
@@ -14,14 +17,65 @@ def get_compute() -> Tuple[float, float, float, float]:
|
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
def get_memory() -> Tuple[float, float, float]:
|
|
20
|
+
"""
|
|
21
|
+
Get memory usage information.
|
|
22
|
+
|
|
23
|
+
For containerized environments (e.g., Google Cloud Run), this reads from cgroup files
|
|
24
|
+
which provide accurate container-specific memory limits and usage.
|
|
25
|
+
|
|
26
|
+
For non-containerized environments, falls back to the 'free' command.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Tuple[float, float, float]: (free_memory, used_memory, total_memory) in MB
|
|
30
|
+
"""
|
|
17
31
|
free_memory = None
|
|
18
32
|
total_memory = None
|
|
19
33
|
used_memory = None
|
|
20
34
|
|
|
35
|
+
# Skip checking the memory in Windows
|
|
36
|
+
if os.name == 'nt':
|
|
37
|
+
return free_memory, used_memory, total_memory
|
|
38
|
+
|
|
39
|
+
# Try to read from cgroup files first (for containerized environments)
|
|
21
40
|
try:
|
|
22
|
-
#
|
|
23
|
-
|
|
41
|
+
# Define MB conversion factor (1024 * 1024)
|
|
42
|
+
mb_factor = 1024 * 1024
|
|
43
|
+
|
|
44
|
+
# Try cgroup v1 paths first
|
|
45
|
+
usage_path = "/sys/fs/cgroup/memory/memory.usage_in_bytes"
|
|
46
|
+
limit_path = "/sys/fs/cgroup/memory/memory.limit_in_bytes"
|
|
47
|
+
|
|
48
|
+
# Check if cgroup v2 is being used (single unified hierarchy)
|
|
49
|
+
if not os.path.exists(usage_path):
|
|
50
|
+
usage_path = "/sys/fs/cgroup/memory.current"
|
|
51
|
+
limit_path = "/sys/fs/cgroup/memory.max"
|
|
52
|
+
|
|
53
|
+
# Read memory usage
|
|
54
|
+
if os.path.exists(usage_path):
|
|
55
|
+
with open(usage_path, "r") as f:
|
|
56
|
+
usage_bytes = int(f.read().strip())
|
|
57
|
+
used_memory = usage_bytes / mb_factor
|
|
58
|
+
|
|
59
|
+
# Read memory limit
|
|
60
|
+
if os.path.exists(limit_path):
|
|
61
|
+
with open(limit_path, "r") as f:
|
|
62
|
+
limit_value = f.read().strip()
|
|
63
|
+
# Handle cgroup v2 "max" value or v1 very large limit (no limit set)
|
|
64
|
+
if limit_value != "max":
|
|
65
|
+
limit_bytes = int(limit_value)
|
|
66
|
+
# A value of 9223372036854771712 or greater indicates no limit set
|
|
67
|
+
if limit_bytes < NO_LIMIT_THRESHOLD:
|
|
68
|
+
total_memory = limit_bytes / mb_factor
|
|
69
|
+
# If we successfully read both values, calculate free memory
|
|
70
|
+
if used_memory is not None and total_memory is not None:
|
|
71
|
+
free_memory = total_memory - used_memory
|
|
24
72
|
return free_memory, used_memory, total_memory
|
|
73
|
+
except (FileNotFoundError, ValueError, PermissionError):
|
|
74
|
+
# Cgroup files not available or unreadable, will fall back to 'free' command
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
# Fallback to 'free' command for non-containerized environments
|
|
78
|
+
try:
|
|
25
79
|
output = subprocess.check_output('free -t -m', shell=True).decode('utf-8')
|
|
26
80
|
values = output.splitlines()[-1].split()[1:]
|
|
27
81
|
total_memory, used_memory, free_memory = map(float, values)
|