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.

Files changed (405) hide show
  1. mage_ai/api/operations/base.py +27 -5
  2. mage_ai/api/policies/GlobalHookPolicy.py +1 -1
  3. mage_ai/api/policies/IntegrationSourcePolicy.py +62 -0
  4. mage_ai/api/policies/OauthPolicy.py +6 -6
  5. mage_ai/api/presenters/GlobalHookPresenter.py +1 -1
  6. mage_ai/api/presenters/IntegrationSourcePresenter.py +9 -2
  7. mage_ai/api/presenters/PipelinePresenter.py +3 -0
  8. mage_ai/api/presenters/PipelineRunPresenter.py +8 -3
  9. mage_ai/api/presenters/PipelineSchedulePresenter.py +22 -1
  10. mage_ai/api/resources/BlockResource.py +5 -0
  11. mage_ai/api/resources/DataProviderResource.py +2 -0
  12. mage_ai/api/resources/IntegrationSourceResource.py +149 -2
  13. mage_ai/data_integrations/sources/constants.py +5 -0
  14. mage_ai/data_integrations/utils/scheduler.py +57 -2
  15. mage_ai/data_preparation/executors/block_executor.py +30 -2
  16. mage_ai/data_preparation/executors/pipeline_executor.py +19 -4
  17. mage_ai/data_preparation/models/block/__init__.py +75 -32
  18. mage_ai/data_preparation/models/block/data_integration/constants.py +3 -0
  19. mage_ai/data_preparation/models/block/data_integration/mixins.py +6 -6
  20. mage_ai/data_preparation/models/block/data_integration/utils.py +198 -39
  21. mage_ai/data_preparation/models/block/sql/bigquery.py +2 -2
  22. mage_ai/data_preparation/models/block/sql/snowflake.py +2 -2
  23. mage_ai/data_preparation/models/block/sql/trino.py +2 -2
  24. mage_ai/data_preparation/models/block/sql/utils/shared.py +20 -3
  25. mage_ai/data_preparation/models/block/utils.py +53 -29
  26. mage_ai/data_preparation/models/global_hooks/constants.py +50 -1
  27. mage_ai/data_preparation/models/global_hooks/models.py +148 -84
  28. mage_ai/data_preparation/models/global_hooks/predicates.py +316 -0
  29. mage_ai/data_preparation/models/pipeline.py +7 -0
  30. mage_ai/data_preparation/models/pipelines/integration_pipeline.py +0 -1
  31. mage_ai/data_preparation/models/project/__init__.py +0 -2
  32. mage_ai/data_preparation/preferences.py +29 -18
  33. mage_ai/data_preparation/repo_manager.py +12 -2
  34. mage_ai/data_preparation/sync/__init__.py +2 -0
  35. mage_ai/data_preparation/templates/constants.py +14 -0
  36. mage_ai/data_preparation/templates/data_exporters/chroma.py +24 -0
  37. mage_ai/data_preparation/templates/data_exporters/streaming/rabbitmq.yaml +7 -0
  38. mage_ai/data_preparation/templates/data_loaders/chroma.py +27 -0
  39. mage_ai/data_preparation/templates/repo/io_config.yaml +3 -0
  40. mage_ai/io/base.py +1 -0
  41. mage_ai/io/chroma.py +162 -0
  42. mage_ai/io/config.py +8 -0
  43. mage_ai/orchestration/db/models/schedules.py +169 -34
  44. mage_ai/orchestration/pipeline_scheduler.py +59 -89
  45. mage_ai/server/constants.py +1 -1
  46. mage_ai/server/frontend_dist/404.html +2 -2
  47. mage_ai/server/frontend_dist/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
  48. mage_ai/server/frontend_dist/_next/static/chunks/1952-0f9a12782f0aaae6.js +1 -0
  49. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
  50. mage_ai/server/frontend_dist/_next/static/chunks/2717-14191a781cf2f286.js +1 -0
  51. mage_ai/server/frontend_dist/_next/static/chunks/3419-a7a52bcaaa687b07.js +1 -0
  52. mage_ai/server/frontend_dist/_next/static/chunks/3437-e81a62f33337ca06.js +1 -0
  53. mage_ai/server/frontend_dist/_next/static/chunks/3943-3cb1f765210dd7a4.js +1 -0
  54. mage_ai/server/frontend_dist/_next/static/chunks/4138-2c16e6d2f22246cd.js +1 -0
  55. mage_ai/server/frontend_dist/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
  56. mage_ai/server/frontend_dist/_next/static/chunks/{4366-93e09e5a4a7e182c.js → 4366-3e52497942acbafe.js} +1 -1
  57. mage_ai/server/frontend_dist/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
  58. mage_ai/server/frontend_dist/_next/static/chunks/{5499-76cf8f023c6b0985.js → 5499-c2853ef57d39fde8.js} +1 -1
  59. mage_ai/server/frontend_dist/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
  60. mage_ai/server/frontend_dist/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
  61. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/6285-e9b45335bfb9ccaf.js → frontend_dist/_next/static/chunks/6285-648f9a732e100b2f.js} +1 -1
  62. mage_ai/server/frontend_dist/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
  63. mage_ai/server/frontend_dist/_next/static/chunks/6990-303bb87fc50f1755.js +1 -0
  64. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
  65. mage_ai/server/frontend_dist/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
  66. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7858-d9df72e95e438284.js → frontend_dist/_next/static/chunks/7858-26a5a5d04fa3c703.js} +1 -1
  67. mage_ai/server/frontend_dist/_next/static/chunks/{8146-92e7ccfed169ee9c.js → 8146-27f0e31f309897a5.js} +1 -1
  68. mage_ai/server/frontend_dist/_next/static/chunks/8264-9d6a7cea289e29ff.js +1 -0
  69. mage_ai/server/frontend_dist/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
  70. mage_ai/server/frontend_dist/_next/static/chunks/8487-608d62c0eef1f29a.js +1 -0
  71. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/1845-5ce774d5ab81ed57.js → frontend_dist/_next/static/chunks/8731-2f78ec7b7760be8f.js} +1 -1
  72. mage_ai/server/frontend_dist/_next/static/chunks/90-93d18aaecef0685b.js +1 -0
  73. mage_ai/server/frontend_dist/_next/static/chunks/9264-727704fc34e74ae0.js +1 -0
  74. mage_ai/server/frontend_dist/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
  75. mage_ai/server/frontend_dist/_next/static/chunks/9624-48fba6b4e6966fb7.js +1 -0
  76. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/976-18c98af60b76f1a7.js → frontend_dist/_next/static/chunks/976-0a8c2c4d7acd957b.js} +1 -1
  77. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-8254de4f793643d0.js +1 -0
  78. 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
  79. mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-a9402b51e9fe748e.js +1 -0
  80. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-85cecae037fd7a70.js +1 -0
  81. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-cfd68e760ae00958.js → [...slug]-c3c9523ea8072c11.js} +1 -1
  82. mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-c3b79ef31007f95b.js → global-data-products-4d046f15202a1c8d.js} +1 -1
  83. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-286133386c97a2b6.js +1 -0
  84. mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-hooks-e561ae38cf5592e8.js → global-hooks-3da370825153056c.js} +1 -1
  85. 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
  86. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{settings-60845f0b59142f32.js → settings-666748ff5d101411.js} +1 -1
  87. 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
  88. 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
  89. 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
  90. 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
  91. mage_ai/server/frontend_dist/_next/static/chunks/pages/{oauth-8bb62c4f6a511c43.js → oauth-e9b8f19c30381c28.js} +1 -1
  92. 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
  93. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-70fc3351bd11025f.js +1 -0
  94. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-6ee3b88a5bb4ce94.js +1 -0
  95. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c9cf383bc13ce7b8.js +1 -0
  96. 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
  97. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-c119f630038b0685.js +1 -0
  98. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-146051325c92d742.js +1 -0
  99. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-ddddcddd2f74b4f6.js → block-runs-15d307e6ba934a56.js} +1 -1
  100. 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
  101. 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
  102. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-06e55db757959ef8.js +1 -0
  103. 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
  104. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-495e877aa7ed709e.js +1 -0
  105. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-49adfeed5157d92b.js +1 -0
  106. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-6143e028225390f5.js +1 -0
  107. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-0886f6320fef7131.js +1 -0
  108. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e82a763d742cc034.js +1 -0
  109. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-50d20fa715d454af.js +1 -0
  110. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-b78b1be5b9ed84b9.js → [...slug]-2bbd63b7e93a8600.js} +1 -1
  111. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-37b78a436eeab258.js → permissions-4ea156c39608caab.js} +1 -1
  112. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-f3c29ec53ee35795.js +1 -0
  113. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-db05a80d18c168e5.js → [...slug]-64ec8928d2542f3c.js} +1 -1
  114. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{roles-f55c77e4f46c8d33.js → roles-835e6ec2a48ec583.js} +1 -1
  115. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{sync-data-2a1f8737561fdd94.js → sync-data-0769149af025de30.js} +1 -1
  116. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-e3bf6e5d8bb250c4.js → [...slug]-612a65c42bcadef0.js} +1 -1
  117. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-20f0a050a42a015d.js → users-e3365b4029a8db33.js} +1 -1
  118. 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
  119. 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
  120. mage_ai/server/frontend_dist/_next/static/chunks/pages/{templates-1bfaa1c50e844813.js → templates-406e13cc5c4caab4.js} +1 -1
  121. mage_ai/server/frontend_dist/_next/static/chunks/pages/{terminal-ed121e305169cf1c.js → terminal-ef8ad878e5e7bb2f.js} +1 -1
  122. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-a90728798f964700.js +1 -0
  123. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-0e0c2713a2922be7.js +1 -0
  124. mage_ai/server/frontend_dist/_next/static/xxcdnITr3IkTdETH5ghqw/_buildManifest.js +1 -0
  125. mage_ai/server/frontend_dist/block-layout.html +2 -2
  126. mage_ai/server/frontend_dist/compute.html +5 -5
  127. mage_ai/server/frontend_dist/files.html +5 -5
  128. mage_ai/server/frontend_dist/global-data-products/[...slug].html +5 -5
  129. mage_ai/server/frontend_dist/global-data-products.html +5 -5
  130. mage_ai/server/frontend_dist/global-hooks/[...slug].html +5 -5
  131. mage_ai/server/frontend_dist/global-hooks.html +5 -5
  132. mage_ai/server/frontend_dist/index.html +2 -2
  133. mage_ai/server/frontend_dist/manage/files.html +5 -5
  134. mage_ai/server/frontend_dist/manage/settings.html +5 -5
  135. mage_ai/server/frontend_dist/manage/users/[user].html +5 -5
  136. mage_ai/server/frontend_dist/manage/users/new.html +5 -5
  137. mage_ai/server/frontend_dist/manage/users.html +5 -5
  138. mage_ai/server/frontend_dist/manage.html +5 -5
  139. mage_ai/server/frontend_dist/oauth.html +4 -4
  140. mage_ai/server/frontend_dist/overview.html +5 -5
  141. mage_ai/server/frontend_dist/pipeline-runs.html +5 -5
  142. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +5 -5
  143. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +5 -5
  144. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +5 -5
  145. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  146. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +5 -5
  147. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +5 -5
  148. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
  149. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +5 -5
  150. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +5 -5
  151. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +5 -5
  152. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +5 -5
  153. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +5 -5
  154. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +5 -5
  155. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +5 -5
  156. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  157. mage_ai/server/frontend_dist/pipelines.html +5 -5
  158. mage_ai/server/frontend_dist/settings/account/profile.html +5 -5
  159. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +5 -5
  160. mage_ai/server/frontend_dist/settings/workspace/permissions.html +5 -5
  161. mage_ai/server/frontend_dist/settings/workspace/preferences.html +5 -5
  162. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +5 -5
  163. mage_ai/server/frontend_dist/settings/workspace/roles.html +5 -5
  164. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +5 -5
  165. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +5 -5
  166. mage_ai/server/frontend_dist/settings/workspace/users.html +5 -5
  167. mage_ai/server/frontend_dist/settings.html +2 -2
  168. mage_ai/server/frontend_dist/sign-in.html +24 -24
  169. mage_ai/server/frontend_dist/templates/[...slug].html +5 -5
  170. mage_ai/server/frontend_dist/templates.html +5 -5
  171. mage_ai/server/frontend_dist/terminal.html +5 -5
  172. mage_ai/server/frontend_dist/test.html +5 -5
  173. mage_ai/server/frontend_dist/triggers.html +5 -5
  174. mage_ai/server/frontend_dist/version-control.html +5 -5
  175. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  176. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
  177. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-0f9a12782f0aaae6.js +1 -0
  178. mage_ai/server/{frontend_dist/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist_base_path_template/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
  179. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-14191a781cf2f286.js +1 -0
  180. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-a7a52bcaaa687b07.js +1 -0
  181. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3437-e81a62f33337ca06.js +1 -0
  182. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-3cb1f765210dd7a4.js +1 -0
  183. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4138-2c16e6d2f22246cd.js +1 -0
  184. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
  185. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4366-93e09e5a4a7e182c.js → 4366-3e52497942acbafe.js} +1 -1
  186. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
  187. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5499-76cf8f023c6b0985.js → 5499-c2853ef57d39fde8.js} +1 -1
  188. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
  189. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
  190. mage_ai/server/{frontend_dist/_next/static/chunks/6285-e9b45335bfb9ccaf.js → frontend_dist_base_path_template/_next/static/chunks/6285-648f9a732e100b2f.js} +1 -1
  191. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
  192. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6990-303bb87fc50f1755.js +1 -0
  193. mage_ai/server/{frontend_dist/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist_base_path_template/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
  194. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
  195. mage_ai/server/{frontend_dist/_next/static/chunks/7858-d9df72e95e438284.js → frontend_dist_base_path_template/_next/static/chunks/7858-26a5a5d04fa3c703.js} +1 -1
  196. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{8146-92e7ccfed169ee9c.js → 8146-27f0e31f309897a5.js} +1 -1
  197. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-9d6a7cea289e29ff.js +1 -0
  198. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
  199. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-608d62c0eef1f29a.js +1 -0
  200. mage_ai/server/{frontend_dist/_next/static/chunks/1845-5ce774d5ab81ed57.js → frontend_dist_base_path_template/_next/static/chunks/8731-2f78ec7b7760be8f.js} +1 -1
  201. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/90-93d18aaecef0685b.js +1 -0
  202. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-727704fc34e74ae0.js +1 -0
  203. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
  204. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-48fba6b4e6966fb7.js +1 -0
  205. mage_ai/server/{frontend_dist/_next/static/chunks/976-18c98af60b76f1a7.js → frontend_dist_base_path_template/_next/static/chunks/976-0a8c2c4d7acd957b.js} +1 -1
  206. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-8254de4f793643d0.js +1 -0
  207. 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
  208. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-a9402b51e9fe748e.js +1 -0
  209. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-85cecae037fd7a70.js +1 -0
  210. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-cfd68e760ae00958.js → [...slug]-c3c9523ea8072c11.js} +1 -1
  211. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-c3b79ef31007f95b.js → global-data-products-4d046f15202a1c8d.js} +1 -1
  212. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-286133386c97a2b6.js +1 -0
  213. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-hooks-e561ae38cf5592e8.js → global-hooks-3da370825153056c.js} +1 -1
  214. 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
  215. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{settings-60845f0b59142f32.js → settings-666748ff5d101411.js} +1 -1
  216. 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
  217. 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
  218. 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
  219. 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
  220. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{oauth-8bb62c4f6a511c43.js → oauth-e9b8f19c30381c28.js} +1 -1
  221. 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
  222. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-70fc3351bd11025f.js +1 -0
  223. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-6ee3b88a5bb4ce94.js +1 -0
  224. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c9cf383bc13ce7b8.js +1 -0
  225. 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
  226. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-c119f630038b0685.js +1 -0
  227. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-146051325c92d742.js +1 -0
  228. 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
  229. 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
  230. 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
  231. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-06e55db757959ef8.js +1 -0
  232. 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
  233. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-495e877aa7ed709e.js +1 -0
  234. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-49adfeed5157d92b.js +1 -0
  235. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-6143e028225390f5.js +1 -0
  236. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-0886f6320fef7131.js +1 -0
  237. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e82a763d742cc034.js +1 -0
  238. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-50d20fa715d454af.js +1 -0
  239. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-b78b1be5b9ed84b9.js → [...slug]-2bbd63b7e93a8600.js} +1 -1
  240. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-37b78a436eeab258.js → permissions-4ea156c39608caab.js} +1 -1
  241. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-f3c29ec53ee35795.js +1 -0
  242. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-db05a80d18c168e5.js → [...slug]-64ec8928d2542f3c.js} +1 -1
  243. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{roles-f55c77e4f46c8d33.js → roles-835e6ec2a48ec583.js} +1 -1
  244. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{sync-data-2a1f8737561fdd94.js → sync-data-0769149af025de30.js} +1 -1
  245. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-e3bf6e5d8bb250c4.js → [...slug]-612a65c42bcadef0.js} +1 -1
  246. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-20f0a050a42a015d.js → users-e3365b4029a8db33.js} +1 -1
  247. 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
  248. 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
  249. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{templates-1bfaa1c50e844813.js → templates-406e13cc5c4caab4.js} +1 -1
  250. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{terminal-ed121e305169cf1c.js → terminal-ef8ad878e5e7bb2f.js} +1 -1
  251. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-a90728798f964700.js +1 -0
  252. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-0e0c2713a2922be7.js +1 -0
  253. mage_ai/server/frontend_dist_base_path_template/_next/static/gDn6inKdLyj35NvURBSCV/_buildManifest.js +1 -0
  254. mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
  255. mage_ai/server/frontend_dist_base_path_template/compute.html +5 -5
  256. mage_ai/server/frontend_dist_base_path_template/files.html +5 -5
  257. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +5 -5
  258. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +5 -5
  259. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +5 -5
  260. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +5 -5
  261. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  262. mage_ai/server/frontend_dist_base_path_template/manage/files.html +5 -5
  263. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +5 -5
  264. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +5 -5
  265. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +5 -5
  266. mage_ai/server/frontend_dist_base_path_template/manage/users.html +5 -5
  267. mage_ai/server/frontend_dist_base_path_template/manage.html +5 -5
  268. mage_ai/server/frontend_dist_base_path_template/oauth.html +4 -4
  269. mage_ai/server/frontend_dist_base_path_template/overview.html +5 -5
  270. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +5 -5
  271. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +5 -5
  272. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +5 -5
  273. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +5 -5
  274. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  275. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +5 -5
  276. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +5 -5
  277. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
  278. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +5 -5
  279. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +5 -5
  280. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +5 -5
  281. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +5 -5
  282. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +5 -5
  283. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +5 -5
  284. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +5 -5
  285. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  286. mage_ai/server/frontend_dist_base_path_template/pipelines.html +5 -5
  287. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +5 -5
  288. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +5 -5
  289. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +5 -5
  290. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +5 -5
  291. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +5 -5
  292. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +5 -5
  293. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +5 -5
  294. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +5 -5
  295. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +5 -5
  296. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  297. mage_ai/server/frontend_dist_base_path_template/sign-in.html +20 -20
  298. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +5 -5
  299. mage_ai/server/frontend_dist_base_path_template/templates.html +5 -5
  300. mage_ai/server/frontend_dist_base_path_template/terminal.html +5 -5
  301. mage_ai/server/frontend_dist_base_path_template/test.html +5 -5
  302. mage_ai/server/frontend_dist_base_path_template/triggers.html +5 -5
  303. mage_ai/server/frontend_dist_base_path_template/version-control.html +5 -5
  304. mage_ai/server/server.py +11 -3
  305. mage_ai/services/k8s/job_manager.py +1 -0
  306. mage_ai/settings/repo.py +3 -0
  307. mage_ai/shared/files.py +47 -0
  308. mage_ai/shared/models.py +1 -0
  309. mage_ai/streaming/constants.py +1 -0
  310. mage_ai/streaming/sinks/postgres.py +2 -0
  311. mage_ai/streaming/sinks/rabbitmq.py +76 -0
  312. mage_ai/streaming/sinks/sink_factory.py +4 -0
  313. mage_ai/streaming/sources/nats_js.py +12 -1
  314. mage_ai/tests/api/operations/test_operations_with_hooks.py +136 -91
  315. mage_ai/tests/api/policies/test_oauth_policy.py +38 -0
  316. mage_ai/tests/data_preparation/executors/test_block_executor.py +2 -0
  317. mage_ai/tests/data_preparation/models/global_hooks/test_global_hooks.py +33 -8
  318. mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +82 -38
  319. mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +803 -0
  320. mage_ai/tests/data_preparation/models/global_hooks/test_utils.py +6 -1
  321. mage_ai/tests/data_preparation/models/test_block.py +26 -0
  322. mage_ai/tests/data_preparation/models/test_pipeline.py +15 -0
  323. mage_ai/tests/factory.py +40 -2
  324. mage_ai/tests/orchestration/test_pipeline_scheduler.py +82 -1
  325. mage_ai/tests/services/k8s/test_job_manager.py +16 -0
  326. mage_ai/tests/shared/mixins.py +60 -23
  327. mage_ai/tests/streaming/sinks/test_rabbitmq.py +36 -0
  328. {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/METADATA +7 -4
  329. {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/RECORD +335 -321
  330. {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/WHEEL +1 -1
  331. mage_ai/server/frontend_dist/_next/static/9jB4XPuz6BzxBcG9VNao5/_buildManifest.js +0 -1
  332. mage_ai/server/frontend_dist/_next/static/chunks/1952-ac7722e8b1ab88fe.js +0 -1
  333. mage_ai/server/frontend_dist/_next/static/chunks/3419-f8d518d024e7b5c8.js +0 -1
  334. mage_ai/server/frontend_dist/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
  335. mage_ai/server/frontend_dist/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
  336. mage_ai/server/frontend_dist/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
  337. mage_ai/server/frontend_dist/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
  338. mage_ai/server/frontend_dist/_next/static/chunks/600-705fe234320ec5de.js +0 -1
  339. mage_ai/server/frontend_dist/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
  340. mage_ai/server/frontend_dist/_next/static/chunks/722-a1584445357a276c.js +0 -1
  341. mage_ai/server/frontend_dist/_next/static/chunks/8264-0d582a6ca33c3dfa.js +0 -1
  342. mage_ai/server/frontend_dist/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
  343. mage_ai/server/frontend_dist/_next/static/chunks/90-a7308bae028d7001.js +0 -1
  344. mage_ai/server/frontend_dist/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
  345. mage_ai/server/frontend_dist/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
  346. mage_ai/server/frontend_dist/_next/static/chunks/9624-334e7db5c84cb4ea.js +0 -1
  347. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
  348. mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-419775ca1293b354.js +0 -1
  349. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
  350. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
  351. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js +0 -1
  352. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
  353. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
  354. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
  355. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-ef680455ae54ccbe.js +0 -1
  356. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
  357. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
  358. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +0 -1
  359. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
  360. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
  361. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
  362. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
  363. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
  364. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
  365. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
  366. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-ac7722e8b1ab88fe.js +0 -1
  367. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-f8d518d024e7b5c8.js +0 -1
  368. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
  369. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
  370. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
  371. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
  372. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/600-705fe234320ec5de.js +0 -1
  373. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
  374. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/722-a1584445357a276c.js +0 -1
  375. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-0d582a6ca33c3dfa.js +0 -1
  376. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
  377. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/90-a7308bae028d7001.js +0 -1
  378. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
  379. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
  380. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-334e7db5c84cb4ea.js +0 -1
  381. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
  382. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-419775ca1293b354.js +0 -1
  383. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
  384. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
  385. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js +0 -1
  386. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
  387. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
  388. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
  389. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-ef680455ae54ccbe.js +0 -1
  390. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
  391. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
  392. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +0 -1
  393. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
  394. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
  395. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
  396. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
  397. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
  398. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
  399. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
  400. mage_ai/server/frontend_dist_base_path_template/_next/static/uPDjJYpJMst1q6psbRyte/_buildManifest.js +0 -1
  401. /mage_ai/server/frontend_dist/_next/static/{9jB4XPuz6BzxBcG9VNao5 → xxcdnITr3IkTdETH5ghqw}/_ssgManifest.js +0 -0
  402. /mage_ai/server/frontend_dist_base_path_template/_next/static/{uPDjJYpJMst1q6psbRyte → gDn6inKdLyj35NvURBSCV}/_ssgManifest.js +0 -0
  403. {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/LICENSE +0 -0
  404. {mage_ai-0.9.46.dist-info → mage_ai-0.9.48.dist-info}/entry_points.txt +0 -0
  405. {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 runtime_history(
506
+ def recently_completed_pipeline_runs(
495
507
  self,
496
508
  pipeline_run=None,
497
509
  sample_size: int = None,
498
- ) -> List[float]:
499
- sample_size_to_use = sample_size if sample_size else 7
500
- previous_runtimes = []
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
- PipelineRun.
508
- query.
522
+ pipeline_runs.
509
523
  filter(
510
- PipelineRun.pipeline_schedule_id == self.id,
511
- PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
524
+ PipelineRun.id != pipeline_run.id,
512
525
  )
513
526
  )
514
527
 
515
- if pipeline_run:
516
- pipeline_runs = (
517
- pipeline_runs.
518
- filter(
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
- pipeline_runs = (
524
- pipeline_runs.
525
- order_by(PipelineRun.execution_date.desc()).
526
- limit(sample_size_to_use).
527
- all()
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
- pipeline_runs = sorted(
531
- pipeline_runs,
532
- key=lambda pr: pr.execution_date,
533
- reverse=True,
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
- ) -> Dict[str, List['PipelineRun']]:
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 key, runs in groupby(active_runs, key=lambda x: x.pipeline_uuid):
879
- grouped[key] = list(runs)
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
- self.streams = self.pipeline.streams(
79
- self.pipeline_run.get_variables(
80
- extra_variables=get_extra_variables(self.pipeline)
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
- backfills = schedule.backfills
230
- # When all pipeline runs that are associated with backfill is done
231
- if len(backfills) >= 1:
232
- backfill = backfills[0]
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 backfill.pipeline_runs]):
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.__update_block_run_statuses(self.pipeline_run.initial_block_runs)
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
- key: list(runs)
1422
- for key, runs in groupby(active_pipeline_schedules, key=lambda x: x.pipeline_uuid)
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
- PipelineScheduler(r).start()
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.
@@ -12,4 +12,4 @@ DATAFRAME_OUTPUT_SAMPLE_COUNT = 10
12
12
  # Dockerfile depends on it because it runs ./scripts/install_mage.sh and uses
13
13
  # the last line to determine the version to install.
14
14
  VERSION = \
15
- '0.9.46'
15
+ '0.9.48'