Flowfile 0.5.4__py3-none-any.whl → 0.6.1__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.
Files changed (259) hide show
  1. flowfile/__main__.py +94 -1
  2. flowfile/api.py +8 -6
  3. flowfile/web/static/assets/{AdminView-f9847d67.js → AdminView-C4K1DdHI.js} +28 -33
  4. flowfile/web/static/assets/{CloudConnectionView-faace55b.js → CloudConnectionView-BZbPvPUL.js} +39 -50
  5. flowfile/web/static/assets/{CloudStorageReader-24c54524.css → CloudStorageReader-BDByiqPI.css} +25 -25
  6. flowfile/web/static/assets/{CloudStorageReader-d86ecaa7.js → CloudStorageReader-DLVukNJ7.js} +30 -35
  7. flowfile/web/static/assets/{CloudStorageWriter-0f4d9a44.js → CloudStorageWriter-Bfi-C1QW.js} +32 -37
  8. flowfile/web/static/assets/{CloudStorageWriter-60547855.css → CloudStorageWriter-y8jL8yjG.css} +24 -24
  9. flowfile/web/static/assets/{ColumnActionInput-f4189ae0.js → ColumnActionInput-BpiCApw9.js} +7 -12
  10. flowfile/web/static/assets/{ColumnSelector-e66b33da.js → ColumnSelector-CEAwedI7.js} +1 -2
  11. flowfile/web/static/assets/ContextMenu-CdojQu0w.js +9 -0
  12. flowfile/web/static/assets/ContextMenu-D12mhsy1.js +9 -0
  13. flowfile/web/static/assets/ContextMenu-EWUR98va.js +9 -0
  14. flowfile/web/static/assets/{ContextMenu.vue_vue_type_script_setup_true_lang-a1bd6314.js → ContextMenu.vue_vue_type_script_setup_true_lang-I4rXXd6G.js} +4 -5
  15. flowfile/web/static/assets/{CrossJoin-24694b8f.js → CrossJoin-BOFfxkJO.js} +19 -18
  16. flowfile/web/static/assets/{CrossJoin-71b4cc10.css → CrossJoin-Cmbyt9im.css} +18 -18
  17. flowfile/web/static/assets/{CustomNode-569d45ff.js → CustomNode-Bhpezobq.js} +12 -17
  18. flowfile/web/static/assets/{DatabaseConnectionSettings-cfc08938.js → DatabaseConnectionSettings-Dw3bSJKB.js} +10 -11
  19. flowfile/web/static/assets/{DatabaseReader-5bf8c75b.css → DatabaseReader-D6pUNUCs.css} +21 -21
  20. flowfile/web/static/assets/{DatabaseReader-701feabb.js → DatabaseReader-m87ghlw0.js} +36 -34
  21. flowfile/web/static/assets/{DatabaseView-0482e5b5.js → DatabaseView-CisSAtpe.js} +30 -38
  22. flowfile/web/static/assets/{DatabaseWriter-16721989.js → DatabaseWriter-Bbj9JLdL.js} +33 -35
  23. flowfile/web/static/assets/{DatabaseWriter-bdcf2c8b.css → DatabaseWriter-RBqdFLj8.css} +17 -17
  24. flowfile/web/static/assets/{DesignerView-f64749fb.js → DesignerView-DemDevTQ.js} +1841 -2090
  25. flowfile/web/static/assets/{DesignerView-49abb835.css → DesignerView-Dm6OzlIc.css} +244 -202
  26. flowfile/web/static/assets/{DocumentationView-61bd2990.js → DocumentationView-BrC1ZR3H.js} +3 -4
  27. flowfile/web/static/assets/{ExploreData-e2735b13.js → ExploreData-BMKcDuRb.js} +8 -10
  28. flowfile/web/static/assets/{ExternalSource-2535c3b2.js → ExternalSource-BXrNNS-f.js} +40 -42
  29. flowfile/web/static/assets/{ExternalSource-7ac7373f.css → ExternalSource-NB6WVl5R.css} +14 -14
  30. flowfile/web/static/assets/{Filter-2cdbc93c.js → Filter-C2MjsN6P.js} +36 -33
  31. flowfile/web/static/assets/{Filter-7494ea97.css → Filter-DCMGGuGC.css} +9 -9
  32. flowfile/web/static/assets/{Formula-53d58c43.css → Formula-BYafbDj8.css} +4 -4
  33. flowfile/web/static/assets/{Formula-fcda3c2c.js → Formula-ufuy4mVD.js} +27 -26
  34. flowfile/web/static/assets/{FuzzyMatch-ad6361d6.css → FuzzyMatch-BGJAwgd0.css} +42 -42
  35. flowfile/web/static/assets/{FuzzyMatch-f8d3b7d3.js → FuzzyMatch-BOHODq3h.js} +36 -38
  36. flowfile/web/static/assets/{GraphSolver-72eaa695.js → GraphSolver-B6ZzpNGO.js} +23 -21
  37. flowfile/web/static/assets/{GraphSolver-4b4d7db9.css → GraphSolver-DFN83sj3.css} +4 -4
  38. flowfile/web/static/assets/{GroupBy-8aa0598b.js → GroupBy-B9BRNcfe.js} +30 -29
  39. flowfile/web/static/assets/{Sort-4abb7fae.css → GroupBy-x4ooP5np.css} +1 -1
  40. flowfile/web/static/assets/Join-Bx_g5bZz.css +118 -0
  41. flowfile/web/static/assets/{Join-e40f0ffa.js → Join-DsBEy1IH.js} +48 -43
  42. flowfile/web/static/assets/{LoginView-5111c9ae.js → LoginView-Ct0rhdcO.js} +1 -2
  43. flowfile/web/static/assets/{ManualInput-3702e677.css → ManualInput-DlZmtMdt.css} +48 -48
  44. flowfile/web/static/assets/{ManualInput-9b6f3224.js → ManualInput-bC4BUgnG.js} +85 -44
  45. flowfile/web/static/assets/{MultiSelect-ef28e19e.js → MultiSelect-DIQ8PuTC.js} +2 -2
  46. flowfile/web/static/assets/{MultiSelect.vue_vue_type_script_setup_true_lang-83b3bbfd.js → MultiSelect.vue_vue_type_script_setup_true_lang-BefHfqTI.js} +1 -1
  47. flowfile/web/static/assets/{NodeDesigner-d2b7ee2b.js → NodeDesigner-D39yzr2k.js} +178 -208
  48. flowfile/web/static/assets/{NodeDesigner-94cd4dd3.css → NodeDesigner-R0l6sYyY.css} +76 -76
  49. flowfile/web/static/assets/{NumericInput-1d789794.js → NumericInput-DMSX3oOr.js} +2 -2
  50. flowfile/web/static/assets/{NumericInput.vue_vue_type_script_setup_true_lang-7775f83e.js → NumericInput.vue_vue_type_script_setup_true_lang-d0YlVHAl.js} +1 -1
  51. flowfile/web/static/assets/{Output-cefef801.js → Output-D0VoXGcW.js} +26 -34
  52. flowfile/web/static/assets/{Output-692dd25d.css → Output-DsmglIDy.css} +5 -5
  53. flowfile/web/static/assets/{Pivot-bab1b75b.js → Pivot-BnMB4sEe.js} +26 -26
  54. flowfile/web/static/assets/{Pivot-0eda81b4.css → Pivot-qKTyWxop.css} +4 -4
  55. flowfile/web/static/assets/{PivotValidation-fba09336.js → PivotValidation-B2lWvugt.js} +7 -9
  56. flowfile/web/static/assets/{PivotValidation-e7941f91.js → PivotValidation-BPlhRjpL.js} +7 -9
  57. flowfile/web/static/assets/{PolarsCode-740e40fa.js → PolarsCode-5h0tHnWR.js} +22 -20
  58. flowfile/web/static/assets/PopOver-BHpt5rsj.js +134 -0
  59. flowfile/web/static/assets/{PopOver-d96599db.css → PopOver-CyYM4-rV.css} +1 -1
  60. flowfile/web/static/assets/{Read-90f366bc.css → Read-DJxkrTb_.css} +10 -10
  61. flowfile/web/static/assets/Read-TsLEFh3B.js +227 -0
  62. flowfile/web/static/assets/{RecordCount-ffc71eca.js → RecordCount-DkVixq9v.js} +18 -17
  63. flowfile/web/static/assets/{RecordId-a70bb8df.js → RecordId-C2UEGlCf.js} +42 -39
  64. flowfile/web/static/assets/{SQLQueryComponent-15a421f5.js → SQLQueryComponent-Dr5KMoD3.js} +2 -3
  65. flowfile/web/static/assets/{Sample-6c26afc7.js → Sample-Cb3eQNmd.js} +30 -30
  66. flowfile/web/static/assets/{SecretSelector-ceed9496.js → SecretSelector-De2L2bSx.js} +3 -4
  67. flowfile/web/static/assets/{SecretsView-214d255a.js → SecretsView-CheC9BPV.js} +13 -16
  68. flowfile/web/static/assets/{Select-8fc29999.js → Select-CI8TloRs.js} +41 -36
  69. flowfile/web/static/assets/{SettingsSection-9f0d1725.js → SettingsSection-B39ulIiI.js} +1 -2
  70. flowfile/web/static/assets/{SettingsSection-83090218.js → SettingsSection-BiCc7S9h.js} +1 -2
  71. flowfile/web/static/assets/{SettingsSection-3f70e4c3.js → SettingsSection-CITK_R7o.js} +2 -3
  72. flowfile/web/static/assets/{SettingsSection-26fe48d4.css → SettingsSection-D2GgY-Aq.css} +4 -4
  73. flowfile/web/static/assets/{SetupView-3fa0aa03.js → SetupView-C1aXRDvp.js} +3 -4
  74. flowfile/web/static/assets/{SetupView-e2da3442.css → SetupView-CI1nd-5Z.css} +38 -38
  75. flowfile/web/static/assets/{SingleSelect-a4a568cb.js → SingleSelect-Kr_hz90m.js} +2 -2
  76. flowfile/web/static/assets/{SingleSelect.vue_vue_type_script_setup_true_lang-c8ebdd33.js → SingleSelect.vue_vue_type_script_setup_true_lang-Rxht5Z5N.js} +1 -1
  77. flowfile/web/static/assets/{SliderInput-be533e71.js → SliderInput-CLqpCxCb.js} +1 -2
  78. flowfile/web/static/assets/{GroupBy-5792782d.css → Sort-BIt2kc_p.css} +1 -1
  79. flowfile/web/static/assets/{Sort-154dad81.js → Sort-Dnw_J6Qi.js} +25 -25
  80. flowfile/web/static/assets/{TextInput-454e2bda.js → TextInput-wdlunIZC.js} +2 -2
  81. flowfile/web/static/assets/{TextInput.vue_vue_type_script_setup_true_lang-e86510d0.js → TextInput.vue_vue_type_script_setup_true_lang-Bcj3ywzv.js} +1 -1
  82. flowfile/web/static/assets/{TextToRows-ea73433d.js → TextToRows-BhtyGWPq.js} +42 -49
  83. flowfile/web/static/assets/{TextToRows-12afb4f4.css → TextToRows-DivDOLDx.css} +9 -9
  84. flowfile/web/static/assets/{ToggleSwitch-9d7b30f1.js → ToggleSwitch-B-6WzfFf.js} +2 -2
  85. flowfile/web/static/assets/{ToggleSwitch.vue_vue_type_script_setup_true_lang-00f2580e.js → ToggleSwitch.vue_vue_type_script_setup_true_lang-Cj8LqT-b.js} +1 -1
  86. flowfile/web/static/assets/{UnavailableFields-b72a2c72.js → UnavailableFields-Yf6XSqFB.js} +2 -3
  87. flowfile/web/static/assets/{Union-1e44f263.js → Union-CwpjeKYC.js} +20 -23
  88. flowfile/web/static/assets/{Unpivot-b6ad6427.css → Union-DQJcpp3-.css} +6 -6
  89. flowfile/web/static/assets/{Unique-a3bc6d0a.js → Unique-25v3urqH.js} +75 -74
  90. flowfile/web/static/assets/{Union-d6a8d7d5.css → Unpivot-Deqh1gtI.css} +6 -6
  91. flowfile/web/static/assets/{Unpivot-e27935fc.js → Unpivot-sYcTTXrq.js} +34 -27
  92. flowfile/web/static/assets/{UnpivotValidation-72497680.js → UnpivotValidation-C5DDEKY2.js} +5 -7
  93. flowfile/web/static/assets/VueGraphicWalker-B8l1_Z92.js +131 -0
  94. flowfile/web/static/assets/VueGraphicWalker-Da_1-3me.css +21 -0
  95. flowfile/web/static/assets/{api-a2102880.js → api-C0LvF-0C.js} +1 -1
  96. flowfile/web/static/assets/{api-f75042b0.js → api-DaC83EO_.js} +1 -1
  97. flowfile/web/static/assets/client-C8Ygr6Gb.js +42 -0
  98. flowfile/web/static/assets/{dropDown-2798a109.js → dropDown-D5YXaPRR.js} +7 -12
  99. flowfile/web/static/assets/{fullEditor-cf7d7d93.js → fullEditor-BVYnWm05.js} +300 -18
  100. flowfile/web/static/assets/genericNodeSettings-2wAu-QKn.css +75 -0
  101. flowfile/web/static/assets/genericNodeSettings-BBtW_Cpz.js +590 -0
  102. flowfile/web/static/assets/{VueGraphicWalker-d9ab70a3.js → graphic-walker.es-VrK6vdGE.js} +92305 -89751
  103. flowfile/web/static/assets/index-BCJxPfM5.js +6693 -0
  104. flowfile/web/static/assets/{index-f0a6e5a5.js → index-CHPMUR0d.js} +150 -170
  105. flowfile/web/static/assets/index-DPkoZWq8.js +32 -0
  106. flowfile/web/static/assets/index-DnW_KC_I.js +277 -0
  107. flowfile/web/static/assets/index-UFXyfirV.css +10797 -0
  108. flowfile/web/static/assets/index-bcuE0Z0p.js +87456 -0
  109. flowfile/web/static/assets/{node.types-2c15bb7e.js → node.types-Dl4gtSW9.js} +2 -2
  110. flowfile/web/static/assets/{outputCsv-3c1757e8.js → outputCsv-BELuBiJZ.js} +2 -3
  111. flowfile/web/static/assets/outputCsv-CdGkv-fN.css +2581 -0
  112. flowfile/web/static/assets/{outputExcel-686e1f48.js → outputExcel-D0TTNM79.js} +1 -2
  113. flowfile/web/static/assets/{outputParquet-df28faa7.js → outputParquet-Cz9EbRHj.js} +1 -2
  114. flowfile/web/static/assets/{readCsv-e37eee21.js → readCsv-7bd3kUMI.js} +1 -2
  115. flowfile/web/static/assets/{readExcel-a13f14bb.js → readExcel-Cq8CCwIv.js} +3 -4
  116. flowfile/web/static/assets/{readParquet-c5244ad5.css → readParquet-CRDmBrsp.css} +4 -4
  117. flowfile/web/static/assets/{readParquet-344cf746.js → readParquet-DjR4mRaj.js} +4 -5
  118. flowfile/web/static/assets/{secrets.api-ae198c5c.js → secrets.api-C9o2KE5V.js} +1 -1
  119. flowfile/web/static/assets/{selectDynamic-6b4b0767.js → selectDynamic-Bl5FVsME.js} +5 -8
  120. flowfile/web/static/assets/useNodeSettings-dMS9zmh_.js +69 -0
  121. flowfile/web/static/assets/{vue-codemirror.esm-31ba0e0b.js → vue-codemirror.esm-CwaYwln0.js} +3469 -3064
  122. flowfile/web/static/assets/{vue-content-loader.es-4469c8ff.js → vue-content-loader.es-CMoRXo7N.js} +3 -3
  123. flowfile/web/static/index.html +2 -3
  124. {flowfile-0.5.4.dist-info → flowfile-0.6.1.dist-info}/METADATA +2 -1
  125. flowfile-0.6.1.dist-info/RECORD +417 -0
  126. {flowfile-0.5.4.dist-info → flowfile-0.6.1.dist-info}/WHEEL +1 -1
  127. flowfile_core/auth/password.py +1 -0
  128. flowfile_core/database/init_db.py +7 -5
  129. flowfile_core/fileExplorer/funcs.py +2 -2
  130. flowfile_core/flowfile/code_generator/code_generator.py +13 -11
  131. flowfile_core/flowfile/filter_expressions.py +327 -0
  132. flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +61 -59
  133. flowfile_core/flowfile/flow_data_engine/flow_file_column/type_registry.py +3 -29
  134. flowfile_core/flowfile/flow_data_engine/flow_file_column/utils.py +45 -14
  135. flowfile_core/flowfile/flow_data_engine/subprocess_operations/models.py +20 -3
  136. flowfile_core/flowfile/flow_data_engine/subprocess_operations/streaming.py +206 -0
  137. flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +158 -24
  138. flowfile_core/flowfile/flow_graph.py +504 -190
  139. flowfile_core/flowfile/flow_node/__init__.py +32 -0
  140. flowfile_core/flowfile/flow_node/executor.py +404 -0
  141. flowfile_core/flowfile/flow_node/flow_node.py +207 -106
  142. flowfile_core/flowfile/flow_node/models.py +40 -0
  143. flowfile_core/flowfile/flow_node/output_field_config_applier.py +217 -0
  144. flowfile_core/flowfile/flow_node/schema_utils.py +78 -0
  145. flowfile_core/flowfile/flow_node/state.py +155 -0
  146. flowfile_core/flowfile/history_manager.py +401 -0
  147. flowfile_core/flowfile/manage/compatibility_enhancements.py +9 -0
  148. flowfile_core/flowfile/manage/io_flowfile.py +3 -1
  149. flowfile_core/flowfile/sources/external_sources/sql_source/models.py +20 -4
  150. flowfile_core/flowfile/util/execution_orderer.py +89 -36
  151. flowfile_core/main.py +2 -4
  152. flowfile_core/routes/auth.py +8 -9
  153. flowfile_core/routes/routes.py +320 -101
  154. flowfile_core/routes/user_defined_components.py +18 -16
  155. flowfile_core/schemas/history_schema.py +220 -0
  156. flowfile_core/schemas/input_schema.py +130 -6
  157. flowfile_core/schemas/schemas.py +9 -0
  158. flowfile_core/schemas/transform_schema.py +27 -5
  159. flowfile_core/schemas/yaml_types.py +23 -5
  160. flowfile_frame/adding_expr.py +18 -126
  161. flowfile_frame/callable_utils.py +261 -0
  162. flowfile_frame/database/connection_manager.py +0 -1
  163. flowfile_frame/expr.py +8 -4
  164. flowfile_frame/flow_frame.py +41 -41
  165. flowfile_frame/lazy.py +3 -12
  166. flowfile_frame/lazy_methods.py +5 -64
  167. flowfile_frame/utils.py +13 -32
  168. flowfile_worker/funcs.py +6 -4
  169. flowfile_worker/main.py +2 -0
  170. flowfile_worker/models.py +31 -11
  171. flowfile_worker/routes.py +60 -35
  172. flowfile_worker/spawner.py +7 -1
  173. flowfile_worker/streaming.py +335 -0
  174. flowfile/web/static/assets/ContextMenu-49463352.js +0 -9
  175. flowfile/web/static/assets/ContextMenu-dd5f3f25.js +0 -9
  176. flowfile/web/static/assets/ContextMenu-f709b884.js +0 -9
  177. flowfile/web/static/assets/Join-28b5e18f.css +0 -109
  178. flowfile/web/static/assets/PopOver-862d7e28.js +0 -939
  179. flowfile/web/static/assets/Read-225cc63f.js +0 -222
  180. flowfile/web/static/assets/VueGraphicWalker-430f0b86.css +0 -6
  181. flowfile/web/static/assets/database_reader-ce1e55f3.svg +0 -24
  182. flowfile/web/static/assets/database_writer-b4ad0753.svg +0 -23
  183. flowfile/web/static/assets/element-icons-9c88a535.woff +0 -0
  184. flowfile/web/static/assets/element-icons-de5eb258.ttf +0 -0
  185. flowfile/web/static/assets/genericNodeSettings-14eac1c3.js +0 -137
  186. flowfile/web/static/assets/genericNodeSettings-3b2507ea.css +0 -46
  187. flowfile/web/static/assets/index-387a6f18.js +0 -60752
  188. flowfile/web/static/assets/index-6b367bb5.js +0 -38
  189. flowfile/web/static/assets/index-e96ab018.css +0 -10466
  190. flowfile/web/static/assets/nodeInput-ed2ae8d7.js +0 -2
  191. flowfile/web/static/assets/outputCsv-b9a072af.css +0 -2499
  192. flowfile-0.5.4.dist-info/RECORD +0 -407
  193. /flowfile/web/static/assets/{AdminView-f53bad23.css → AdminView-B2Dthl3u.css} +0 -0
  194. /flowfile/web/static/assets/{CloudConnectionView-cf85f943.css → CloudConnectionView-BdFYGWV7.css} +0 -0
  195. /flowfile/web/static/assets/{ColumnActionInput-c44b7aee.css → ColumnActionInput-dCasSIC9.css} +0 -0
  196. /flowfile/web/static/assets/{ColumnSelector-371637fb.css → ColumnSelector-j6sEOjo1.css} +0 -0
  197. /flowfile/web/static/assets/{CustomNode-edb9b939.css → CustomNode-VPlajG0j.css} +0 -0
  198. /flowfile/web/static/assets/{DatabaseConnectionSettings-c20a1e16.css → DatabaseConnectionSettings-B78hXYgu.css} +0 -0
  199. /flowfile/web/static/assets/{DatabaseView-6655afd6.css → DatabaseView-B-_adk1s.css} +0 -0
  200. /flowfile/web/static/assets/{DocumentationView-9ea6e871.css → DocumentationView-CL7iipFL.css} +0 -0
  201. /flowfile/web/static/assets/{ExploreData-10c5acc8.css → ExploreData-DHjv0Plr.css} +0 -0
  202. /flowfile/web/static/assets/{LoginView-d325d632.css → LoginView-DN1BXY3e.css} +0 -0
  203. /flowfile/web/static/assets/{PivotValidation-0e905b1a.css → PivotValidation-DK-FARWe.css} +0 -0
  204. /flowfile/web/static/assets/{PivotValidation-41b57ad6.css → PivotValidation-FUa9F47u.css} +0 -0
  205. /flowfile/web/static/assets/{PolarsCode-2b1f1f23.css → PolarsCode-G-gRSrSc.css} +0 -0
  206. /flowfile/web/static/assets/{SQLQueryComponent-edb90b98.css → SQLQueryComponent-oAbWw0r-.css} +0 -0
  207. /flowfile/web/static/assets/{SecretSelector-6329f743.css → SecretSelector-CJSadIZx.css} +0 -0
  208. /flowfile/web/static/assets/{SecretsView-aa291340.css → SecretsView-DbzIRAba.css} +0 -0
  209. /flowfile/web/static/assets/{SettingsSection-8f980839.css → SettingsSection-BGcJnH6q.css} +0 -0
  210. /flowfile/web/static/assets/{SettingsSection-07fbbc39.css → SettingsSection-DDWn_EGW.css} +0 -0
  211. /flowfile/web/static/assets/{SliderInput-f2e4f23c.css → SliderInput-BRk-q_Dk.css} +0 -0
  212. /flowfile/web/static/assets/{UnavailableFields-394a1f78.css → UnavailableFields-DRKDImKe.css} +0 -0
  213. /flowfile/web/static/assets/{Unique-2b705521.css → Unique-Absb0aON.css} +0 -0
  214. /flowfile/web/static/assets/{UnpivotValidation-d5ca3b7b.css → UnpivotValidation-DSBkFgS-.css} +0 -0
  215. /flowfile/web/static/assets/{airbyte-292aa232.png → airbyte-W0xvIXwZ.png} +0 -0
  216. /flowfile/web/static/assets/{cloud_storage_reader-aa1415d6.png → cloud_storage_reader-3GpSCk90.png} +0 -0
  217. /flowfile/web/static/assets/{cross_join-d30c0290.png → cross_join-B0qpgYoV.png} +0 -0
  218. /flowfile/web/static/assets/{dropDown-1d6acbd9.css → dropDown-CE0VF5_P.css} +0 -0
  219. /flowfile/web/static/assets/{explore_data-8a0a2861.png → explore_data-tX6olPPL.png} +0 -0
  220. /flowfile/web/static/assets/{fa-brands-400-808443ae.ttf → fa-brands-400-D1LuMI3I.ttf} +0 -0
  221. /flowfile/web/static/assets/{fa-brands-400-d7236a19.woff2 → fa-brands-400-D_cYUPeE.woff2} +0 -0
  222. /flowfile/web/static/assets/{fa-regular-400-e3456d12.woff2 → fa-regular-400-BjRzuEpd.woff2} +0 -0
  223. /flowfile/web/static/assets/{fa-regular-400-54cf6086.ttf → fa-regular-400-DZaxPHgR.ttf} +0 -0
  224. /flowfile/web/static/assets/{fa-solid-900-aa759986.woff2 → fa-solid-900-CTAAxXor.woff2} +0 -0
  225. /flowfile/web/static/assets/{fa-solid-900-d2f05935.ttf → fa-solid-900-D0aA9rwL.ttf} +0 -0
  226. /flowfile/web/static/assets/{fa-v4compatibility-0ce9033c.woff2 → fa-v4compatibility-C9RhG_FT.woff2} +0 -0
  227. /flowfile/web/static/assets/{fa-v4compatibility-30f6abf6.ttf → fa-v4compatibility-CCth-dXg.ttf} +0 -0
  228. /flowfile/web/static/assets/{filter-d7708bda.png → filter-WRdZyUOw.png} +0 -0
  229. /flowfile/web/static/assets/{formula-eeeb1611.png → formula-CgM7uHVI.png} +0 -0
  230. /flowfile/web/static/assets/{fullEditor-fe9f7e18.css → fullEditor-CmDI7T9F.css} +0 -0
  231. /flowfile/web/static/assets/{fuzzy_match-40c161b2.png → fuzzy_match-Yon3k5Tc.png} +0 -0
  232. /flowfile/web/static/assets/{graph_solver-8b7888b8.png → graph_solver-BlMrBttD.png} +0 -0
  233. /flowfile/web/static/assets/{group_by-80561fc3.png → group_by-Gici0CSS.png} +0 -0
  234. /flowfile/web/static/assets/{input_data-ab2eb678.png → input_data-BRdGecLc.png} +0 -0
  235. /flowfile/web/static/assets/{join-349043ae.png → join-BITWRu73.png} +0 -0
  236. /flowfile/web/static/assets/{manual_input-ae98f31d.png → manual_input-CFvo_EUS.png} +0 -0
  237. /flowfile/web/static/assets/{old_join-5d0eb604.png → old_join-B9bkpPqv.png} +0 -0
  238. /flowfile/web/static/assets/{output-06ec0371.png → output-Dp7-ZpC4.png} +0 -0
  239. /flowfile/web/static/assets/{outputExcel-f5d272b2.css → outputExcel-CKgRe2iT.css} +0 -0
  240. /flowfile/web/static/assets/{outputParquet-54597c3c.css → outputParquet-d7j407cK.css} +0 -0
  241. /flowfile/web/static/assets/{pivot-9660df51.png → pivot-DSxKhNlD.png} +0 -0
  242. /flowfile/web/static/assets/{polars_code-05ce5dc6.png → polars_code-DxiztZ1c.png} +0 -0
  243. /flowfile/web/static/assets/{readCsv-3bfac4c3.css → readCsv-BG-1Jilp.css} +0 -0
  244. /flowfile/web/static/assets/{readExcel-3db6b763.css → readExcel-DBQXKPtC.css} +0 -0
  245. /flowfile/web/static/assets/{record_count-dab44eb5.png → record_count-DCeaLtpS.png} +0 -0
  246. /flowfile/web/static/assets/{record_id-0b15856b.png → record_id-FeUjyIFh.png} +0 -0
  247. /flowfile/web/static/assets/{sample-693a88b5.png → sample-DeqfRiB-.png} +0 -0
  248. /flowfile/web/static/assets/{select-b0d0437a.png → select-D4JjbdjS.png} +0 -0
  249. /flowfile/web/static/assets/{selectDynamic-f2fb394f.css → selectDynamic-CjeTPUUo.css} +0 -0
  250. /flowfile/web/static/assets/{sort-2aa579f0.png → sort-DGwUG9WS.png} +0 -0
  251. /flowfile/web/static/assets/{summarize-2a099231.png → summarize-DFaNHpfp.png} +0 -0
  252. /flowfile/web/static/assets/{text_to_rows-859b29ea.png → text_to_rows-BdiAewrN.png} +0 -0
  253. /flowfile/web/static/assets/{union-2d8609f4.png → union-DCK-LSMq.png} +0 -0
  254. /flowfile/web/static/assets/{unique-1958b98a.png → unique-CdP3zZIq.png} +0 -0
  255. /flowfile/web/static/assets/{unpivot-d3cb4b5b.png → unpivot-CHttrEt8.png} +0 -0
  256. /flowfile/web/static/assets/{user-defined-icon-0ae16c90.png → user-defined-icon-BcIp2Vzo.png} +0 -0
  257. /flowfile/web/static/assets/{view-7a0f0be1.png → view-DUSRwjvq.png} +0 -0
  258. {flowfile-0.5.4.dist-info → flowfile-0.6.1.dist-info}/entry_points.txt +0 -0
  259. {flowfile-0.5.4.dist-info → flowfile-0.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,32 @@
1
+ from flowfile_core.flowfile.flow_node.executor import InMemoryStateProvider, NodeExecutor, StateProvider
2
+ from flowfile_core.flowfile.flow_node.flow_node import FlowNode
3
+ from flowfile_core.flowfile.flow_node.models import (
4
+ ExecutionDecision,
5
+ ExecutionStrategy,
6
+ InvalidationReason,
7
+ NodeResults,
8
+ NodeSchemaInformation,
9
+ NodeStepInputs,
10
+ NodeStepPromise,
11
+ NodeStepSettings,
12
+ NodeStepStats,
13
+ )
14
+ from flowfile_core.flowfile.flow_node.state import NodeExecutionState, SourceFileInfo
15
+
16
+ __all__ = [
17
+ "FlowNode",
18
+ "ExecutionDecision",
19
+ "ExecutionStrategy",
20
+ "InvalidationReason",
21
+ "NodeResults",
22
+ "NodeSchemaInformation",
23
+ "NodeStepInputs",
24
+ "NodeStepPromise",
25
+ "NodeStepSettings",
26
+ "NodeStepStats",
27
+ "NodeExecutionState",
28
+ "SourceFileInfo",
29
+ "NodeExecutor",
30
+ "StateProvider",
31
+ "InMemoryStateProvider",
32
+ ]
@@ -0,0 +1,404 @@
1
+ """
2
+ Node execution logic - separate from node definition.
3
+
4
+ Handles the 'how to run' independently from 'what to run'.
5
+ Enables stateless execution by accepting external state providers.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING, Protocol
10
+
11
+ from flowfile_core.flowfile.flow_data_engine.subprocess_operations import (
12
+ results_exists,
13
+ )
14
+ from flowfile_core.flowfile.flow_node.models import (
15
+ ExecutionDecision,
16
+ ExecutionStrategy,
17
+ InvalidationReason,
18
+ )
19
+ from flowfile_core.flowfile.flow_node.state import NodeExecutionState, SourceFileInfo
20
+ from flowfile_core.schemas import schemas
21
+
22
+ if TYPE_CHECKING:
23
+ from flowfile_core.configs.flow_logger import NodeLogger
24
+ from flowfile_core.flowfile.flow_node.flow_node import FlowNode
25
+
26
+
27
+ class StateProvider(Protocol):
28
+ """
29
+ Protocol for providing/storing node state.
30
+
31
+ Implement this to store state externally (Redis, DB, etc.)
32
+ for stateless worker support.
33
+ """
34
+
35
+ def get_state(self, node_id: str | int, flow_id: str) -> NodeExecutionState:
36
+ """Retrieve state for a node."""
37
+ ...
38
+
39
+ def save_state(self, node_id: str | int, flow_id: str, state: NodeExecutionState) -> None:
40
+ """Persist state for a node."""
41
+ ...
42
+
43
+
44
+ class InMemoryStateProvider:
45
+ """
46
+ Default state provider: state lives in FlowNode._execution_state.
47
+
48
+ This maintains current behavior where state is kept in memory
49
+ on the node instance itself.
50
+ """
51
+
52
+ def __init__(self, node: FlowNode):
53
+ self._node = node
54
+
55
+ def get_state(self, node_id: str | int, flow_id: str) -> NodeExecutionState:
56
+ return self._node._execution_state
57
+
58
+ def save_state(self, node_id: str | int, flow_id: str, state: NodeExecutionState) -> None:
59
+ # For in-memory, state is already on the node - nothing to do
60
+ pass
61
+
62
+
63
+ class NodeExecutor:
64
+ """
65
+ Handles node execution logic.
66
+
67
+ Separated from FlowNode to allow:
68
+ - Stateless execution (state from external source)
69
+ - Different execution strategies
70
+ - Easier testing
71
+ - Clear separation of concerns
72
+
73
+ Performance note: This class is designed to be reused via lazy
74
+ instantiation on FlowNode._executor to avoid repeated object creation.
75
+ """
76
+
77
+ __slots__ = ('node', 'state_provider')
78
+
79
+ def __init__(
80
+ self,
81
+ node: FlowNode,
82
+ state_provider: StateProvider | None = None,
83
+ ):
84
+ self.node = node
85
+ self.state_provider = state_provider or InMemoryStateProvider(node)
86
+
87
+ def execute(
88
+ self,
89
+ run_location: schemas.ExecutionLocationsLiteral,
90
+ reset_cache: bool = False,
91
+ performance_mode: bool = False,
92
+ retry: bool = True,
93
+ node_logger: NodeLogger = None,
94
+ optimize_for_downstream: bool = True,
95
+ ) -> None:
96
+ """
97
+ Main execution entry point.
98
+
99
+ This method is called when the fast-path in FlowNode.execute_node()
100
+ determines that full execution logic is needed.
101
+
102
+ Args:
103
+ run_location: Where to execute ('local' or 'remote')
104
+ reset_cache: Force cache invalidation
105
+ performance_mode: Skip example data generation for speed
106
+ retry: Allow retry on recoverable errors
107
+ node_logger: Logger for this node's execution
108
+ optimize_for_downstream: Cache wide transforms for downstream nodes
109
+ """
110
+ if node_logger is None:
111
+ raise ValueError("node_logger is required")
112
+
113
+ state = self.state_provider.get_state(self.node.node_id, self.node.parent_uuid)
114
+
115
+ # Handle explicit cache reset
116
+ if reset_cache:
117
+ self._clear_cache(state)
118
+
119
+ # Decide execution strategy
120
+ decision = self._decide_execution(state, run_location, performance_mode, reset_cache)
121
+
122
+ # Override for wide transforms when optimizing for downstream
123
+ if (decision.should_run
124
+ and decision.strategy == ExecutionStrategy.LOCAL_WITH_SAMPLING
125
+ and self.node.node_default
126
+ and self.node.node_default.transform_type == "wide"
127
+ and optimize_for_downstream
128
+ and run_location != "local"):
129
+ decision = ExecutionDecision(True, ExecutionStrategy.REMOTE, decision.reason)
130
+
131
+ if not decision.should_run:
132
+ return
133
+
134
+ reason_str = decision.reason.name if decision.reason else "UNKNOWN"
135
+ strategy_str = decision.strategy.name
136
+ node_logger.info(f"Starting to run {self.node.__name__} ({reason_str} -> {strategy_str})")
137
+
138
+ # Override performance_mode when cache_results is enabled
139
+ # This ensures example data is generated even in Performance mode
140
+ effective_performance_mode = performance_mode
141
+ if self.node.node_settings.cache_results:
142
+ effective_performance_mode = False
143
+
144
+ # Prepare and execute
145
+ self._prepare_for_execution(state)
146
+ self.node.reset()
147
+
148
+ try:
149
+ self._execute_with_strategy(state, decision.strategy, effective_performance_mode, node_logger)
150
+ self._update_source_file_info(state)
151
+ self._sync_state_to_legacy(state)
152
+ self.state_provider.save_state(self.node.node_id, self.node.parent_uuid, state)
153
+ except Exception as e:
154
+ self._handle_error(state, e, run_location, effective_performance_mode, retry, node_logger)
155
+
156
+ def _decide_execution(
157
+ self,
158
+ state: NodeExecutionState,
159
+ run_location: schemas.ExecutionLocationsLiteral,
160
+ performance_mode: bool,
161
+ force_refresh: bool,
162
+ ) -> ExecutionDecision:
163
+ """
164
+ Single source of truth for execution decisions.
165
+
166
+ Determines both WHETHER to run and HOW to run in one place.
167
+ """
168
+ # Output nodes always run
169
+ if self.node.node_template.node_group == "output":
170
+ strategy = self._determine_strategy(run_location)
171
+ return ExecutionDecision(True, strategy, InvalidationReason.OUTPUT_NODE)
172
+
173
+ # Forced refresh (reset_cache=True)
174
+ if force_refresh:
175
+ strategy = self._determine_strategy(run_location)
176
+ return ExecutionDecision(True, strategy, InvalidationReason.FORCED_REFRESH)
177
+
178
+ # Never ran before
179
+ if not state.has_run_with_current_setup:
180
+ strategy = self._determine_strategy(run_location)
181
+ return ExecutionDecision(True, strategy, InvalidationReason.NEVER_RAN)
182
+
183
+ # Check if source file changed (for read nodes)
184
+ if self._source_file_changed(state):
185
+ strategy = self._determine_strategy(run_location)
186
+ return ExecutionDecision(True, strategy, InvalidationReason.SOURCE_FILE_CHANGED)
187
+
188
+ # Cache-enabled nodes: check if cache file is still present
189
+ if self.node.node_settings.cache_results:
190
+ if results_exists(self.node.hash):
191
+ return ExecutionDecision(False, ExecutionStrategy.SKIP, None)
192
+ strategy = self._determine_strategy(run_location)
193
+ return ExecutionDecision(True, strategy, InvalidationReason.CACHE_MISSING)
194
+
195
+ # Already ran with current settings → skip
196
+ # Results are available in memory from previous execution
197
+ return ExecutionDecision(False, ExecutionStrategy.SKIP, None)
198
+
199
+ def _determine_strategy(
200
+ self,
201
+ run_location: schemas.ExecutionLocationsLiteral,
202
+ ) -> ExecutionStrategy:
203
+ """Determine the execution strategy based on location and node settings.
204
+
205
+ Decision logic:
206
+ - local → FULL_LOCAL
207
+ - remote + cache_results → REMOTE (caching needs full materialization)
208
+ - remote + narrow transform → LOCAL_WITH_SAMPLING (fast local compute + external sampler)
209
+ - remote → REMOTE
210
+
211
+ Narrow transforms (e.g., select, sample, union) only operate on columns
212
+ without reshaping data, so they're cheap to compute locally. An external
213
+ sampler provides preview data for the UI.
214
+
215
+ When cache_results is enabled, the node must run fully remote so the
216
+ result can be materialized and stored in the cache.
217
+ """
218
+ # Local execution mode (e.g., WASM, no worker available)
219
+ if run_location == "local":
220
+ return ExecutionStrategy.FULL_LOCAL
221
+
222
+ # Caching requires full remote execution to materialize and store results
223
+ if self.node.node_settings.cache_results:
224
+ return ExecutionStrategy.REMOTE
225
+
226
+ # Narrow transforms are lightweight column-level operations that can
227
+ # run locally with an external sampler for preview data
228
+ if (self.node.node_default is not None
229
+ and self.node.node_default.transform_type == "narrow"):
230
+ return ExecutionStrategy.LOCAL_WITH_SAMPLING
231
+
232
+ # Full remote execution for wide transforms and everything else
233
+ return ExecutionStrategy.REMOTE
234
+
235
+ def _execute_with_strategy(
236
+ self,
237
+ state: NodeExecutionState,
238
+ strategy: ExecutionStrategy,
239
+ performance_mode: bool,
240
+ node_logger: NodeLogger,
241
+ ) -> None:
242
+ """Execute using the determined strategy."""
243
+ match strategy:
244
+ case ExecutionStrategy.SKIP:
245
+ return
246
+ case ExecutionStrategy.FULL_LOCAL:
247
+ self._do_full_local(state, performance_mode)
248
+ case ExecutionStrategy.LOCAL_WITH_SAMPLING:
249
+ self._do_local_with_sampling(state, performance_mode, node_logger.flow_id)
250
+ case ExecutionStrategy.REMOTE:
251
+ self._do_remote(state, performance_mode, node_logger)
252
+
253
+ def _do_full_local(self, state: NodeExecutionState, performance_mode: bool) -> None:
254
+ """
255
+ 100% in-process execution.
256
+
257
+ Used for WASM environments or when no external worker is available.
258
+ """
259
+ self.node._do_execute_full_local(performance_mode)
260
+ if not performance_mode:
261
+ state.mark_successful()
262
+ if self.node.results.resulting_data is not None:
263
+ state.result_schema = self.node.results.resulting_data.schema
264
+
265
+ def _do_local_with_sampling(
266
+ self,
267
+ state: NodeExecutionState,
268
+ performance_mode: bool,
269
+ flow_id: int
270
+ ) -> None:
271
+ """
272
+ In-process execution with external sampler for preview data.
273
+
274
+ The main computation runs locally, but sample data is generated
275
+ via an external process for the UI preview.
276
+ """
277
+ self.node._do_execute_local_with_sampling(performance_mode, flow_id)
278
+ if self.node.results.resulting_data is not None:
279
+ state.result_schema = self.node.results.resulting_data.schema
280
+ if self.node.results.errors is None and not self.node.node_stats.is_canceled:
281
+ state.mark_successful()
282
+
283
+ def _do_remote(
284
+ self,
285
+ state: NodeExecutionState,
286
+ performance_mode: bool,
287
+ node_logger: NodeLogger
288
+ ) -> None:
289
+ """
290
+ Full remote worker execution.
291
+
292
+ Computation is offloaded to an external worker process.
293
+ """
294
+ self.node._do_execute_remote(performance_mode, node_logger)
295
+ if self.node.results.resulting_data is not None:
296
+ state.result_schema = self.node.results.resulting_data.schema
297
+ state.mark_successful()
298
+
299
+ def _source_file_changed(self, state: NodeExecutionState) -> bool:
300
+ """
301
+ Check if source file has changed since last successful run.
302
+
303
+ Only applicable to read nodes. Returns False for other node types.
304
+ """
305
+ if self.node.node_type != "read":
306
+ return False
307
+
308
+ path = self._get_source_path()
309
+ if not path:
310
+ return False
311
+
312
+ # First time - no previous info to compare
313
+ if state.source_file_info is None:
314
+ return False
315
+
316
+ return state.source_file_info.has_changed()
317
+
318
+ def _get_source_path(self) -> str | None:
319
+ """Get the source file path for read nodes."""
320
+ setting_input = self.node.setting_input
321
+ if not hasattr(setting_input, 'received_file') or not setting_input.received_file:
322
+ return None
323
+
324
+ rf = setting_input.received_file
325
+ # Prefer absolute path if available
326
+ if hasattr(rf, 'abs_file_path') and rf.abs_file_path:
327
+ return rf.abs_file_path
328
+ return rf.path if hasattr(rf, 'path') else None
329
+
330
+ def _update_source_file_info(self, state: NodeExecutionState) -> None:
331
+ """Update source file tracking after successful execution."""
332
+ if self.node.node_type != "read":
333
+ return
334
+
335
+ path = self._get_source_path()
336
+ if path:
337
+ state.source_file_info = SourceFileInfo.from_path(path)
338
+
339
+ def _prepare_for_execution(self, state: NodeExecutionState) -> None:
340
+ """Prepare node state before execution."""
341
+ self.node.clear_table_example()
342
+ state.reset_results_only()
343
+ self.node.results.errors = None
344
+ self.node.results.resulting_data = None
345
+ self.node.results.example_data = None
346
+
347
+ def _clear_cache(self, state: NodeExecutionState) -> None:
348
+ """Clear cached results."""
349
+ self.node.remove_cache()
350
+ state.has_run_with_current_setup = False
351
+ state.has_completed_last_run = False
352
+
353
+ def _sync_state_to_legacy(self, state: NodeExecutionState) -> None:
354
+ """Sync _execution_state to legacy node_stats for backwards compatibility."""
355
+ self.node.node_stats._has_run_with_current_setup = state.has_run_with_current_setup
356
+ self.node.node_stats.has_completed_last_run = state.has_completed_last_run
357
+ self.node.node_stats.is_canceled = state.is_canceled
358
+ self.node.node_stats.error = state.error
359
+
360
+ def _handle_error(
361
+ self,
362
+ state: NodeExecutionState,
363
+ error: Exception,
364
+ run_location: schemas.ExecutionLocationsLiteral,
365
+ performance_mode: bool,
366
+ retry: bool,
367
+ node_logger: NodeLogger,
368
+ ) -> None:
369
+ """Handle execution errors with retry logic."""
370
+ error_str = str(error)
371
+ state.mark_failed(error_str)
372
+ self._sync_state_to_legacy(state)
373
+ self.node.results.errors = error_str
374
+
375
+ # Retry on missing file errors (upstream cache was cleared)
376
+ if "No such file or directory (os error" in error_str and retry:
377
+ node_logger.warning("Input file missing, retrying upstream nodes...")
378
+ for node_input in self.node.node_inputs.get_all_inputs():
379
+ # Recursively execute upstream nodes
380
+ node_input.execute_node(
381
+ run_location=run_location,
382
+ performance_mode=performance_mode,
383
+ retry=True,
384
+ reset_cache=True,
385
+ node_logger=node_logger,
386
+ )
387
+ # Retry this node once (no further retries)
388
+ self.execute(
389
+ run_location=run_location,
390
+ performance_mode=performance_mode,
391
+ retry=False,
392
+ node_logger=node_logger,
393
+ )
394
+ return
395
+
396
+ # Log appropriate error message
397
+ if "Connection refused" in error_str and "/submit_query/" in error_str:
398
+ node_logger.warning(
399
+ "Could not connect to remote worker. "
400
+ "Ensure the worker process is running, or change settings to local execution."
401
+ )
402
+ node_logger.error("Remote worker connection refused")
403
+ else:
404
+ node_logger.error(f"Error running node: {error}")