diff --git a/CHANGELOG.md b/CHANGELOG.md index b96ec476ee..95d061e880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [1.566.1](https://github.com/windmill-labs/windmill/compare/v1.566.0...v1.566.1) (2025-10-25) + + +### Bug Fixes + +* fix dependency jobs on CE ([29b6feb](https://github.com/windmill-labs/windmill/commit/29b6febdd81cf16bd14a9ec4528e215e8221704a)) + +## [1.566.0](https://github.com/windmill-labs/windmill/compare/v1.565.0...v1.566.0) (2025-10-24) + + +### Features + +* **aichat:** add user-level custom system prompts ([#6884](https://github.com/windmill-labs/windmill/issues/6884)) ([b5d0f23](https://github.com/windmill-labs/windmill/commit/b5d0f23f4fe9ea05069cada517a47ebe1cf8267a)) +* **backend:** pass all headers and query to webhook preprocessor ([#6931](https://github.com/windmill-labs/windmill/issues/6931)) ([f0bbdd4](https://github.com/windmill-labs/windmill/commit/f0bbdd4aa8a95f1894e9a19687856afa9d73142f)) +* **backend:** stream early return ([#6896](https://github.com/windmill-labs/windmill/issues/6896)) ([e81d629](https://github.com/windmill-labs/windmill/commit/e81d6297050b468e30074ec1ac144be368040d4a)) +* **flow chat:** display image outputs ([#6880](https://github.com/windmill-labs/windmill/issues/6880)) ([53d8fbe](https://github.com/windmill-labs/windmill/commit/53d8fbe5084b3fb8d4eba3555d7d85458bf05aed)) +* job debouncing ([#6878](https://github.com/windmill-labs/windmill/issues/6878)) ([edece03](https://github.com/windmill-labs/windmill/commit/edece035f806aafde5696b0b2711a53ead2bf9c4)) +* support wildcards in http routes ([#6927](https://github.com/windmill-labs/windmill/issues/6927)) ([f43dee1](https://github.com/windmill-labs/windmill/commit/f43dee1952d28a6bbfd2912ab78623da081b60f9)) + + +### Bug Fixes + +* also auto add/del igroup members to workspaces where configured ([#6888](https://github.com/windmill-labs/windmill/issues/6888)) ([1d3245e](https://github.com/windmill-labs/windmill/commit/1d3245eea260609b2f32ba4839e96b2e13d0dabc)) +* apify oauth ([#6902](https://github.com/windmill-labs/windmill/issues/6902)) ([b33e3d8](https://github.com/windmill-labs/windmill/commit/b33e3d85052699becc0d211b2d5737be4d68da4a)) +* **cli:** increase custom bundler output size ([fadfcfd](https://github.com/windmill-labs/windmill/commit/fadfcfd0fce52c3906b1cdd2d2ace5af8dfb01f7)) +* **cli:** resource type sync with protected private hub ([#6933](https://github.com/windmill-labs/windmill/issues/6933)) ([6d403da](https://github.com/windmill-labs/windmill/commit/6d403da05addca02614c9f013a56e78734c0a4f9)) +* **cloud:** better errors when failing to get team plan status ([#6908](https://github.com/windmill-labs/windmill/issues/6908)) ([7b46491](https://github.com/windmill-labs/windmill/commit/7b464915785c576484b53dea8b9a5d9ebd74ec2b)) +* **debouncing:** fix perf issues and re-enable debouncing ([#6932](https://github.com/windmill-labs/windmill/issues/6932)) ([999aaaa](https://github.com/windmill-labs/windmill/commit/999aaaacd8727f2a8afdac2007e6536c66f1c2f7)) +* detect preprocessor in re-exported named exports ([#6899](https://github.com/windmill-labs/windmill/issues/6899)) ([fa76105](https://github.com/windmill-labs/windmill/commit/fa76105d14e6ca113de494d5c3faf8175582712e)) +* **yaml-validator:** update openflow for aiagents ([#6895](https://github.com/windmill-labs/windmill/issues/6895)) ([e40d52d](https://github.com/windmill-labs/windmill/commit/e40d52d411187f9b433c765611686e30a2807037)) + ## [1.565.0](https://github.com/windmill-labs/windmill/compare/v1.564.0...v1.565.0) (2025-10-22) diff --git a/backend/.sqlx/query-53dee7c119d724624b9973ee981576154cec84a09069286d2d7144dbad54f4d6.json b/backend/.sqlx/query-53dee7c119d724624b9973ee981576154cec84a09069286d2d7144dbad54f4d6.json new file mode 100644 index 0000000000..902ed458c2 --- /dev/null +++ b/backend/.sqlx/query-53dee7c119d724624b9973ee981576154cec84a09069286d2d7144dbad54f4d6.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO script\n (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets, debounce_key, debounce_delay_s)\n\n SELECT workspace_id, $1, path, array_prepend($2::bigint, COALESCE(parent_hashes, '{}'::bigint[])), summary, description, content, created_by, schema, is_template, extra_perms, NULL, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets, debounce_key, debounce_delay_s\n\n FROM script WHERE hash = $2 AND workspace_id = $3;\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Text" + ] + }, + "nullable": [] + }, + "hash": "53dee7c119d724624b9973ee981576154cec84a09069286d2d7144dbad54f4d6" +} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index ddbcfa6458..f1c399ff1c 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -547,7 +547,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -661,7 +661,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -683,7 +683,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -694,7 +694,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1223,7 +1223,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1363,7 +1363,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.107", + "syn 2.0.108", "which 4.4.2", ] @@ -1384,7 +1384,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1404,7 +1404,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1611,7 +1611,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1634,7 +1634,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1644,7 +1644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17d4f95e880cfd28c4ca5a006cf7f6af52b4bcb7b5866f573b2faa126fb7affb" dependencies = [ "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1778,7 +1778,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1921,7 +1921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b4a6cae9efc04cc6cbb8faf338d2c497c165c83e74509cf4dbedea948bbf6e5" dependencies = [ "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -1935,9 +1935,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.41" +version = "1.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" dependencies = [ "find-msvc-tools", "jobserver", @@ -2073,7 +2073,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2128,7 +2128,7 @@ dependencies = [ "nom 7.1.3", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2510,7 +2510,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2603,7 +2603,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2617,7 +2617,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2650,7 +2650,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -2661,7 +2661,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -3153,7 +3153,7 @@ checksum = "df6f88d7ee27daf8b108ba910f9015176b36fbc72902b1ca5c2a5f1d1717e1a1" dependencies = [ "datafusion-expr", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -3591,7 +3591,7 @@ checksum = "babccedee31ce7e57c3e6dff2cb3ab8d68c49d0df8222fe0d11d628e65192790" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -3982,7 +3982,7 @@ dependencies = [ "stringcase", "strum 0.25.0", "strum_macros 0.25.3", - "syn 2.0.107", + "syn 2.0.108", "thiserror 2.0.17", ] @@ -4484,7 +4484,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -4505,7 +4505,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -4580,7 +4580,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -4600,7 +4600,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -4726,7 +4726,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -4761,14 +4761,14 @@ checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -4971,7 +4971,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5037,7 +5037,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5057,7 +5057,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5077,7 +5077,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5324,9 +5324,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "libz-rs-sys", @@ -5394,7 +5394,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5432,7 +5432,7 @@ checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5567,7 +5567,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -5952,7 +5952,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -6284,7 +6284,7 @@ checksum = "149e3ea90eb5a26ad354cfe3cb7f7401b9329032d0235f2687d03a35f30e5d4c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -6476,11 +6476,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7135,7 +7135,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -7486,7 +7486,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -7542,7 +7542,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -7775,9 +7775,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" @@ -8149,7 +8149,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -8268,7 +8268,7 @@ checksum = "c402a4092d5e204f32c9e155431046831fa712637043c58cb73bc6bc6c9663b5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -8313,7 +8313,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "termcolor", "thiserror 2.0.17", ] @@ -8416,7 +8416,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -8622,7 +8622,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -8891,7 +8891,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9110,7 +9110,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9574,7 +9574,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9655,7 +9655,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9705,7 +9705,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9917,7 +9917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9981,7 +9981,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -9992,7 +9992,7 @@ checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" dependencies = [ "proc-macro-rules-macros", "proc-macro2", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -10004,14 +10004,14 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -10115,7 +10115,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.107", + "syn 2.0.108", "tempfile", ] @@ -10129,7 +10129,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -10538,7 +10538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" dependencies = [ "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -10607,7 +10607,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -10883,9 +10883,9 @@ dependencies = [ [[package]] name = "rmcp" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35d31f89beb59c83bc31363426da25b323ce0c2e5b53c7bf29867d16ee7898" +checksum = "1fdad1258f7259fdc0f2dfc266939c82c3b5d1fd72bcde274d600cdc27e60243" dependencies = [ "base64 0.22.1", "bytes", @@ -10914,15 +10914,15 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88518b38110c439a03f0f4eee40e5105d648a530711cb87f98991e3f324a664" +checksum = "ede0589a208cc7ce81d1be68aa7e74b917fcd03c81528408bab0457e187dcd9b" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", "serde_json", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11012,7 +11012,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.107", + "syn 2.0.108", "walkdir", ] @@ -11499,7 +11499,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11511,7 +11511,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11700,7 +11700,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11711,7 +11711,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11763,7 +11763,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -11830,7 +11830,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12261,7 +12261,7 @@ checksum = "da5fc6819faabb412da764b99d3b713bb55083c11e7e0c00144d386cd6a1939c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12326,7 +12326,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12349,7 +12349,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.107", + "syn 2.0.108", "tokio", "url", ] @@ -12513,7 +12513,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12582,7 +12582,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12594,7 +12594,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12713,7 +12713,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12762,7 +12762,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12847,7 +12847,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12954,7 +12954,7 @@ checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12965,7 +12965,7 @@ checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -12988,7 +12988,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -13004,9 +13004,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.107" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -13048,7 +13048,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -13406,7 +13406,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -13417,7 +13417,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -13663,7 +13663,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -14093,7 +14093,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -14346,7 +14346,7 @@ checksum = "27a7a9b72ba121f6f1f6c3632b85604cac41aedb5ddc70accbebb6cac83de846" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -14829,7 +14829,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "wasm-bindgen-shared", ] @@ -14864,7 +14864,7 @@ checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -14899,7 +14899,7 @@ checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -15153,7 +15153,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "aws-sdk-config", @@ -15213,7 +15213,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "argon2", @@ -15333,7 +15333,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.565.0" +version = "1.566.1" dependencies = [ "base64 0.22.1", "chrono", @@ -15348,7 +15348,7 @@ dependencies = [ [[package]] name = "windmill-audit" -version = "1.565.0" +version = "1.566.1" dependencies = [ "chrono", "serde", @@ -15361,7 +15361,7 @@ dependencies = [ [[package]] name = "windmill-autoscaling" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "axum", @@ -15380,7 +15380,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "async-recursion", @@ -15465,7 +15465,7 @@ dependencies = [ [[package]] name = "windmill-git-sync" -version = "1.565.0" +version = "1.566.1" dependencies = [ "regex", "serde", @@ -15480,7 +15480,7 @@ dependencies = [ [[package]] name = "windmill-indexer" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "bytes", @@ -15504,19 +15504,19 @@ dependencies = [ [[package]] name = "windmill-macros" -version = "1.565.0" +version = "1.566.1" dependencies = [ "itertools 0.14.0", "lazy_static", "proc-macro2", "quote", "regex", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] name = "windmill-parser" -version = "1.565.0" +version = "1.566.1" dependencies = [ "convert_case 0.6.0", "serde", @@ -15525,7 +15525,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "lazy_static", @@ -15537,7 +15537,7 @@ dependencies = [ [[package]] name = "windmill-parser-csharp" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "serde_json", @@ -15549,7 +15549,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "gosyn", @@ -15561,7 +15561,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "lazy_static", @@ -15573,7 +15573,7 @@ dependencies = [ [[package]] name = "windmill-parser-java" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "serde_json", @@ -15585,7 +15585,7 @@ dependencies = [ [[package]] name = "windmill-parser-nu" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "nu-parser", @@ -15596,7 +15596,7 @@ dependencies = [ [[package]] name = "windmill-parser-php" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "itertools 0.14.0", @@ -15607,7 +15607,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "itertools 0.14.0", @@ -15619,7 +15619,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "async-recursion", @@ -15642,7 +15642,7 @@ dependencies = [ [[package]] name = "windmill-parser-ruby" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "lazy_static", @@ -15656,7 +15656,7 @@ dependencies = [ [[package]] name = "windmill-parser-rust" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -15666,14 +15666,14 @@ dependencies = [ "quote", "regex", "serde_json", - "syn 2.0.107", + "syn 2.0.108", "toml", "windmill-parser", ] [[package]] name = "windmill-parser-sql" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "lazy_static", @@ -15687,7 +15687,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "lazy_static", @@ -15705,7 +15705,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "getrandom 0.2.16", @@ -15730,7 +15730,7 @@ dependencies = [ [[package]] name = "windmill-parser-yaml" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "serde", @@ -15741,7 +15741,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "async-recursion", @@ -15774,7 +15774,7 @@ dependencies = [ [[package]] name = "windmill-sql-datatype-parser-wasm" -version = "1.565.0" +version = "1.566.1" dependencies = [ "wasm-bindgen", "wasm-bindgen-test", @@ -15784,7 +15784,7 @@ dependencies = [ [[package]] name = "windmill-worker" -version = "1.565.0" +version = "1.566.1" dependencies = [ "anyhow", "async-once-cell", @@ -15995,7 +15995,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16006,7 +16006,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16017,7 +16017,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16028,7 +16028,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16039,7 +16039,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16050,7 +16050,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16548,7 +16548,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "synstructure 0.13.2", ] @@ -16560,7 +16560,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "synstructure 0.13.2", ] @@ -16581,7 +16581,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16601,7 +16601,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", "synstructure 0.13.2", ] @@ -16622,7 +16622,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] @@ -16655,7 +16655,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn 2.0.108", ] [[package]] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 3817c5af7d..2aa9a4f301 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.565.0" +version = "1.566.1" authors.workspace = true edition.workspace = true @@ -34,7 +34,7 @@ members = [ exclude = ["./windmill-duckdb-ffi-internal"] [workspace.package] -version = "1.565.0" +version = "1.566.1" authors = ["Ruben Fiszel "] edition = "2021" @@ -161,6 +161,7 @@ bitflags.workspace = true nom.workspace = true globset.workspace = true + [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = { optional = true, workspace = true } tikv-jemalloc-sys = { optional = true, workspace = true } @@ -265,6 +266,7 @@ aws-sigv4 = "^1.3.4" aws-sdk-config = "=1.68.0" async-trait = "0.1.88" + v8 = "=130.0.7" # Exact version NOTE: Do not forget to update version and hash in flake.nix deno_fetch = "0.214.0" deno_tls = "0.177.0" diff --git a/backend/migrations/20251024141453_job_debouncing_index_by_job_id.down.sql b/backend/migrations/20251024141453_job_debouncing_index_by_job_id.down.sql new file mode 100644 index 0000000000..719fdc0390 --- /dev/null +++ b/backend/migrations/20251024141453_job_debouncing_index_by_job_id.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +DROP INDEX IF EXISTS idx_debounce_key_job_id; diff --git a/backend/migrations/20251024141453_job_debouncing_index_by_job_id.up.sql b/backend/migrations/20251024141453_job_debouncing_index_by_job_id.up.sql new file mode 100644 index 0000000000..baaa49400e --- /dev/null +++ b/backend/migrations/20251024141453_job_debouncing_index_by_job_id.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +CREATE INDEX IF NOT EXISTS idx_debounce_key_job_id ON debounce_key (job_id); diff --git a/backend/parsers/windmill-parser-py-imports/src/lib.rs b/backend/parsers/windmill-parser-py-imports/src/lib.rs index bc63d2f8af..b024ba6244 100644 --- a/backend/parsers/windmill-parser-py-imports/src/lib.rs +++ b/backend/parsers/windmill-parser-py-imports/src/lib.rs @@ -170,10 +170,10 @@ fn parse_code_for_imports(code: &str, path: &str) -> error::Result> // This is needed because we've split off the real main function above let code_with_fake_main = format!("{}\n\ndef main(): pass", code); + let ast = Suite::parse(&code_with_fake_main, "main.py").map_err(|e| { error::Error::ExecutionErr(format!("Error parsing code for imports: {}", e.to_string())) })?; - // Note: We're still using the original code for finding pins, // as the TextRange values from the parsed AST would be based on code_with_fake_main // but we want to match against the original code diff --git a/backend/tests/relative_imports.rs b/backend/tests/relative_imports.rs index 78484d0879..0403365850 100644 --- a/backend/tests/relative_imports.rs +++ b/backend/tests/relative_imports.rs @@ -577,6 +577,12 @@ def main(): async fn test_1(db: sqlx::Pool) -> anyhow::Result<()> { // This tests if debouncing and consolidation works. // Also makes sures that dependency job does not create new flow version + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } let (client, port, _s) = init_client(db.clone()).await; let mut completed = listen_for_completed_jobs(&db).await; @@ -792,6 +798,12 @@ def main(): async fn test_left(db: sqlx::Pool) -> anyhow::Result<()> { use crate::common::RunJob; + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } // TODO: We don't care about timer. If there is no timer, it will be set automatically for djobs?? let (_client, port, _s) = init_client(db.clone()).await; let mut completed = listen_for_completed_jobs(&db).await; @@ -1114,6 +1126,12 @@ def main(): // #[windmill::all_min_versions] async fn test_3(db: sqlx::Pool) -> anyhow::Result<()> { // This tests checks if concurrency limit works correcly and there is no race conditions. + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } let (_client, port, _s) = init_client(db.clone()).await; let mut completed = listen_for_completed_jobs(&db).await; @@ -1441,6 +1459,12 @@ WHERE #[cfg(feature = "python")] #[sqlx::test(fixtures("base", "djob_debouncing"))] async fn test_1(db: sqlx::Pool) -> anyhow::Result<()> { + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } // This tests if debouncing and consolidation works. // Also makes sures that dependency job does not create new flow version @@ -1620,6 +1644,12 @@ WHERE #[sqlx::test(fixtures("base", "djob_debouncing"))] async fn test_left(db: sqlx::Pool) -> anyhow::Result<()> { use crate::common::RunJob; + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } // TODO: We don't care about timer. If there is no timer, it will be set automatically for djobs?? let (_client, port, _s) = init_client(db.clone()).await; @@ -1929,6 +1959,12 @@ WHERE #[sqlx::test(fixtures("base", "djob_debouncing"))] // TODO: Same test_but script fails. async fn test_1(db: sqlx::Pool) -> anyhow::Result<()> { + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } // This tests if debouncing and consolidation works. // Also makes sures that dependency job does not create new flow version let (client, port, _s) = init_client(db.clone()).await; @@ -2172,6 +2208,12 @@ WHERE #[sqlx::test(fixtures("base", "djob_debouncing"))] async fn test_left(db: sqlx::Pool) -> anyhow::Result<()> { use crate::common::RunJob; + { + let mut mvsd = windmill_common::worker::MIN_VERSION_SUPPORTS_DEBOUNCING + .write() + .await; + *mvsd = true; + } // TODO: We don't care about timer. If there is no timer, it will be set automatically for djobs?? let (_client, port, _s) = init_client(db.clone()).await; @@ -2281,6 +2323,7 @@ WHERE .await .unwrap(); + dbg!(&r); assert_eq!(r.len(), 4); assert!(r.contains(&Some(-221349019907577876))); assert!(r.contains(&Some(533400))); diff --git a/backend/tests/worker.rs b/backend/tests/worker.rs index c2516e1877..1129846bc9 100644 --- a/backend/tests/worker.rs +++ b/backend/tests/worker.rs @@ -2869,13 +2869,15 @@ def heavy_compute(n: int): def send_result(res: int, email: str): print(f"Sending result {res} to {email}") return "OK" - + def main(n: int): l = [] for i in range(n): l.append(heavy_compute(i)) print(l) return [send_result(sum(l), "example@example.com"), n] + + "#; #[cfg(feature = "python")] diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 97e8523149..f5cf215eca 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.565.0 + version: 1.566.1 title: Windmill API contact: @@ -15442,6 +15442,10 @@ components: type: integer concurrency_key: type: string + debounce_key: + type: string + debounce_delay_s: + type: integer cache_ttl: type: number dedicated_worker: diff --git a/backend/windmill-api/src/args.rs b/backend/windmill-api/src/args.rs index a541f8c738..763074948f 100644 --- a/backend/windmill-api/src/args.rs +++ b/backend/windmill-api/src/args.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use axum::{ - extract::{FromRequest, FromRequestParts, Multipart, Query, Request}, - http::{HeaderMap, Uri}, + extract::{FromRequest, Multipart, Query, Request}, + http::HeaderMap, response::{IntoResponse, Response}, }; use bytes::Bytes; -use http::{header::CONTENT_TYPE, request::Parts, StatusCode}; +use http::{header::CONTENT_TYPE, StatusCode}; use serde::{Deserialize, Serialize}; use serde_json::value::RawValue; use sqlx::types::JsonRawValue; @@ -44,11 +44,13 @@ pub enum Body { #[derive(Debug, Clone, Default)] pub struct WebhookArgsMetadata { pub raw_string: Option, - pub headers: HashMap>, + pub headers: HeaderMap, + pub query: Option, pub method: http::Method, - pub query: HashMap>, pub query_wrap_body: bool, pub query_use_raw: bool, + pub query_include_header: Option, + pub query_include_query: Option, } pub struct RawWebhookArgs { @@ -262,6 +264,18 @@ impl WebhookArgs { self, runnable_format: RunnableFormat, ) -> Result { + let headers = build_headers( + &self.metadata.headers, + self.metadata.query_include_header, + runnable_format.has_preprocessor, + ); + + let query = build_query( + self.metadata.query.as_deref(), + self.metadata.query_include_query, + runnable_format.has_preprocessor, + ); + match runnable_format { RunnableFormat { has_preprocessor: true, version: RunnableFormatVersion::V2 } => { let mut args = HashMap::new(); @@ -272,8 +286,8 @@ impl WebhookArgs { kind: "webhook".to_string(), body: to_raw_value(&self.body), raw_string: self.metadata.raw_string, - headers: self.metadata.headers, - query: self.metadata.query, + headers, + query, }), ); @@ -282,8 +296,7 @@ impl WebhookArgs { RunnableFormat { has_preprocessor, .. } => { let mut extra = HashMap::new(); - let WebhookArgsMetadata { query, query_wrap_body, headers, raw_string, .. } = - self.metadata; + let WebhookArgsMetadata { query_wrap_body, raw_string, .. } = self.metadata; for (k, v) in headers { extra.insert(k, v); @@ -332,6 +345,7 @@ pub struct RequestQuery { pub raw: Option, pub wrap_body: Option, pub include_header: Option, + pub include_query: Option, } async fn req_to_string( @@ -359,23 +373,21 @@ where let content_type = content_type_header.and_then(|value| value.to_str().ok()); let uri = request.uri(); let request_query = Query::::try_from_uri(uri).unwrap().0; - let headers = build_headers(&headers_map, request_query.include_header, is_http_trigger); - let query_decode = DecodeQueries::from_uri(uri, is_http_trigger); - let mut query = HashMap::new(); - if let Some(DecodeQueries(queries)) = query_decode { - query.extend(queries); - } + + let query = uri.query().map(|s| s.to_owned()); let raw = !is_http_trigger && request_query.raw.unwrap_or(false); let wrap_body = !is_http_trigger && request_query.wrap_body.unwrap_or(false); ( content_type, WebhookArgsMetadata { - headers, + headers: headers_map.clone(), query, method: request.method().clone(), raw_string: None, query_wrap_body: wrap_body, query_use_raw: raw, + query_include_header: request_query.include_header, + query_include_query: request_query.include_query, }, ) }; @@ -460,11 +472,11 @@ lazy_static::lazy_static! { pub fn build_headers( headers: &HeaderMap, include_header: Option, - is_http_trigger: bool, + include_all_headers: bool, ) -> HashMap> { let mut selected_headers = HashMap::new(); - if is_http_trigger { + if include_all_headers { for (k, v) in headers.iter() { selected_headers.insert( k.to_string(), @@ -490,73 +502,40 @@ pub fn build_headers( selected_headers } -#[derive(Deserialize)] -pub struct IncludeQuery { - pub include_query: Option, -} +pub fn build_query( + query: Option<&str>, + include_query: Option, + include_all_query: bool, +) -> HashMap> { + let Some(query) = query else { + return HashMap::new(); + }; -pub struct DecodeQueries(pub HashMap>); - -#[axum::async_trait] -impl FromRequestParts for DecodeQueries -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { - Ok(DecodeQueries::from_uri(&parts.uri, false) - .unwrap_or_else(|| DecodeQueries(HashMap::new()))) - } -} - -impl DecodeQueries { - pub fn from_uri(uri: &Uri, is_http_trigger: bool) -> Option { - let query = uri.query(); - if query.is_none() { - return None; - } - let query = query.unwrap(); - if is_http_trigger { + if include_all_query { + let queries = + serde_urlencoded::from_str::>(&query).unwrap_or_default(); + queries + .into_iter() + .map(|(k, v)| (k, to_raw_value(&v))) + .collect() + } else { + let parse_query_args = include_query + .map(|s| s.split(",").map(|p| p.to_string()).collect::>()) + .unwrap_or_default(); + let mut args = HashMap::new(); + if !parse_query_args.is_empty() { let queries = - serde_urlencoded::from_str::>(query).unwrap_or_default(); - Some(DecodeQueries( - queries - .into_iter() - .map(|(k, v)| (k, to_raw_value(&v))) - .collect(), - )) - } else { - let include_query = serde_urlencoded::from_str::(query) - .map(|x| x.include_query) - .ok() - .flatten() - .unwrap_or_default(); - let parse_query_args = include_query - .split(",") - .map(|s| s.to_string()) - .collect::>(); - let mut args = HashMap::new(); - if !parse_query_args.is_empty() { - let queries = serde_urlencoded::from_str::>(query) - .unwrap_or_default(); - parse_query_args.iter().for_each(|h| { - if let Some(v) = queries.get(h) { - args.insert(h.to_string(), to_raw_value(v)); - } - }); - } - Some(DecodeQueries(args)) + serde_urlencoded::from_str::>(&query).unwrap_or_default(); + parse_query_args.iter().for_each(|h| { + if let Some(v) = queries.get(h) { + args.insert(h.to_string(), to_raw_value(v)); + } + }); } + args } } -// impl<'c> PushArgs<'c> { -// pub fn insert, V: Into>>(&mut self, k: K, v: V) { -// self.extra.insert(k.into(), v.into()); -// } -// } - fn restructure_cloudevents_metadata( mut p: HashMap>, ) -> Result>, Error> { diff --git a/backend/windmill-api/src/capture.rs b/backend/windmill-api/src/capture.rs index 3283dea123..bcc287ec04 100644 --- a/backend/windmill-api/src/capture.rs +++ b/backend/windmill-api/src/capture.rs @@ -398,7 +398,7 @@ async fn set_gcp_trigger_config( gcp_config.create_update, false, capture_config.is_flow, - gcp_config.ack_deadline + gcp_config.ack_deadline, ) .await?; gcp_config.create_update = Some(config); @@ -966,6 +966,8 @@ async fn http_payload( Path((w_id, runnable_kind, path, route_path)): Path<(String, RunnableKind, String, StripPath)>, args: RawHttpTriggerArgs, ) -> std::result::Result { + use crate::args::{build_headers, build_query}; + let path = path.replace(".", "/"); let is_flow = matches!(runnable_kind, RunnableKind::Flow); let route_path = route_path.to_path(); @@ -1002,9 +1004,18 @@ async fn http_payload( .map(|(k, v)| (k.to_string(), v.to_string())) .collect(); + let headers = build_headers(&args.0.metadata.headers, None, true); + let query = build_query(args.0.metadata.query.as_deref(), None, true); + let preprocessor_args = args .clone() - .to_v2_preprocessor_args(&http_trigger_config.route_path, &route_path, ¶ms) + .to_v2_preprocessor_args( + &http_trigger_config.route_path, + &route_path, + ¶ms, + headers, + query, + ) .map_err(|e| e.into_response())?; let main_args = args diff --git a/backend/windmill-api/src/triggers/http/http_trigger_args.rs b/backend/windmill-api/src/triggers/http/http_trigger_args.rs index 8fb96d42f0..af829cec53 100644 --- a/backend/windmill-api/src/triggers/http/http_trigger_args.rs +++ b/backend/windmill-api/src/triggers/http/http_trigger_args.rs @@ -15,7 +15,10 @@ use windmill_common::{ use windmill_queue::PushArgsOwned; use crate::{ - args::{try_from_request_body, Body, RawWebhookArgs, WebhookArgs, WebhookArgsMetadata}, + args::{ + build_headers, build_query, try_from_request_body, Body, RawWebhookArgs, WebhookArgs, + WebhookArgsMetadata, + }, db::ApiAuthed, }; @@ -102,8 +105,8 @@ struct HttpTriggerWmTrigger<'a> { route: &'a str, path: &'a str, params: &'a HashMap, - query: &'a HashMap>, - headers: &'a HashMap>, + query: HashMap>, + headers: HashMap>, method: HttpMethod, } @@ -142,14 +145,22 @@ impl HttpTriggerArgs { format: RunnableFormat, wrap_body: bool, ) -> Result { + let headers = build_headers(&self.0.metadata.headers, None, true); + let query = build_query(self.0.metadata.query.as_deref(), None, true); match format { RunnableFormat { has_preprocessor: true, version: RunnableFormatVersion::V2 } => { // we don't care about wrap_body in v2 - self.to_v2_preprocessor_args(route_path, called_path, params) - } - RunnableFormat { has_preprocessor: true, version: RunnableFormatVersion::V1 } => { - self.to_v1_preprocessor_args(route_path, called_path, params, wrap_body) + self.to_v2_preprocessor_args(route_path, called_path, params, headers, query) } + RunnableFormat { has_preprocessor: true, version: RunnableFormatVersion::V1 } => self + .to_v1_preprocessor_args( + route_path, + called_path, + params, + wrap_body, + headers, + query, + ), RunnableFormat { has_preprocessor: false, .. } => self.to_main_args(wrap_body), } } @@ -160,6 +171,8 @@ impl HttpTriggerArgs { called_path: &str, params: &HashMap, wrap_body: bool, + headers: HashMap>, + query: HashMap>, ) -> Result { let mut extra = HashMap::new(); let mut wm_trigger = HashMap::new(); @@ -171,8 +184,8 @@ impl HttpTriggerArgs { path: called_path, method: (&self.0.metadata.method).try_into()?, params, - query: &self.0.metadata.query, - headers: &self.0.metadata.headers, + query, + headers, }), ); extra.insert("wm_trigger".to_string(), to_raw_value(&wm_trigger)); @@ -189,6 +202,8 @@ impl HttpTriggerArgs { route_path: &str, called_path: &str, params: &HashMap, + headers: HashMap>, + query: HashMap>, ) -> Result { let mut args = HashMap::new(); args.insert( @@ -197,8 +212,8 @@ impl HttpTriggerArgs { kind: "http".to_string(), body: to_raw_value(&self.0.body), raw_string: self.0.metadata.raw_string, - headers: self.0.metadata.headers, - query: self.0.metadata.query, + headers, + query, method: (&self.0.metadata.method).try_into()?, route: route_path, path: called_path, diff --git a/backend/windmill-common/src/scripts.rs b/backend/windmill-common/src/scripts.rs index b0e771d138..b6a4fd3391 100644 --- a/backend/windmill-common/src/scripts.rs +++ b/backend/windmill-common/src/scripts.rs @@ -799,14 +799,14 @@ pub async fn clone_script<'c>( draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, \ dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, \ delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, \ - codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets) + codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets, debounce_key, debounce_delay_s) SELECT workspace_id, $1, path, array_prepend($2::bigint, COALESCE(parent_hashes, '{}'::bigint[])), summary, description, \ content, created_by, schema, is_template, extra_perms, NULL, language, kind, tag, \ draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, \ dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, \ delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, \ - codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets + codebase, has_preprocessor, on_behalf_of_email, schema_validation, assets, debounce_key, debounce_delay_s FROM script WHERE hash = $2 AND workspace_id = $3; ", new_hash, base_hash.0, w_id).execute(&mut **tx).await?; diff --git a/backend/windmill-common/src/worker.rs b/backend/windmill-common/src/worker.rs index 2a346ea2b3..52413d38f8 100644 --- a/backend/windmill-common/src/worker.rs +++ b/backend/windmill-common/src/worker.rs @@ -409,6 +409,10 @@ fn format_pull_query(peek: String) -> String { raw_flow, script_entrypoint_override, preprocessed FROM v2_job WHERE id = (SELECT id FROM peek) + ), delete_debounce AS NOT MATERIALIZED ( + DELETE FROM debounce_key + USING j + WHERE j.kind::text != 'flowdependencies' AND j.kind::text != 'appdependencies' AND j.kind::text != 'dependencies' AND debounce_key.job_id = j.id ) SELECT j.id, j.workspace_id, j.parent_job, j.created_by, started_at, scheduled_for, j.runnable_id, j.runnable_path, j.args, canceled_by, canceled_reason, j.kind, j.trigger, j.trigger_kind, j.permissioned_as, @@ -426,7 +430,7 @@ fn format_pull_query(peek: String) -> String { ", peek ); - tracing::debug!("pull query: {}", r); + // tracing::debug!("pull query: {}", r); r } diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 6112045b73..299c0231d9 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -1140,13 +1140,13 @@ async fn commit_completed_job( .unwrap_or(false); if schedule_next_tick { - if let Err(err) = handle_maybe_scheduled_job( + if let Err(err) = Box::pin(handle_maybe_scheduled_job( db, queued_job, &schedule, &script_path, &queued_job.workspace_id, - ) + )) .await { match err { @@ -2428,7 +2428,7 @@ pub async fn pull( #[cfg(not(feature = "enterprise"))] let has_concurent_limit = false - || (job.is_dependency() && cfg!(feature = "private") && !*WMDEBUG_NO_DJOB_DEBOUNCING); + || (job.is_dependency() && job.concurrent_limit.is_some() && cfg!(feature = "private") && !*WMDEBUG_NO_DJOB_DEBOUNCING); // if we don't have private flag, we don't have concurrency limit // concurrency check. If more than X jobs for this path are already running, we re-queue and pull another job from the queue @@ -3622,8 +3622,8 @@ pub async fn push<'c, 'd>( cache_ttl, dedicated_worker, _low_level_priority, - mut custom_debounce_key, - mut debounce_delay_s, + custom_debounce_key, + debounce_delay_s, ) = match job_payload { JobPayload::ScriptHash { hash, @@ -4391,14 +4391,6 @@ pub async fn push<'c, 'd>( ), }; - if custom_debounce_key.is_some() { - tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_key"); - custom_debounce_key = None; - } - if debounce_delay_s.is_some() { - tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_delay_s"); - debounce_delay_s = None; - } // Enforce concurrency limit on all dependency jobs. // TODO: We can ignore this for scripts djobs. The main reason we need all djobs to be sequential is because we have // nodes_to_relock and we need all locks whose corresponding steps aren't in nodes_to_relock be already present. diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 7266ead92d..7ae80a97b6 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -546,6 +546,7 @@ pub async fn handle_python_job( precomputed_agent_info: Option, has_stream: &mut bool, ) -> windmill_common::error::Result> { + let script_path = crate::common::use_flow_root_path(job.runnable_path()); let annotations = PythonAnnotations::parse(inner_content); @@ -1181,13 +1182,13 @@ async fn handle_python_deps( let (v, requirements_lines, error_hint) = match conn { Connection::Sql(db) => { let mut version_specifiers = vec![]; - let (r, h) = windmill_parser_py_imports::parse_python_imports( + let (r, h) = Box::pin(windmill_parser_py_imports::parse_python_imports( inner_content, w_id, script_path, db, &mut version_specifiers, - ) + )) .await?; let v = PyV::resolve( diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 5fe2ffac68..0e6da36a20 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -954,6 +954,8 @@ pub async fn run_worker( killpill_tx: KillpillSender, base_internal_url: &str, ) { + + #[cfg(not(feature = "enterprise"))] if !*DISABLE_NSJAIL { tracing::warn!( @@ -1542,13 +1544,15 @@ pub async fn run_worker( Ok(_) | Err(broadcast::error::TryRecvError::Closed) => true, _ => false, } { - if !killed_but_draining_same_worker_jobs && job_completed_tx.is_sql() { + if !killed_but_draining_same_worker_jobs { killed_but_draining_same_worker_jobs = true; - tracing::info!(worker = %worker_name, hostname = %hostname, "killpill received in worker main loop, sending killpill job"); - job_completed_tx - .kill() - .await - .expect("send kill to job completed tx"); + if job_completed_tx.is_sql() { + tracing::info!(worker = %worker_name, hostname = %hostname, "killpill received in worker main loop, sending killpill job"); + job_completed_tx + .kill() + .await + .expect("send kill to job completed tx"); + } } continue; } else if killed_but_draining_same_worker_jobs { @@ -2360,292 +2364,250 @@ pub async fn handle_queued_job( precomputed_agent_info: Option, #[cfg(feature = "benchmark")] _bench: &mut BenchmarkIter, ) -> windmill_common::error::Result { - return Box::pin(async move { - // Extract the active span from the context - if job.canceled_by.is_some() { - return Err(Error::JsonErr(canceled_job_to_result(&job))); - } - if let Some(e) = &job.pre_run_error { - return Err(Error::ExecutionErr(e.to_string())); - } + // Extract the active span from the context - #[cfg(any(not(feature = "enterprise"), feature = "sqlx"))] - match conn { - Connection::Sql(db) => { - if job.parent_job.is_none() && job.created_by.starts_with("email-") { - let daily_count = sqlx::query!( - "SELECT value FROM metrics WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day' ORDER BY created_at DESC LIMIT 1" - ).fetch_optional(db) - .warn_after_seconds(5) - .await?.map(|x| serde_json::from_value::(x.value).unwrap_or(1)); + if job.canceled_by.is_some() { + return Err(Error::JsonErr(canceled_job_to_result(&job))); + } + if let Some(e) = &job.pre_run_error { + return Err(Error::ExecutionErr(e.to_string())); + } - if let Some(count) = daily_count { - if count >= 100 { - return Err(error::Error::QuotaExceeded(format!( - "Email trigger usage limit of 100 per day has been reached." - ))); - } else { - sqlx::query!( - "UPDATE metrics SET value = $1 WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day'", - serde_json::json!(count + 1) - ) - .execute(db) - .warn_after_seconds(5) - .await?; - } + #[cfg(any(not(feature = "enterprise"), feature = "sqlx"))] + match conn { + Connection::Sql(db) => { + if job.parent_job.is_none() && job.created_by.starts_with("email-") { + let daily_count = sqlx::query!( + "SELECT value FROM metrics WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day' ORDER BY created_at DESC LIMIT 1" + ).fetch_optional(db) + .warn_after_seconds(5) + .await?.map(|x| serde_json::from_value::(x.value).unwrap_or(1)); + + if let Some(count) = daily_count { + if count >= 100 { + return Err(error::Error::QuotaExceeded(format!( + "Email trigger usage limit of 100 per day has been reached." + ))); } else { sqlx::query!( - "INSERT INTO metrics (id, value) VALUES ('email_trigger_usage', to_jsonb(1))" + "UPDATE metrics SET value = $1 WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day'", + serde_json::json!(count + 1) ) - .execute(db) - .warn_after_seconds(5) - .await?; + .execute(db) + .warn_after_seconds(5) + .await?; } - } - } - Connection::Http(_) => { - return Err(Error::internal_err(format!( - "Could not check email trigger usage for job with agent worker {}", - job.id - ))) - } - } - - // no need to mark job as started if http conn, it's done by the server when pulled - if let Connection::Sql(db) = conn { - job.mark_as_started_if_step(db).await?; - } - - let started = Instant::now(); - // Pre-fetch preview jobs raw values if necessary. - // The `raw_*` values passed to this function are the original raw values from `queue` tables, - // they are kept for backward compatibility as they have been moved to the `job` table. - let preview_data = match (job.kind, job.runnable_id) { - ( - JobKind::Preview - | JobKind::Dependencies - | JobKind::FlowPreview - | JobKind::Flow - | JobKind::FlowDependencies - | JobKind::SingleStepFlow, - x, - ) => { - if x.map(|x| x.0).is_none_or(|x| is_special_codebase_hash(x)) { - Some( - cache::job::fetch_preview( - conn, - &job.id, - raw_lock, - raw_code, - raw_flow.clone(), - ) - .await?, - ) } else { - None + sqlx::query!( + "INSERT INTO metrics (id, value) VALUES ('email_trigger_usage', to_jsonb(1))" + ) + .execute(db) + .warn_after_seconds(5) + .await?; } } - _ => None, - }; - - let cached_res_path = if job.cache_ttl.is_some() { - match conn { - Connection::Sql(db) => { - Some(cached_result_path(db, &client, &job, preview_data.as_ref()).await) - } - Connection::Http(_) => None, - } - } else { - None - }; - - if let Some(db) = conn.as_sql() { - if let Some(cached_res_path) = cached_res_path.as_ref() { - let cached_result_maybe = get_cached_resource_value_if_valid( - db, - &client, - &job.id, - &job.workspace_id, - &cached_res_path, - ) - .warn_after_seconds(5) - .await; - if let Some(result) = cached_result_maybe { - { - let logs = "Job skipped because args & path found in cache and not expired" - .to_string(); - append_logs(&job.id, &job.workspace_id, logs, conn).await; - } - let result = job_completed_tx - .send_job( - JobCompleted { - preprocessed_args: None, - job, - result, - result_columns: None, - mem_peak: 0, - canceled_by: None, - success: true, - cached_res_path: None, - token: client.token.clone(), - duration: None, - has_stream: Some(false), - from_cache: Some(true), - }, - true, - ) - .await; - - match result { - Ok(_) => { - tracing::debug!("Send job completed") - } - Err(err) => { - tracing::error!( - "An error occurred while sending job completed: {:#?}", - err - ) - } - } - - return Ok(true); - } - }; } - if job.is_flow() { - if let Some(db) = conn.as_sql() { - let flow_data = match preview_data { - Some(RawData::Flow(data)) => data, - // Not a preview: fetch from the cache or the database. - _ => cache::job::fetch_flow(db, &job.kind, job.runnable_id).await?, - }; - handle_flow( - job, - &flow_data, - db, - &client, - None, - &same_worker_tx.expect(SAME_WORKER_REQUIREMENTS), - worker_dir, - job_completed_tx.clone(), - worker_name, - ) - .warn_after_seconds(10) - .await?; - Ok(true) - } else { - return Err(Error::internal_err( - "Could not handle flow job with agent worker".to_string(), - )); - } - } else { - let mut logs = "".to_string(); - let mut mem_peak: i32 = 0; - let mut canceled_by: Option = None; - // println!("handle queue {:?}", SystemTime::now()); - - logs.push_str(&format!( - "job={} {}={} worker={} hostname={}\n", - &job.id, *LOG_TAG_NAME, &job.tag, &worker_name, &hostname - )); - - if *NO_LOGS_AT_ALL { - logs.push_str("Logs are fully disabled for this worker\n"); - } - - if *NO_LOGS { - logs.push_str("Logs are disabled for this worker\n"); - } - - if *SLOW_LOGS { - logs.push_str("Logs are 10x less frequent for this worker\n"); - } - - #[cfg(not(feature = "enterprise"))] - if job.concurrent_limit.is_some() { - logs.push_str("---\n"); - logs.push_str("WARNING: This job has concurrency limits enabled. Concurrency limits are an EE feature and the setting is ignored.\n"); - logs.push_str("---\n"); - } - - // Only used for testing in tests/relative_imports.rs - // Give us some space to work with. - #[cfg(debug_assertions)] - if let Some(dbg_djob_sleep) = job - .args - .as_ref() - .map(|x| { - x.get("dbg_djob_sleep") - .map(|v| serde_json::from_str::(v.get()).ok()) - .flatten() - }) - .flatten() - { - tracing::debug!("Debug: {} going to sleep for {}", job.id, dbg_djob_sleep); - sleep(std::time::Duration::from_secs(dbg_djob_sleep as u64)).await; - } - - tracing::debug!( - workspace_id = %job.workspace_id, - "handling job {}", + Connection::Http(_) => { + return Err(Error::internal_err(format!( + "Could not check email trigger usage for job with agent worker {}", job.id - ); - append_logs(&job.id, &job.workspace_id, logs, conn).await; + ))) + } + } - let mut column_order: Option> = None; - let mut new_args: Option>> = None; - let mut has_stream = false; - let result = match job.kind { - JobKind::Dependencies => match conn { - Connection::Sql(db) => { - handle_dependency_job( - &job, - preview_data.as_ref(), - &mut mem_peak, - &mut canceled_by, - job_dir, - db, - worker_name, - worker_dir, - base_internal_url, - &client.token, - occupancy_metrics, + // no need to mark job as started if http conn, it's done by the server when pulled + if let Connection::Sql(db) = conn { + job.mark_as_started_if_step(db).await?; + } + + let started = Instant::now(); + // Pre-fetch preview jobs raw values if necessary. + // The `raw_*` values passed to this function are the original raw values from `queue` tables, + // they are kept for backward compatibility as they have been moved to the `job` table. + let preview_data = match (job.kind, job.runnable_id) { + ( + JobKind::Preview + | JobKind::Dependencies + | JobKind::FlowPreview + | JobKind::Flow + | JobKind::FlowDependencies + | JobKind::SingleStepFlow, + x, + ) => { + if x.map(|x| x.0).is_none_or(|x| is_special_codebase_hash(x)) { + Some( + cache::job::fetch_preview( + conn, + &job.id, + raw_lock, + raw_code, + raw_flow.clone(), + ) + .await?, + ) + } else { + None + } + } + _ => None, + }; + + let cached_res_path = if job.cache_ttl.is_some() { + match conn { + Connection::Sql(db) => { + Some(cached_result_path(db, &client, &job, preview_data.as_ref()).await) + } + Connection::Http(_) => None, + } + } else { + None + }; + + if let Some(db) = conn.as_sql() { + if let Some(cached_res_path) = cached_res_path.as_ref() { + let cached_result_maybe = get_cached_resource_value_if_valid( + db, + &client, + &job.id, + &job.workspace_id, + &cached_res_path, + ) + .warn_after_seconds(5) + .await; + if let Some(result) = cached_result_maybe { + { + let logs = "Job skipped because args & path found in cache and not expired" + .to_string(); + append_logs(&job.id, &job.workspace_id, logs, conn).await; + } + let result = job_completed_tx + .send_job( + JobCompleted { + preprocessed_args: None, + job, + result, + result_columns: None, + mem_peak: 0, + canceled_by: None, + success: true, + cached_res_path: None, + token: client.token.clone(), + duration: None, + has_stream: Some(false), + from_cache: Some(true), + }, + true, + ) + .await; + + match result { + Ok(_) => { + tracing::debug!("Send job completed") + } + Err(err) => { + tracing::error!( + "An error occurred while sending job completed: {:#?}", + err ) - .await } - Connection::Http(_) => { - return Err(Error::internal_err( - "Could not handle dependency job with agent worker".to_string(), - )); - } - }, - JobKind::FlowDependencies => match conn { - Connection::Sql(db) => { - handle_flow_dependency_job( - (*job).clone(), - preview_data.as_ref(), - &mut mem_peak, - &mut canceled_by, - job_dir, - db, - worker_name, - worker_dir, - base_internal_url, - &client.token, - occupancy_metrics, - ) - .await - } - Connection::Http(_) => { - return Err(Error::internal_err( - "Could not handle flow dependency job with agent worker".to_string(), - )); - } - }, - JobKind::AppDependencies => match conn { - Connection::Sql(db) => handle_app_dependency_job( - (*job).clone(), + } + + return Ok(true); + } + }; + } + if job.is_flow() { + if let Some(db) = conn.as_sql() { + let flow_data = match preview_data { + Some(RawData::Flow(data)) => data, + // Not a preview: fetch from the cache or the database. + _ => cache::job::fetch_flow(db, &job.kind, job.runnable_id).await?, + }; + Box::pin(handle_flow( + job, + &flow_data, + db, + &client, + None, + &same_worker_tx.expect(SAME_WORKER_REQUIREMENTS), + worker_dir, + job_completed_tx.clone(), + worker_name, + )) + .warn_after_seconds(10) + .await?; + Ok(true) + } else { + return Err(Error::internal_err( + "Could not handle flow job with agent worker".to_string(), + )); + } + } else { + + let mut logs = "".to_string(); + let mut mem_peak: i32 = 0; + let mut canceled_by: Option = None; + // println!("handle queue {:?}", SystemTime::now()); + + logs.push_str(&format!( + "job={} {}={} worker={} hostname={}\n", + &job.id, *LOG_TAG_NAME, &job.tag, &worker_name, &hostname + )); + + if *NO_LOGS_AT_ALL { + logs.push_str("Logs are fully disabled for this worker\n"); + } + + if *NO_LOGS { + logs.push_str("Logs are disabled for this worker\n"); + } + + if *SLOW_LOGS { + logs.push_str("Logs are 10x less frequent for this worker\n"); + } + + #[cfg(not(feature = "enterprise"))] + if job.concurrent_limit.is_some() { + logs.push_str("---\n"); + logs.push_str("WARNING: This job has concurrency limits enabled. Concurrency limits are an EE feature and the setting is ignored.\n"); + logs.push_str("---\n"); + } + + // Only used for testing in tests/relative_imports.rs + // Give us some space to work with. + #[cfg(debug_assertions)] + if let Some(dbg_djob_sleep) = job + .args + .as_ref() + .map(|x| { + x.get("dbg_djob_sleep") + .map(|v| serde_json::from_str::(v.get()).ok()) + .flatten() + }) + .flatten() + { + tracing::debug!("Debug: {} going to sleep for {}", job.id, dbg_djob_sleep); + sleep(std::time::Duration::from_secs(dbg_djob_sleep as u64)).await; + } + + tracing::debug!( + workspace_id = %job.workspace_id, + "handling job {}", + job.id + ); + append_logs(&job.id, &job.workspace_id, logs, conn).await; + + let mut column_order: Option> = None; + let mut new_args: Option>> = None; + let mut has_stream = false; + // Box::pin all async branches to prevent large match enum on stack + let result = match job.kind { + JobKind::Dependencies => match conn { + Connection::Sql(db) => { + Box::pin(handle_dependency_job( + &job, + preview_data.as_ref(), &mut mem_peak, &mut canceled_by, job_dir, @@ -2655,109 +2617,156 @@ pub async fn handle_queued_job( base_internal_url, &client.token, occupancy_metrics, - ) + )) .await - .map(|()| serde_json::from_str("{}").unwrap()), - Connection::Http(_) => { - return Err(Error::internal_err( - "Could not handle app dependency job with agent worker".to_string(), - )); - } - }, - JobKind::Identity => Ok(job - .args - .as_ref() - .map(|x| x.get("previous_result")) - .flatten() - .map(|x| x.to_owned()) - .unwrap_or_else(|| serde_json::from_str("{}").unwrap())), - JobKind::AIAgent => match conn { - Connection::Sql(db) => { - handle_ai_agent_job( - conn, - db, - job.as_ref(), - &client, - &mut canceled_by, - &mut mem_peak, - &mut *occupancy_metrics, - &job_completed_tx, - worker_dir, - base_internal_url, - worker_name, - hostname, - killpill_rx, - &mut has_stream, - ) - .await - } - Connection::Http(_) => { - return Err(Error::internal_err( - "Agent worker does not support ai agent jobs".to_string(), - )); - } - }, - _ => { - let metric_timer = Instant::now(); - let preview_data = preview_data.and_then(|data| match data { - RawData::Script(data) => Some(data), - _ => None, - }); - let r = handle_code_execution_job( - job.as_ref(), - preview_data, - conn, - client, - parent_runnable_path, - job_dir, - worker_dir, + } + Connection::Http(_) => { + return Err(Error::internal_err( + "Could not handle dependency job with agent worker".to_string(), + )); + } + }, + JobKind::FlowDependencies => match conn { + Connection::Sql(db) => { + Box::pin(handle_flow_dependency_job( + (*job).clone(), + preview_data.as_ref(), &mut mem_peak, &mut canceled_by, + job_dir, + db, + worker_name, + worker_dir, + base_internal_url, + &client.token, + occupancy_metrics, + )) + .await + } + Connection::Http(_) => { + return Err(Error::internal_err( + "Could not handle flow dependency job with agent worker".to_string(), + )); + } + }, + JobKind::AppDependencies => match conn { + Connection::Sql(db) => Box::pin(handle_app_dependency_job( + (*job).clone(), + &mut mem_peak, + &mut canceled_by, + job_dir, + db, + worker_name, + worker_dir, + base_internal_url, + &client.token, + occupancy_metrics, + )) + .await + .map(|()| serde_json::from_str("{}").unwrap()), + Connection::Http(_) => { + return Err(Error::internal_err( + "Could not handle app dependency job with agent worker".to_string(), + )); + } + }, + JobKind::Identity => Ok(job + .args + .as_ref() + .map(|x| x.get("previous_result")) + .flatten() + .map(|x| x.to_owned()) + .unwrap_or_else(|| serde_json::from_str("{}").unwrap())), + JobKind::AIAgent => match conn { + Connection::Sql(db) => { + Box::pin(handle_ai_agent_job( + conn, + db, + job.as_ref(), + &client, + &mut canceled_by, + &mut mem_peak, + &mut *occupancy_metrics, + &job_completed_tx, + worker_dir, base_internal_url, worker_name, - &mut column_order, - &mut new_args, - occupancy_metrics, + hostname, killpill_rx, - precomputed_agent_info, &mut has_stream, - ) - .await; - occupancy_metrics.total_duration_of_running_jobs += - metric_timer.elapsed().as_secs_f32(); - r + )) + .await } - }; + Connection::Http(_) => { + return Err(Error::internal_err( + "Agent worker does not support ai agent jobs".to_string(), + )); + } + }, + _ => { + let metric_timer = Instant::now(); + let preview_data = preview_data.and_then(|data| match data { + RawData::Script(data) => Some(data), + _ => None, + }); - //it's a test job, no need to update the db - if job.as_ref().workspace_id == "" { - return Ok(true); - } + // Box::pin to move large future to heap + let r = Box::pin(handle_code_execution_job( + job.as_ref(), + preview_data, + conn, + client, + parent_runnable_path, + job_dir, + worker_dir, + &mut mem_peak, + &mut canceled_by, + base_internal_url, + worker_name, + &mut column_order, + &mut new_args, + occupancy_metrics, + killpill_rx, + precomputed_agent_info, + &mut has_stream, + )).await; - if result - .as_ref() - .is_err_and(|err| matches!(err, &Error::AlreadyCompleted(_))) - { - return Ok(false); + occupancy_metrics.total_duration_of_running_jobs += + metric_timer.elapsed().as_secs_f32(); + r } - process_result( - job, - result.map(|x| Arc::new(x)), - job_dir, - job_completed_tx, - mem_peak, - canceled_by, - cached_res_path, - &client.token, - column_order, - new_args, - conn, - Some(started.elapsed().as_millis() as i64), - has_stream, - ) - .await + }; + + //it's a test job, no need to update the db + if job.as_ref().workspace_id == "" { + return Ok(true); } - }).await; + + if result + .as_ref() + .is_err_and(|err| matches!(err, &Error::AlreadyCompleted(_))) + { + return Ok(false); + } + process_result( + job, + result.map(|x| Arc::new(x)), + job_dir, + job_completed_tx, + mem_peak, + canceled_by, + cached_res_path, + &client.token, + column_order, + new_args, + conn, + Some(started.elapsed().as_millis() as i64), + has_stream, + ) + .await + } + + } pub fn build_envs( @@ -2944,16 +2953,20 @@ async fn handle_code_execution_job( precomputed_agent_info: Option, has_stream: &mut bool, ) -> error::Result> { + let script_hash = || { job.runnable_id .ok_or_else(|| Error::internal_err("expected script hash")) }; + let (arc_data, arc_metadata, data, metadata): ( Arc, Arc, ScriptData, ScriptMetadata, ); + + // Box::pin the script fetching match to prevent large enum on stack let ( ScriptData { code, lock }, ScriptMetadata { language, envs, codebase, schema_validator, schema }, @@ -2964,7 +2977,7 @@ async fn handle_code_execution_job( .and_then(|x| hash_to_codebase_id(&job.id.to_string(), x.0)); if codebase.is_none() && job.runnable_id.is_some() { (arc_data, arc_metadata) = - cache::script::fetch(conn, job.runnable_id.unwrap()).await?; + Box::pin(cache::script::fetch(conn, job.runnable_id.unwrap())).await?; (arc_data.as_ref(), arc_metadata.as_ref()) } else { arc_data = @@ -2981,7 +2994,7 @@ async fn handle_code_execution_job( } JobKind::Script_Hub => { let ContentReqLangEnvs { content, lockfile, language, envs, codebase, schema } = - get_hub_script_content_and_requirements(job.runnable_path.as_ref(), conn.as_sql()) + Box::pin(get_hub_script_content_and_requirements(job.runnable_path.as_ref(), conn.as_sql())) .await?; data = ScriptData { code: content, lock: lockfile }; @@ -2989,11 +3002,11 @@ async fn handle_code_execution_job( (&data, &metadata) } JobKind::Script => { - (arc_data, arc_metadata) = cache::script::fetch(conn, script_hash()?).await?; + (arc_data, arc_metadata) = Box::pin(cache::script::fetch(conn, script_hash()?)).await?; (arc_data.as_ref(), arc_metadata.as_ref()) } JobKind::FlowScript => { - arc_data = cache::flow::fetch_script(conn, FlowNodeId(script_hash()?.0)).await?; + arc_data = Box::pin(cache::flow::fetch_script(conn, FlowNodeId(script_hash()?.0))).await?; metadata = ScriptMetadata { language: job.script_lang, envs: None, @@ -3004,7 +3017,7 @@ async fn handle_code_execution_job( (arc_data.as_ref(), &metadata) } JobKind::AppScript => { - arc_data = cache::app::fetch_script(conn, AppScriptId(script_hash()?.0)).await?; + arc_data = Box::pin(cache::app::fetch_script(conn, AppScriptId(script_hash()?.0))).await?; metadata = ScriptMetadata { language: job.script_lang, envs: None, @@ -3022,7 +3035,7 @@ async fn handle_code_execution_job( .ok_or_else(|| Error::internal_err("expected script path".to_string()))?; if script_path.starts_with("hub/") { let ContentReqLangEnvs { content, lockfile, language, envs, codebase, schema } = - get_hub_script_content_and_requirements(Some(script_path), conn.as_sql()) + Box::pin(get_hub_script_content_and_requirements(Some(script_path), conn.as_sql())) .await?; data = ScriptData { code: content, lock: lockfile }; metadata = @@ -3039,7 +3052,7 @@ async fn handle_code_execution_job( .await? .ok_or_else(|| Error::internal_err("expected script hash".to_string()))?; - (arc_data, arc_metadata) = cache::script::fetch(conn, ScriptHash(hash)).await?; + (arc_data, arc_metadata) = Box::pin(cache::script::fetch(conn, ScriptHash(hash))).await?; (arc_data.as_ref(), arc_metadata.as_ref()) } } @@ -3329,6 +3342,7 @@ mount {{ let envs = build_envs(envs.as_ref())?; + // Box::pin all language handlers to prevent large match enum on stack let result: error::Result> = match language { None => { return Err(Error::ExecutionErr( @@ -3342,7 +3356,7 @@ mount {{ )); #[cfg(feature = "python")] - handle_python_job( + Box::pin(handle_python_job( lock.as_ref(), job_dir, worker_dir, @@ -3361,11 +3375,11 @@ mount {{ occupancy_metrics, precomputed_agent_info, has_stream, - ) + )) .await } Some(ScriptLang::Deno) => { - handle_deno_job( + Box::pin(handle_deno_job( lock.as_ref(), mem_peak, canceled_by, @@ -3381,11 +3395,11 @@ mount {{ new_args, occupancy_metrics, has_stream, - ) + )) .await } Some(ScriptLang::Bun) | Some(ScriptLang::Bunnative) => { - handle_bun_job( + Box::pin(handle_bun_job( lock.as_ref(), codebase.as_ref(), mem_peak, @@ -3404,11 +3418,11 @@ mount {{ occupancy_metrics, precomputed_agent_info, has_stream, - ) + )) .await } Some(ScriptLang::Go) => { - handle_go_job( + Box::pin(handle_go_job( mem_peak, canceled_by, job, @@ -3423,11 +3437,11 @@ mount {{ worker_name, envs, occupancy_metrics, - ) + )) .await } Some(ScriptLang::Bash) => { - handle_bash_job( + Box::pin(handle_bash_job( mem_peak, canceled_by, job, @@ -3442,11 +3456,11 @@ mount {{ envs, occupancy_metrics, killpill_rx, - ) + )) .await } Some(ScriptLang::Powershell) => { - handle_powershell_job( + Box::pin(handle_powershell_job( mem_peak, canceled_by, job, @@ -3460,7 +3474,7 @@ mount {{ worker_name, envs, occupancy_metrics, - ) + )) .await } Some(ScriptLang::Php) => { @@ -3470,7 +3484,7 @@ mount {{ )); #[cfg(feature = "php")] - handle_php_job( + Box::pin(handle_php_job( lock.as_ref(), mem_peak, canceled_by, @@ -3485,7 +3499,7 @@ mount {{ envs, &shared_mount, occupancy_metrics, - ) + )) .await } Some(ScriptLang::Rust) => { @@ -3495,7 +3509,7 @@ mount {{ )); #[cfg(feature = "rust")] - handle_rust_job( + Box::pin(handle_rust_job( mem_peak, canceled_by, job, @@ -3510,7 +3524,7 @@ mount {{ worker_name, envs, occupancy_metrics, - ) + )) .await } Some(ScriptLang::Ansible) => { @@ -3520,7 +3534,7 @@ mount {{ )); #[cfg(feature = "python")] - handle_ansible_job( + Box::pin(handle_ansible_job( lock.as_ref(), job_dir, worker_dir, @@ -3536,11 +3550,11 @@ mount {{ base_internal_url, envs, occupancy_metrics, - ) + )) .await } Some(ScriptLang::CSharp) => { - handle_csharp_job( + Box::pin(handle_csharp_job( mem_peak, canceled_by, job, @@ -3555,7 +3569,7 @@ mount {{ worker_name, envs, occupancy_metrics, - ) + )) .await } Some(ScriptLang::Nu) => { @@ -3565,7 +3579,7 @@ mount {{ ); #[cfg(feature = "nu")] - handle_nu_job(JobHandlerInputNu { + Box::pin(handle_nu_job(JobHandlerInputNu { mem_peak, canceled_by, job, @@ -3580,7 +3594,7 @@ mount {{ worker_name, envs, occupancy_metrics, - }) + })) .await } Some(ScriptLang::Java) => { @@ -3591,7 +3605,7 @@ mount {{ .into()); #[cfg(feature = "java")] - handle_java_job(JobHandlerInputJava { + Box::pin(handle_java_job(JobHandlerInputJava { mem_peak, canceled_by, job, @@ -3606,7 +3620,7 @@ mount {{ worker_name, envs, occupancy_metrics, - }) + })) .await } Some(ScriptLang::Ruby) => { @@ -3617,7 +3631,7 @@ mount {{ .into()); #[cfg(feature = "ruby")] - handle_ruby_job(JobHandlerInputRuby { + Box::pin(handle_ruby_job(JobHandlerInputRuby { mem_peak, canceled_by, job, @@ -3632,7 +3646,7 @@ mount {{ worker_name, envs, occupancy_metrics, - }) + })) .await } // for related places search: ADD_NEW_LANG diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index 850ae46c17..662c947842 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -104,7 +104,7 @@ pub async fn update_flow_status_after_job_completion( let mut unrecoverable = unrecoverable; loop { potentially_crash_for_testing(); - let nrec = match update_flow_status_after_job_completion_internal( + let nrec = match Box::pin(update_flow_status_after_job_completion_internal( db, client, rec.flow, @@ -122,13 +122,13 @@ pub async fn update_flow_status_after_job_completion( job_completed_tx.clone(), #[cfg(feature = "benchmark")] bench, - ) + )) .await { Ok(j) => j, Err(e) => { tracing::error!("Error while updating flow status of {} after completion of {}, updating flow status again with error: {e:#}", rec.flow, &rec.job_id_for_status); - update_flow_status_after_job_completion_internal( + Box::pin(update_flow_status_after_job_completion_internal( db, client, rec.flow, @@ -148,7 +148,7 @@ pub async fn update_flow_status_after_job_completion( job_completed_tx.clone(), #[cfg(feature = "benchmark")] bench, - ) + )) .await? } }; @@ -1508,7 +1508,7 @@ pub async fn update_flow_status_after_job_completion_internal( true } else { tracing::debug!(id = %flow_job.id, "start handle flow"); - match handle_flow( + match Box::pin(handle_flow( flow_job.clone(), &flow_data, db, @@ -1518,7 +1518,7 @@ pub async fn update_flow_status_after_job_completion_internal( worker_dir, job_completed_tx, worker_name, - ) + )) .warn_after_seconds(10) .await { @@ -1963,7 +1963,7 @@ pub async fn handle_flow( let mut rec = PushNextFlowJobRec { flow_job: flow_job, status: status }; loop { let PushNextFlowJobRec { flow_job, status } = rec; - let next = push_next_flow_job( + let next = Box::pin(push_next_flow_job( flow_job, status, flow, @@ -1973,7 +1973,7 @@ pub async fn handle_flow( same_worker_tx, worker_dir, worker_name, - ) + )) .warn_after_seconds(10) .await?; match next { diff --git a/backend/windmill-worker/src/worker_lockfiles.rs b/backend/windmill-worker/src/worker_lockfiles.rs index bfd726a238..0d0c16635e 100644 --- a/backend/windmill-worker/src/worker_lockfiles.rs +++ b/backend/windmill-worker/src/worker_lockfiles.rs @@ -417,7 +417,7 @@ pub async fn process_relative_imports( // Script might have no relative imports but still be referenced by someone else. match timeout( core::time::Duration::from_secs(60), - trigger_dependents_to_recompute_dependencies( + Box::pin(trigger_dependents_to_recompute_dependencies( w_id, script_path, deployment_message, @@ -427,7 +427,7 @@ pub async fn process_relative_imports( permissioned_as, db, already_visited, - ), + )), ) .warn_after_seconds(10) .await diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index bae29463a6..93e3200f3f 100644 --- a/benchmarks/lib.ts +++ b/benchmarks/lib.ts @@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts"; import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts"; import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts"; -export const VERSION = "v1.565.0"; +export const VERSION = "v1.566.1"; export async function login(email: string, password: string): Promise { return await windmill.UserService.login({ diff --git a/cli/src/commands/hub/hub.ts b/cli/src/commands/hub/hub.ts index 79bf02ee47..314d781bba 100644 --- a/cli/src/commands/hub/hub.ts +++ b/cli/src/commands/hub/hub.ts @@ -44,18 +44,57 @@ export async function pull(opts: GlobalOptions) { "X-email": userInfo.email, }; + if (hubBaseUrl !== DEFAULT_HUB_BASE_URL) { + const hubSecret = (await wmill.getGlobal({ + key: "hub_api_secret", + })) as string | undefined; + log.info("Fetching resource types from private hub: " + hubBaseUrl); + if (hubSecret) { + log.info("Using hub API secret"); + headers["X-api-secret"] = hubSecret; + } + } + if (uid) { headers["X-uid"] = uid; } - let list = await fetch(hubBaseUrl + "/resource_types/list", { + let res1 = await fetch(hubBaseUrl + "/resource_types/list", { headers, - }).then((r) => r.json() as Promise); + }); + + if (!res1.ok) { + if (res1.status === 401) { + // 401 can only happen on a private hub + throw new Error("Unauthorized access to private hub: " + hubBaseUrl); + } else { + throw new Error( + "Couldn't fetch resource types from hub " + + hubBaseUrl + + ": " + + (await res1.text()) + ); + } + } + + let list = (await res1.json()) as HubResourceType[]; if (list && list.length === 0 && hubBaseUrl !== DEFAULT_HUB_BASE_URL) { - list = await fetch(DEFAULT_HUB_BASE_URL + "/resource_types/list", { + log.info( + "No resource types found in private hub, fetching from public hub" + ); + delete headers["X-api-secret"]; + const res2 = await fetch(DEFAULT_HUB_BASE_URL + "/resource_types/list", { headers, - }).then((r) => r.json() as Promise); + }); + + if (!res2.ok) { + throw new Error( + "Couldn't fetch resource types from public hub: " + (await res2.text()) + ); + } + + list = (await res2.json()) as HubResourceType[]; } const resourceTypes = await wmill.listResourceType({ diff --git a/cli/src/main.ts b/cli/src/main.ts index 0f61d573a3..111ac39e51 100644 --- a/cli/src/main.ts +++ b/cli/src/main.ts @@ -68,7 +68,7 @@ export { // } // }); -export const VERSION = "1.565.0"; +export const VERSION = "1.566.1"; export const WM_FORK_PREFIX = "wm-fork"; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 23869fffb2..a22a2a2aa5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.565.0", + "version": "1.566.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.565.0", + "version": "1.566.1", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index 0e8c75c54b..0a11d755ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.565.0", + "version": "1.566.1", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte index 086757b185..840bac9526 100644 --- a/frontend/src/lib/components/common/table/ScriptRow.svelte +++ b/frontend/src/lib/components/common/table/ScriptRow.svelte @@ -305,16 +305,20 @@ { displayName: 'Publish to Hub', icon: Globe2, - action: () => { + action: async () => { + const scriptData = await ScriptService.getScriptByPath({ + workspace: $workspaceStore!, + path: script.path + }) window.open( scriptToHubUrl( - script.content, - script.summary, - script.description ?? '', - script.kind, - script.language, - script.schema, - script.lock ?? '', + scriptData.content, + scriptData.summary, + scriptData.description ?? '', + scriptData.kind, + scriptData.language, + scriptData.schema, + scriptData.lock ?? '', $hubBaseUrlStore ).toString(), '_blank' diff --git a/frontend/src/lib/components/instanceSettings.ts b/frontend/src/lib/components/instanceSettings.ts index 3a638207a7..6679018bf8 100644 --- a/frontend/src/lib/components/instanceSettings.ts +++ b/frontend/src/lib/components/instanceSettings.ts @@ -233,8 +233,7 @@ export const settings: Record = { key: 'hub_api_secret', fieldType: 'password', storage: 'setting', - ee_only: '', - requiresReloadOnChange: true + ee_only: '' }, { label: 'App workspace prefix', diff --git a/lsp/Pipfile b/lsp/Pipfile index 3acae6aa74..a35728cdb8 100644 --- a/lsp/Pipfile +++ b/lsp/Pipfile @@ -4,8 +4,8 @@ verify_ssl = true name = "pypi" [packages] -wmill = ">=1.565.0" -wmill_pg = ">=1.565.0" +wmill = ">=1.566.1" +wmill_pg = ">=1.566.1" sendgrid = "*" mysql-connector-python = "*" pymongo = "*" diff --git a/openflow.openapi.yaml b/openflow.openapi.yaml index 6a011e4efc..382bc26654 100644 --- a/openflow.openapi.yaml +++ b/openflow.openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.565.0 + version: 1.566.1 title: OpenFlow Spec contact: name: Ruben Fiszel diff --git a/powershell-client/WindmillClient/WindmillClient.psd1 b/powershell-client/WindmillClient/WindmillClient.psd1 index abcca20ccc..2facc2689e 100644 --- a/powershell-client/WindmillClient/WindmillClient.psd1 +++ b/powershell-client/WindmillClient/WindmillClient.psd1 @@ -12,7 +12,7 @@ RootModule = 'WindmillClient.psm1' # Version number of this module. - ModuleVersion = '1.565.0' + ModuleVersion = '1.566.1' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/python-client/wmill/pyproject.toml b/python-client/wmill/pyproject.toml index 1f5f2a5243..4cac1ec8ff 100644 --- a/python-client/wmill/pyproject.toml +++ b/python-client/wmill/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill" -version = "1.565.0" +version = "1.566.1" description = "A client library for accessing Windmill server wrapping the Windmill client API" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/python-client/wmill_pg/pyproject.toml b/python-client/wmill_pg/pyproject.toml index ae37a045ac..63c13dde64 100644 --- a/python-client/wmill_pg/pyproject.toml +++ b/python-client/wmill_pg/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill-pg" -version = "1.565.0" +version = "1.566.1" description = "An extension client for the wmill client library focused on pg" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/typescript-client/jsr.json b/typescript-client/jsr.json index 122d46da87..6a1fc6d96b 100644 --- a/typescript-client/jsr.json +++ b/typescript-client/jsr.json @@ -1,6 +1,6 @@ { "name": "@windmill/windmill", - "version": "1.565.0", + "version": "1.566.1", "exports": "./src/index.ts", "publish": { "exclude": ["!src", "./s3Types.ts", "./client.ts"] diff --git a/typescript-client/package.json b/typescript-client/package.json index 97cee04a3e..3c897900c8 100644 --- a/typescript-client/package.json +++ b/typescript-client/package.json @@ -1,7 +1,7 @@ { "name": "windmill-client", "description": "Windmill SDK client for browsers and Node.js", - "version": "1.565.0", + "version": "1.566.1", "author": "Ruben Fiszel", "license": "Apache 2.0", "devDependencies": { diff --git a/version.txt b/version.txt index e73b7284cb..f3a03324b2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.565.0 +1.566.1