diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b95b535a6..8ab3bc7a43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,60 @@ # Changelog +## [1.305.3](https://github.com/windmill-labs/windmill/compare/v1.305.2...v1.305.3) (2024-04-12) + + +### Bug Fixes + +* improve app icon renderer and app html renderer ([ee56821](https://github.com/windmill-labs/windmill/commit/ee56821a4734fa56097ae1ec7e032b6d14c0ee80)) + +## [1.305.2](https://github.com/windmill-labs/windmill/compare/v1.305.1...v1.305.2) (2024-04-11) + + +### Bug Fixes + +* unsaved changes on deploy of flow ([d1650db](https://github.com/windmill-labs/windmill/commit/d1650dbed935b206a8de8a59835933d559ff3a20)) + +## [1.305.1](https://github.com/windmill-labs/windmill/compare/v1.305.0...v1.305.1) (2024-04-11) + + +### Bug Fixes + +* fix plug connection for apps with array items ([c88e6a8](https://github.com/windmill-labs/windmill/commit/c88e6a86359cbdad038db09d54979cec1f12c8f3)) +* **frontend:** add missing darkModeObserver in CronInput ([#3531](https://github.com/windmill-labs/windmill/issues/3531)) ([8525494](https://github.com/windmill-labs/windmill/commit/8525494a68314e342b7393f6b6df15565ffb4082)) +* **frontend:** fix text alignement ([#3533](https://github.com/windmill-labs/windmill/issues/3533)) ([0c9a95c](https://github.com/windmill-labs/windmill/commit/0c9a95c964a16c3194d4887b7a3882a626faf6e4)) +* improve goto behavior ([6c33f17](https://github.com/windmill-labs/windmill/commit/6c33f17829a3a43cd1794abfc0c0807caa01bcfd)) +* load lazily the app icons ([cd5b023](https://github.com/windmill-labs/windmill/commit/cd5b0230338f3f20d7306b8a3feef509f6c8fe30)) +* remove requirement on full wasm parser for row insert of db studio ([cd07020](https://github.com/windmill-labs/windmill/commit/cd07020edb8ff652d086023771caa07755b5b2a2)) +* remove requirement on full wasm parser for row insert of db studio ([f17bed9](https://github.com/windmill-labs/windmill/commit/f17bed9741762f5241206a1bc257bcc4c4cb96fb)) +* update monaco configurations ([62e4ec2](https://github.com/windmill-labs/windmill/commit/62e4ec2e1443b47c273631d2b8efa7f3a9ba804c)) + +## [1.305.0](https://github.com/windmill-labs/windmill/compare/v1.304.4...v1.305.0) (2024-04-09) + + +### Features + +* flow concurrency limits support custom concurrency key ([a55aad3](https://github.com/windmill-labs/windmill/commit/a55aad30039d8bc44f4cbc9aa2fa3e220966ca80)) + + +### Bug Fixes + +* add ability to cancel flows directly from operator modal ([5272956](https://github.com/windmill-labs/windmill/commit/5272956153419f3eac7203a9b043ca63c2cf869b)) + +## [1.304.4](https://github.com/windmill-labs/windmill/compare/v1.304.3...v1.304.4) (2024-04-09) + + +### Bug Fixes + +* allow for longer approver names in flows ([f117539](https://github.com/windmill-labs/windmill/commit/f117539a54e5947832c1d435a4991274d103cef0)) +* **frontend:** Fix bypass confirmation shortcut ([#3527](https://github.com/windmill-labs/windmill/issues/3527)) ([db5abd3](https://github.com/windmill-labs/windmill/commit/db5abd37cda548e642fa825cd279a730a7af5c00)) +* **frontend:** Improve theme editor ([#3525](https://github.com/windmill-labs/windmill/issues/3525)) ([975055b](https://github.com/windmill-labs/windmill/commit/975055b90ff3e7bd0b8202920ca78fb9178663a7)) +* improve deadlocks for parallel branches with parallelism constraints ([0c824de](https://github.com/windmill-labs/windmill/commit/0c824de4cdfb3b6b609cce0e1678a58743ea24f4)) +* improve deadlocks for parallel branches with parallelism constraints ([8dd1175](https://github.com/windmill-labs/windmill/commit/8dd117528c793b828631d5f320bb28ce9c5e3a3f)) +* improve handling of very large iterator on frontend ([7e4b6c3](https://github.com/windmill-labs/windmill/commit/7e4b6c374415862954f4876b693a199aabcab45e)) +* improve order dragndrop for json editor in app ([1ab1fb7](https://github.com/windmill-labs/windmill/commit/1ab1fb7e4de9984c6408d1fe5ef332d8f242362b)) +* improve performance of for-loops with parralelism ([a4442d4](https://github.com/windmill-labs/windmill/commit/a4442d4d3d919383ac09df66f20d6c4f98c04a92)) +* improve performance of for-loops with parralelism ([29422f1](https://github.com/windmill-labs/windmill/commit/29422f156d8ca3e0ac03288bd11b31f505a492c1)) + ## [1.304.3](https://github.com/windmill-labs/windmill/compare/v1.304.2...v1.304.3) (2024-04-08) diff --git a/backend/.sqlx/query-0c349ac832cbf055fce755c8e2081eacf2b836b0396ec48a6cc2405fb7aa76de.json b/backend/.sqlx/query-0c349ac832cbf055fce755c8e2081eacf2b836b0396ec48a6cc2405fb7aa76de.json new file mode 100644 index 0000000000..6d466677b2 --- /dev/null +++ b/backend/.sqlx/query-0c349ac832cbf055fce755c8e2081eacf2b836b0396ec48a6cc2405fb7aa76de.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE queue SET suspend = suspend - 1 WHERE id = $1 AND suspend > 0", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "0c349ac832cbf055fce755c8e2081eacf2b836b0396ec48a6cc2405fb7aa76de" +} diff --git a/backend/.sqlx/query-2719f910142b32476a16025bb9836b0cab019ba0a436b330ea3a53fba4725f73.json b/backend/.sqlx/query-a3ccf362b4f6df400b3c7a084795dbf541eb14c5c374656ffb96da7283a2a6f1.json similarity index 57% rename from backend/.sqlx/query-2719f910142b32476a16025bb9836b0cab019ba0a436b330ea3a53fba4725f73.json rename to backend/.sqlx/query-a3ccf362b4f6df400b3c7a084795dbf541eb14c5c374656ffb96da7283a2a6f1.json index 89895ed0bd..bc5e2351f9 100644 --- a/backend/.sqlx/query-2719f910142b32476a16025bb9836b0cab019ba0a436b330ea3a53fba4725f73.json +++ b/backend/.sqlx/query-a3ccf362b4f6df400b3c7a084795dbf541eb14c5c374656ffb96da7283a2a6f1.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT concurrency_key FROM script WHERE hash = $1", + "query": "SELECT concurrency_key FROM script WHERE hash = $1 AND workspace_id = $2", "describe": { "columns": [ { @@ -11,12 +11,13 @@ ], "parameters": { "Left": [ - "Int8" + "Int8", + "Text" ] }, "nullable": [ true ] }, - "hash": "2719f910142b32476a16025bb9836b0cab019ba0a436b330ea3a53fba4725f73" + "hash": "a3ccf362b4f6df400b3c7a084795dbf541eb14c5c374656ffb96da7283a2a6f1" } diff --git a/backend/.sqlx/query-a875cb56485b812e9d4739afd0915067f7e5abe0ca0adf264b792fccf21e005b.json b/backend/.sqlx/query-a875cb56485b812e9d4739afd0915067f7e5abe0ca0adf264b792fccf21e005b.json new file mode 100644 index 0000000000..e264db5ef2 --- /dev/null +++ b/backend/.sqlx/query-a875cb56485b812e9d4739afd0915067f7e5abe0ca0adf264b792fccf21e005b.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT value->>'concurrency_key' FROM flow WHERE path = $1 AND workspace_id = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "?column?", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "a875cb56485b812e9d4739afd0915067f7e5abe0ca0adf264b792fccf21e005b" +} diff --git a/backend/.sqlx/query-ca2bdfa3c310b05348e20464df8403fde43dec24a8b8823383d0ac8f2116babf.json b/backend/.sqlx/query-b8d97d300ffe6fae99f2396ae07cef03903752d17ce3fdadca47d86da75139aa.json similarity index 75% rename from backend/.sqlx/query-ca2bdfa3c310b05348e20464df8403fde43dec24a8b8823383d0ac8f2116babf.json rename to backend/.sqlx/query-b8d97d300ffe6fae99f2396ae07cef03903752d17ce3fdadca47d86da75139aa.json index 6157317987..e88b9bf05a 100644 --- a/backend/.sqlx/query-ca2bdfa3c310b05348e20464df8403fde43dec24a8b8823383d0ac8f2116babf.json +++ b/backend/.sqlx/query-b8d97d300ffe6fae99f2396ae07cef03903752d17ce3fdadca47d86da75139aa.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id FROM queue WHERE parent_job = $1 AND suspend > 0 ORDER by id FOR UPDATE", + "query": "SELECT id FROM queue WHERE parent_job = $1 AND suspend > 0 ORDER by suspend", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "ca2bdfa3c310b05348e20464df8403fde43dec24a8b8823383d0ac8f2116babf" + "hash": "b8d97d300ffe6fae99f2396ae07cef03903752d17ce3fdadca47d86da75139aa" } diff --git a/backend/.sqlx/query-d42005ce0f8fbb2f65e8caa3cb06b6888b6c29e40ff575bb3893ea93e48450dc.json b/backend/.sqlx/query-d42005ce0f8fbb2f65e8caa3cb06b6888b6c29e40ff575bb3893ea93e48450dc.json deleted file mode 100644 index f2c558bd01..0000000000 --- a/backend/.sqlx/query-d42005ce0f8fbb2f65e8caa3cb06b6888b6c29e40ff575bb3893ea93e48450dc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE queue SET suspend = suspend - 1 WHERE parent_job = $1 AND suspend > 0", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [] - }, - "hash": "d42005ce0f8fbb2f65e8caa3cb06b6888b6c29e40ff575bb3893ea93e48450dc" -} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 78f33276e3..2176540d4c 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "archiver-rs" @@ -491,9 +491,9 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", @@ -557,9 +557,9 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297b64446175a73987cedc3c438d79b2a654d0fff96f65ff530fbe039347644c" +checksum = "48730d0b4c3d91c43d0d37168831d9fd0e065ad4a889a2ee9faf8d34c3d2804d" dependencies = [ "aws-credential-types", "aws-runtime", @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13dc54b4b49f8288532334bba8f87386a40571c47c37b1304979b556dc613c8" +checksum = "c4ee6903f9d0197510eb6b44c4d86b493011d08b4992938f7b9be0333b6685aa" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -623,9 +623,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "019a07902c43b03167ea5df0182f0cb63fae89f9a9682c44d18cf2e4a042cb34" +checksum = "b2be5ba83b077b67a6f7a1927eb6b212bf556e33bd74b5eaa5aa6e421910803a" dependencies = [ "aws-credential-types", "aws-runtime", @@ -645,9 +645,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c46ee08a48a7f4eaa4ad201dcc1dd537b49c50859d14d4510e00ad9d3f9af2" +checksum = "022ca669825f841aef17b12d4354ef2b8651e4664be49f2d9ea13e4062a80c9f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -667,9 +667,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f752ac730125ca6017f72f9db5ec1772c9ecc664f87aa7507a7d81b023c23713" +checksum = "8e4a5f5cb007347c1ab34a6d56456301dfada921fc9e57d687ecb08baddd11ff" dependencies = [ "aws-credential-types", "aws-runtime", @@ -763,9 +763,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53572b4cd934ee5e8461ad53caa36e9d246aaef42166e3ac539e206a925d330" +checksum = "de34bcfa1fb3c82a80e252a753db34a6658e07f23d3a5b3fc96919518fa7a3f5" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -789,9 +789,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb2b3a7030dc9a3c9a08ce0b25decea5130e9db19619d4dffbbff34f75fe850" +checksum = "4cc56a5c96ec741de6c5e6bf1ce6948be969d6506dfa9c39cffc284e31e4979b" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -841,9 +841,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dbf2f3da841a8930f159163175cf6a3d16ddde517c1b0fba7aa776822800f40" +checksum = "afb278e322f16f59630a83b6b2dc992a0b48aa74ed47b4130f193fae0053d713" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -1240,9 +1240,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" @@ -1398,9 +1398,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd97381a8cc6493395a5afc4c691c1084b3768db713b73aa215217aa245d153" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" dependencies = [ "jobserver", "libc", @@ -1573,9 +1573,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -1737,9 +1737,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b432c56615136f8dba245fed7ec3d5518c500a31108661067e61e72fe7e6bc" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -3526,9 +3526,9 @@ dependencies = [ [[package]] name = "hstr" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f5356d62012374578cd3a5c013d6586de3efbca3b53379fc1edfbb95c9db14" +checksum = "96274be293b8877e61974a607105d09c84caebe9620b47774aa8a6b942042dd4" dependencies = [ "hashbrown 0.14.3", "new_debug_unreachable", @@ -3917,9 +3917,9 @@ checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "f08474e32172238f2827bd160c67871cdb2801430f65c3979184dc362e3ca118" dependencies = [ "libc", ] @@ -4221,9 +4221,9 @@ dependencies = [ [[package]] name = "malachite" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95720fa434c3fb2701c89deefc75ee0a7ec63f376c3385f868486413236b2bd4" +checksum = "38ad951c9d45bd4c77f4c843844870dddeb2e332864226f5a62277498e1627b8" dependencies = [ "malachite-base", "malachite-nz", @@ -4232,9 +4232,9 @@ dependencies = [ [[package]] name = "malachite-base" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d768a3e1dc170837bc0e4dad10fc9140260deb164118d3278d2193f4de796" +checksum = "d073a3d1e4e037975af5ef176a2632672e25e8ddbe8e1811745c2e0726b6ad94" dependencies = [ "hashbrown 0.14.3", "itertools 0.11.0", @@ -4257,9 +4257,9 @@ dependencies = [ [[package]] name = "malachite-nz" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2d170d59f4f8e2b3f463649ec5ba40cb6968ed7b4ce54541d7de63d39e3c05" +checksum = "2546fc6ae29728079e87a2a0f011509e6060713b65e62ee46ba5d413b495ebc7" dependencies = [ "itertools 0.11.0", "libm", @@ -4268,9 +4268,9 @@ dependencies = [ [[package]] name = "malachite-q" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a77ea0d54682a8923756320ca3840497a878d19c9bdb29c830d95f081eb13f3" +checksum = "0ad0ac879ecbb7e1cc8060b48696eebed0b0de8d922db4f8b378dfbc1bad806a" dependencies = [ "itertools 0.11.0", "malachite-base", @@ -4476,7 +4476,7 @@ dependencies = [ "mysql_common", "native-tls", "once_cell", - "pem 3.0.3", + "pem 3.0.4", "percent-encoding", "pin-project", "rand 0.8.5", @@ -5037,11 +5037,11 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "serde", ] @@ -6025,9 +6025,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -8328,9 +8328,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.8" +version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b1a378e48fb3ce3a5cf04359c456c9c98ff689bcf1c1bc6e6a31f247686f275" +checksum = "26d7c217777061d5a2d652aea771fb9ba98b6dade657204b08c4b9604d11555b" dependencies = [ "cfg-if", "core-foundation-sys", @@ -8486,9 +8486,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -8507,9 +8507,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -8817,7 +8817,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -9707,7 +9707,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "axum", @@ -9744,7 +9744,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "argon2", @@ -9821,7 +9821,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.304.3" +version = "1.305.3" dependencies = [ "base64 0.21.7", "chrono", @@ -9839,7 +9839,7 @@ dependencies = [ [[package]] name = "windmill-audit" -version = "1.304.3" +version = "1.305.3" dependencies = [ "chrono", "serde", @@ -9852,7 +9852,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "aws-config", @@ -9888,7 +9888,7 @@ dependencies = [ [[package]] name = "windmill-git-sync" -version = "1.304.3" +version = "1.305.3" dependencies = [ "regex", "rsmq_async", @@ -9903,7 +9903,7 @@ dependencies = [ [[package]] name = "windmill-parser" -version = "1.304.3" +version = "1.305.3" dependencies = [ "serde", "serde_json", @@ -9911,7 +9911,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "lazy_static", @@ -9922,7 +9922,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "gosyn", @@ -9934,7 +9934,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "lazy_static", @@ -9945,7 +9945,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "itertools 0.12.1", @@ -9956,7 +9956,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "async-recursion", @@ -9973,7 +9973,7 @@ dependencies = [ [[package]] name = "windmill-parser-sql" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "lazy_static", @@ -9984,7 +9984,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -10002,7 +10002,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "getrandom 0.2.14", @@ -10020,7 +10020,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "async-recursion", @@ -10051,9 +10051,20 @@ dependencies = [ "windmill-common", ] +[[package]] +name = "windmill-sql-datatype-parser-wasm" +version = "1.305.3" +dependencies = [ + "serde", + "wasm-bindgen", + "wasm-bindgen-test", + "windmill-parser", + "windmill-parser-sql", +] + [[package]] name = "windmill-worker" -version = "1.304.3" +version = "1.305.3" dependencies = [ "anyhow", "async-recursion", @@ -10085,7 +10096,7 @@ dependencies = [ "object_store", "once_cell", "openidconnect", - "pem 3.0.3", + "pem 3.0.4", "postgres-native-tls", "prometheus", "rand 0.8.5", @@ -10281,9 +10292,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index c2f990d83e..00c6a908c2 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.304.3" +version = "1.305.3" authors.workspace = true edition.workspace = true @@ -20,10 +20,11 @@ members = [ "./parsers/windmill-parser-bash", "./parsers/windmill-parser-py", "./parsers/windmill-parser-py-imports", + "./parsers/windmill-sql-datatype-parser-wasm", ] [workspace.package] -version = "1.304.3" +version = "1.305.3" authors = ["Ruben Fiszel "] edition = "2021" diff --git a/backend/migrations/20240409181630_add_concurrency_key_to_flow.down.sql b/backend/migrations/20240409181630_add_concurrency_key_to_flow.down.sql new file mode 100644 index 0000000000..050f94cee7 --- /dev/null +++ b/backend/migrations/20240409181630_add_concurrency_key_to_flow.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +ALTER TABLE flow DROP COLUMN concurrency_key; diff --git a/backend/migrations/20240409181630_add_concurrency_key_to_flow.up.sql b/backend/migrations/20240409181630_add_concurrency_key_to_flow.up.sql new file mode 100644 index 0000000000..3ad350a983 --- /dev/null +++ b/backend/migrations/20240409181630_add_concurrency_key_to_flow.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +ALTER TABLE flow ADD COLUMN concurrency_key VARCHAR(255); diff --git a/backend/parsers/windmill-parser-sql/src/lib.rs b/backend/parsers/windmill-parser-sql/src/lib.rs index c64ed7f846..cdca933d90 100644 --- a/backend/parsers/windmill-parser-sql/src/lib.rs +++ b/backend/parsers/windmill-parser-sql/src/lib.rs @@ -5,7 +5,7 @@ use regex::Regex; use serde_json::json; use std::collections::HashMap; -use windmill_parser::{Arg, MainArgSignature, Typ}; +pub use windmill_parser::{Arg, MainArgSignature, Typ}; pub fn parse_mysql_sig(code: &str) -> anyhow::Result { let parsed = parse_mysql_file(&code)?; diff --git a/backend/parsers/windmill-sql-datatype-parser-wasm/Cargo.toml b/backend/parsers/windmill-sql-datatype-parser-wasm/Cargo.toml new file mode 100644 index 0000000000..3176ec1ce6 --- /dev/null +++ b/backend/parsers/windmill-sql-datatype-parser-wasm/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "windmill-sql-datatype-parser-wasm" +version.workspace = true +edition.workspace = true +authors.workspace = true + + +[lib] +crate-type = ["cdylib"] +name = "windmill_sql_datatype_parser_wasm" +path = "./src/lib.rs" + +[dev-dependencies] +wasm-bindgen-test.workspace = true + +[dependencies] +windmill-parser.workspace = true +windmill-parser-sql.workspace = true +wasm-bindgen.workspace = true +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/backend/parsers/windmill-sql-datatype-parser-wasm/build.sh b/backend/parsers/windmill-sql-datatype-parser-wasm/build.sh new file mode 100644 index 0000000000..0ac5a6fde0 --- /dev/null +++ b/backend/parsers/windmill-sql-datatype-parser-wasm/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eou pipefail + +deno task wasmbuild --out ../../../cli/wasm/ diff --git a/backend/parsers/windmill-sql-datatype-parser-wasm/package-lock.json b/backend/parsers/windmill-sql-datatype-parser-wasm/package-lock.json new file mode 100644 index 0000000000..f88d35a75a --- /dev/null +++ b/backend/parsers/windmill-sql-datatype-parser-wasm/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "windmill-parser-wasm", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/backend/parsers/windmill-sql-datatype-parser-wasm/package.json b/backend/parsers/windmill-sql-datatype-parser-wasm/package.json new file mode 100644 index 0000000000..fa9dffe133 --- /dev/null +++ b/backend/parsers/windmill-sql-datatype-parser-wasm/package.json @@ -0,0 +1,4 @@ +{ + "name": "windmill-sql-datatype-parser-wasm", + "version": "0.1.0" +} diff --git a/backend/parsers/windmill-sql-datatype-parser-wasm/src/lib.rs b/backend/parsers/windmill-sql-datatype-parser-wasm/src/lib.rs new file mode 100644 index 0000000000..30103beafd --- /dev/null +++ b/backend/parsers/windmill-sql-datatype-parser-wasm/src/lib.rs @@ -0,0 +1,40 @@ +use wasm_bindgen::prelude::*; +use windmill_parser_sql::Typ; + +fn to_str(typ: Typ) -> String { + match typ { + Typ::Str(_) => "str".to_string(), + Typ::Int => "int".to_string(), + Typ::Float => "float".to_string(), + Typ::Bool => "bool".to_string(), + Typ::List(t) => format!("list-{}", to_str(*t)), + Typ::Bytes => "bytes".to_string(), + Typ::Datetime => "datetime".to_string(), + _ => "unknown".to_string(), + } +} + +#[wasm_bindgen] +pub fn parse_sql(typ: &str) -> String { + to_str(windmill_parser_sql::parse_pg_typ(typ)) +} + +#[wasm_bindgen] +pub fn parse_mysql(typ: &str) -> String { + to_str(windmill_parser_sql::parse_mysql_typ(typ)) +} + +#[wasm_bindgen] +pub fn parse_bigquery(typ: &str) -> String { + to_str(windmill_parser_sql::parse_bigquery_typ(typ)) +} + +#[wasm_bindgen] +pub fn parse_snowflake(typ: &str) -> String { + to_str(windmill_parser_sql::parse_snowflake_typ(typ)) +} + +#[wasm_bindgen] +pub fn parse_mssql(typ: &str) -> String { + to_str(windmill_parser_sql::parse_mssql_typ(typ)) +} diff --git a/backend/src/monitor.rs b/backend/src/monitor.rs index 285ef3bfb1..08a778182c 100644 --- a/backend/src/monitor.rs +++ b/backend/src/monitor.rs @@ -927,7 +927,7 @@ async fn handle_zombie_flows( r#" SELECT * FROM queue - WHERE running = true AND suspend = 0 AND scheduled_for <= now() AND (job_kind = 'flow' OR job_kind = 'flowpreview') + WHERE running = true AND suspend = 0 AND suspend_until IS null AND scheduled_for <= now() AND (job_kind = 'flow' OR job_kind = 'flowpreview') AND last_ping IS NOT NULL AND last_ping < NOW() - ($1 || ' seconds')::interval "#, ).bind(FLOW_ZOMBIE_TRANSITION_TIMEOUT.as_str()) diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 16d7bfa09a..9cc7dc6ef7 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.304.3 + version: 1.305.3 title: Windmill API contact: diff --git a/backend/windmill-api/src/flows.rs b/backend/windmill-api/src/flows.rs index 398a4faa7e..05f732358c 100644 --- a/backend/windmill-api/src/flows.rs +++ b/backend/windmill-api/src/flows.rs @@ -334,7 +334,7 @@ async fn create_flow( nf.draft_only, nf.tag, nf.dedicated_worker, - nf.visible_to_runner_only, + nf.visible_to_runner_only.unwrap_or(false), ) .execute(&mut tx) .await?; @@ -502,7 +502,7 @@ async fn update_flow( w_id, nf.tag, nf.dedicated_worker, - nf.visible_to_runner_only, + nf.visible_to_runner_only.unwrap_or(false), ) .execute(&mut tx) .await?; @@ -985,6 +985,7 @@ mod tests { cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }; let expect = serde_json::json!({ "modules": [ diff --git a/backend/windmill-common/src/flows.rs b/backend/windmill-common/src/flows.rs index 9d1d5caca6..ff4d023d7d 100644 --- a/backend/windmill-common/src/flows.rs +++ b/backend/windmill-common/src/flows.rs @@ -105,6 +105,8 @@ pub struct FlowValue { #[serde(skip_serializing_if = "Option::is_none")] // Priority at the flow level pub priority: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub concurrency_key: Option, } #[derive(Deserialize, Serialize, Debug, Clone)] diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index ee4ea1f694..21305fa52e 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -1657,12 +1657,12 @@ pub async fn pull( + Duration::try_seconds(i64::from(job_custom_concurrency_time_window_s)) .unwrap_or_default(); tracing::info!("Job '{}' from path '{}' with concurrency key '{}' has reached its concurrency limit of {} jobs run in the last {} seconds. This job will be re-queued for next execution at {}", - job_uuid, job_script_path, job_custom_concurrent_limit, job_concurrency_key, job_custom_concurrency_time_window_s, estimated_next_schedule_timestamp); + job_uuid, job_script_path, job_concurrency_key, job_custom_concurrent_limit, job_custom_concurrency_time_window_s, estimated_next_schedule_timestamp); let job_log_event = format!( "\nRe-scheduled job to {estimated_next_schedule_timestamp} due to concurrency limits with key {job_concurrency_key} and limit {job_custom_concurrent_limit} in the last {job_custom_concurrency_time_window_s} seconds", ); - let _ = append_logs(job_uuid, pulled_job.workspace_id, job_log_event, db); + let _ = append_logs(job_uuid, pulled_job.workspace_id, job_log_event, db).await; if rsmq.is_some() { // if let Some(ref mut rsmq) = tx.rsmq { // if using redis, only one message at a time can be poped from the queue. Process only this message and move to the next elligible job @@ -1884,50 +1884,63 @@ async fn pull_single_job_and_mark_as_running_no_concurrency_limit< } async fn concurrency_key(db: &Pool, queued_job: &QueuedJob) -> String { - if queued_job.is_flow() { - // custom concurrency keys are not yet supported for flows - queued_job.full_path_with_workspace() - } else { - let concurrency_key = sqlx::query_scalar!( - "SELECT concurrency_key FROM script WHERE hash = $1", - queued_job.script_hash.unwrap_or(ScriptHash(0)).0 + let r = if queued_job.is_flow() { + sqlx::query_scalar!( + "SELECT value->>'concurrency_key' FROM flow WHERE path = $1 AND workspace_id = $2", + queued_job.script_path, + queued_job.workspace_id ) .fetch_one(db) - .await; - match concurrency_key { - Ok(Some(custom_concurrency_key)) => { - let workspaced = - custom_concurrency_key.replace("$workspace", queued_job.workspace_id.as_str()); - if RE_ARG_TAG.is_match(&workspaced) { - let mut interpolated = workspaced.clone(); - for cap in RE_ARG_TAG.captures_iter(&workspaced) { - let arg_name = cap.get(1).unwrap().as_str(); - let arg_value = match queued_job.args.as_ref() { - Some(Json(args_map_json)) => match args_map_json.get(arg_name) { - Some(arg_value_raw) => { - serde_json::to_string(arg_value_raw).unwrap_or_default() - } - None => "".to_string(), - }, + .await + } else { + sqlx::query_scalar!( + "SELECT concurrency_key FROM script WHERE hash = $1 AND workspace_id = $2", + queued_job.script_hash.unwrap_or(ScriptHash(0)).0, + queued_job.workspace_id + ) + .fetch_one(db) + .await + }; + process_custom_concurrency_key(queued_job, r).await +} + +async fn process_custom_concurrency_key( + queued_job: &QueuedJob, + concurrency_key: Result, sqlx::Error>, +) -> String { + match concurrency_key { + Ok(Some(custom_concurrency_key)) => { + let workspaced = + custom_concurrency_key.replace("$workspace", queued_job.workspace_id.as_str()); + if RE_ARG_TAG.is_match(&workspaced) { + let mut interpolated = workspaced.clone(); + for cap in RE_ARG_TAG.captures_iter(&workspaced) { + let arg_name = cap.get(1).unwrap().as_str(); + let arg_value = match queued_job.args.as_ref() { + Some(Json(args_map_json)) => match args_map_json.get(arg_name) { + Some(arg_value_raw) => { + serde_json::to_string(arg_value_raw).unwrap_or_default() + } None => "".to_string(), - }; - interpolated = interpolated - .replace(format!("$args[{}]", arg_name).as_str(), arg_value.as_str()); - } - interpolated - } else { - workspaced + }, + None => "".to_string(), + }; + interpolated = interpolated + .replace(format!("$args[{}]", arg_name).as_str(), arg_value.as_str()); } + interpolated + } else { + workspaced } - Ok(None) => queued_job.full_path_with_workspace(), - _ => { - tracing::warn!( - "Unable to retrieve concurrency key for script {:?} | {:?}", - queued_job.script_path, - queued_job.script_hash - ); - queued_job.full_path_with_workspace() - } + } + Ok(None) => queued_job.full_path_with_workspace(), + _ => { + tracing::warn!( + "Unable to retrieve concurrency key for script {:?} | {:?}", + queued_job.script_path, + queued_job.script_hash + ); + queued_job.full_path_with_workspace() } } } @@ -3000,6 +3013,7 @@ pub async fn push<'c, T: Serialize + Send + Sync, R: rsmq_async::RsmqConnection skip_expr: None, cache_ttl: cache_ttl.map(|val| val as u32), early_return: None, + concurrency_key: None, priority: priority, }; ( diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 6c399c1fcb..d9d7282613 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -1338,6 +1338,7 @@ pub async fn run_worker 3 { + let suspend_first = if suspend_first_success || last_checked_suspended.elapsed().as_secs() > 3 { last_checked_suspended = Instant::now(); true } else { false }; - pull(&db, rsmq.clone(), suspend_first).map(|x| (x, pull_time)).await + pull(&db, rsmq.clone(), suspend_first).map(|x| (x, pull_time, suspend_first)).await } => { add_time!(timing, loop_start, "post pull"); // tracing::debug!("pulled job: {:?}", job.as_ref().ok().and_then(|x| x.as_ref().map(|y| y.id))); let duration_pull_s = timer.elapsed().as_secs_f64(); let err_pull = job.is_ok(); let empty = job.as_ref().is_ok_and(|x| x.is_none()); + suspend_first_success = suspend_first && !empty; if !agent_mode && duration_pull_s > 0.5 { tracing::warn!("pull took more than 0.5s ({duration_pull_s}), this is a sign that the database is VERY undersized for this load. empty: {empty}, err: {err_pull}"); #[cfg(feature = "prometheus")] diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index 44430fa7c5..f6728e9742 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -415,28 +415,29 @@ pub async fn update_flow_status_after_job_completion_internal< tx.commit().await?; if parallelism.is_some() { - let mut tx = db.begin().await?; - // this ensure that the lock is taken in the same order and thus avoid deadlocks - let _ = sqlx::query!( - "SELECT id FROM queue WHERE parent_job = $1 AND suspend > 0 ORDER by id FOR UPDATE", - job_id_for_status + let ids = sqlx::query_scalar!( + "SELECT id FROM queue WHERE parent_job = $1 AND suspend > 0 ORDER by suspend", + flow ) - .fetch_all(&mut *tx) + .fetch_all(db) .await .map_err(|e| { Error::InternalErr(format!("error while locking jobs to decrease parallelism of: {e}")) })?; - sqlx::query!( - "UPDATE queue SET suspend = suspend - 1 WHERE parent_job = $1 AND suspend > 0", - flow - ) - .execute(&mut *tx) - .await - .map_err(|e| { - Error::InternalErr(format!("error decreasing suspend: {e}")) - })?; - tx.commit().await?; + for id in ids { + sqlx::query!( + "UPDATE queue SET suspend = suspend - 1 WHERE id = $1 AND suspend > 0", + id + ) + .execute(db) + .await + .map_err(|e| { + Error::InternalErr(format!( + "error decreasing suspend for {id}: {e}" + )) + })?; + } } sqlx::query!( @@ -446,13 +447,18 @@ pub async fn update_flow_status_after_job_completion_internal< flow ) .execute(db) - .await?; + .await + .map_err(|e| { + Error::InternalErr(format!("error while setting last ping to null: {e}")) + })?; let r = sqlx::query_scalar!( "DELETE FROM parallel_monitor_lock WHERE parent_flow_id = $1 and job_id = $2 RETURNING last_ping", flow, job_id_for_status - ).fetch_optional(db).await?; + ).fetch_optional(db).await.map_err(|e| { + Error::InternalErr(format!("error while removing parallel_monitor_lock: {e}")) + })?; if r.is_some() { tracing::info!( "parallel flow has removed lock on its parent, last ping was {:?}", @@ -741,7 +747,10 @@ pub async fn update_flow_status_after_job_completion_internal< &_cleanup_module.flow_jobs_to_clean, ) .execute(db) - .await?; + .await + .map_err(|e| { + Error::InternalErr(format!("error while cleaning up completed_job: {e}")) + })?; } } if flow_job.canceled { @@ -2598,6 +2607,7 @@ async fn compute_next_flow_transform( cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }, path: Some(format!("{}/forloop", flow_job.script_path())), restarted_from: None, @@ -2696,6 +2706,7 @@ async fn compute_next_flow_transform( cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }, path: Some(format!( "{}/branchone-{}", @@ -2747,6 +2758,7 @@ async fn compute_next_flow_transform( cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }, path: Some(format!( "{}/branchall-{}", @@ -2814,6 +2826,7 @@ async fn compute_next_flow_transform( cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }, path: Some(format!( "{}/branchall-{}", @@ -2886,6 +2899,7 @@ async fn next_loop_iteration( cache_ttl: None, priority: None, early_return: None, + concurrency_key: None, }, path: inner_path, restarted_from: None, diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index fe87d03118..9b962c19f6 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.304.3"; +export const VERSION = "v1.305.3"; export async function login(email: string, password: string): Promise { return await windmill.UserService.login({ diff --git a/cli/deps.ts b/cli/deps.ts index a9991251ad..a7afa06707 100644 --- a/cli/deps.ts +++ b/cli/deps.ts @@ -1,37 +1,38 @@ // windmill export { setClient } from "npm:windmill-client@1.304.2"; export * from "npm:windmill-client@1.304.2"; -export { SEP } from "https://deno.land/std@0.201.0/path/separator.ts"; + // cliffy -export { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.ts"; -export { Table } from "https://deno.land/x/cliffy@v1.0.0-rc.3/table/table.ts"; -export { colors } from "https://deno.land/x/cliffy@v1.0.0-rc.3/ansi/colors.ts"; -export { Secret } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/secret.ts"; -export { Select } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/select.ts"; -export { Confirm } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts"; -export { Input } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/input.ts"; +export { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; +export { Table } from "https://deno.land/x/cliffy@v1.0.0-rc.4/table/table.ts"; +export { colors } from "https://deno.land/x/cliffy@v1.0.0-rc.4/ansi/colors.ts"; +export { Secret } from "https://deno.land/x/cliffy@v1.0.0-rc.4/prompt/secret.ts"; +export { Select } from "https://deno.land/x/cliffy@v1.0.0-rc.4/prompt/select.ts"; +export { Confirm } from "https://deno.land/x/cliffy@v1.0.0-rc.4/prompt/confirm.ts"; +export { Input } from "https://deno.land/x/cliffy@v1.0.0-rc.4/prompt/input.ts"; export { DenoLandProvider, UpgradeCommand, -} from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/upgrade/mod.ts"; -export { CompletionsCommand } from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/completions/mod.ts"; +} from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/mod.ts"; +export { CompletionsCommand } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/mod.ts"; // std -export * as path from "https://deno.land/std@0.184.0/path/mod.ts"; -export { ensureDir } from "https://deno.land/std@0.184.0/fs/ensure_dir.ts"; +export * as path from "https://deno.land/std@0.207.0/path/mod.ts"; +export { ensureDir } from "https://deno.land/std@0.207.0/fs/ensure_dir.ts"; export { copy, readAll, readerFromStreamReader, -} from "https://deno.land/std@0.184.0/streams/mod.ts"; +} from "https://deno.land/std@0.207.0/streams/mod.ts"; +export { SEP } from "https://deno.land/std@0.207.0/path/separator.ts"; +export { DelimiterStream } from "https://deno.land/std@0.207.0/streams/mod.ts"; +export { iterateReader } from "https://deno.land/std@0.207.0/streams/iterate_reader.ts"; +export { writeAllSync } from "https://deno.land/std@0.207.0/streams/mod.ts"; +export { encodeHex } from "https://deno.land/std@0.207.0/encoding/hex.ts"; + +// other export { Application, Router } from "https://deno.land/x/oak@v12.5.0/mod.ts"; export { getPort } from "https://deno.land/x/getport@v2.1.2/mod.ts"; - -export { DelimiterStream } from "https://deno.land/std@0.184.0/streams/mod.ts"; -export { iterateReader } from "https://deno.land/std@0.184.0/streams/iterate_reader.ts"; -export { writeAllSync } from "https://deno.land/std@0.184.0/streams/mod.ts"; - -// other export { getAvailablePort } from "https://deno.land/x/port@1.0.0/mod.ts"; export { default as dir } from "https://deno.land/x/dir@1.5.1/mod.ts"; export { passwordGenerator } from "https://deno.land/x/password_generator@latest/mod.ts"; // TODO: I think the version is called latest, but it's still pinned. @@ -48,5 +49,4 @@ export { parse as yamlParse, } from "https://deno.land/std@0.184.0/yaml/mod.ts"; export { open } from "https://deno.land/x/open@v0.0.5/index.ts"; -export { encodeHex } from "https://deno.land/std@0.207.0/encoding/hex.ts"; export { default as gitignore_parser } from "npm:gitignore-parser"; diff --git a/cli/main.ts b/cli/main.ts index 2687089460..f9796a96c3 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -31,7 +31,7 @@ addEventListener("error", (event) => { } }); -export const VERSION = "v1.304.3"; +export const VERSION = "v1.305.3"; let command: any = new Command() .name("wmill") diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b1f36e78c9..79d15ebc17 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.304.3", + "version": "1.305.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.304.3", + "version": "1.305.3", "license": "AGPL-3.0", "dependencies": { "@aws-crypto/sha256-js": "^4.0.0", @@ -52,6 +52,7 @@ "vscode-uri": "~3.0.8", "vscode-ws-jsonrpc": "~3.1.0", "windmill-parser-wasm": "^1.286.2", + "windmill-sql-datatype-parser-wasm": "1.305.0", "y-monaco": "^0.1.4", "y-websocket": "^1.5.0", "yaml": "^2.3.4", @@ -114,7 +115,6 @@ "fsevents": "^2.3.3" }, "peerDependencies": { - "@sveltejs/kit": "^1.25.0", "svelte": "^4.0.0" } }, @@ -10095,6 +10095,11 @@ "resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.286.2.tgz", "integrity": "sha512-xwmIRy/QJoT/p5MpZw5O1Ed4T25gOjHvR4VpkJTxeMhhzRzhXA52gBRABRGL1lZImo74kWTHdMVQ/UdKB7yO0g==" }, + "node_modules/windmill-sql-datatype-parser-wasm": { + "version": "1.305.0", + "resolved": "https://registry.npmjs.org/windmill-sql-datatype-parser-wasm/-/windmill-sql-datatype-parser-wasm-1.305.0.tgz", + "integrity": "sha512-tn0yVn61g6EQp4t7zVnH6ZeL1CbjSSPinpMB8PwbxCTcv+dj5ibWRzYmNu+bqzcLjwdMTUA6VRHsbYJ3Ne4HpQ==" + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 85d7647ca7..7d63e27a71 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.304.3", + "version": "1.305.3", "scripts": { "dev": "vite dev", "build": "vite build", @@ -134,13 +134,13 @@ "vscode-uri": "~3.0.8", "vscode-ws-jsonrpc": "~3.1.0", "windmill-parser-wasm": "^1.286.2", + "windmill-sql-datatype-parser-wasm": "1.305.0", "y-monaco": "^0.1.4", "y-websocket": "^1.5.0", "yaml": "^2.3.4", "yjs": "^13.6.7" }, "peerDependencies": { - "@sveltejs/kit": "^1.25.0", "svelte": "^4.0.0" }, "exports": { diff --git a/frontend/src/lib/components/ContentSearch.svelte b/frontend/src/lib/components/ContentSearch.svelte index c282de51fa..6631f1cebb 100644 --- a/frontend/src/lib/components/ContentSearch.svelte +++ b/frontend/src/lib/components/ContentSearch.svelte @@ -10,7 +10,6 @@ import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte' import FlowIcon from './home/FlowIcon.svelte' import { Alert, Button } from './common' - import { goto } from '$app/navigation' import YAML from 'yaml' let search: string = '' @@ -41,14 +40,14 @@ let searchKind: 'all' | 'scripts' | 'flows' | 'apps' | 'resources' = 'all' - let isOpen = false; - let inputElement; + let isOpen = false + let inputElement - // Reactive statement to focus the input when the modal opens - $: if (isOpen && inputElement) { - // Use a timeout to ensure focus after any animations or rendering - setTimeout(() => inputElement.focus(), 0); - } + // Reactive statement to focus the input when the modal opens + $: if (isOpen && inputElement) { + // Use a timeout to ensure focus after any animations or rendering + setTimeout(() => inputElement.focus(), 0) + } let scripts: undefined | { path: string; content: string }[] = undefined let filteredScriptItems: { path: string; content: string; marked: any }[] = [] @@ -94,7 +93,6 @@ flows: getCounts(filteredFlowItems.length), scripts: getCounts(filteredScriptItems.length) } - {/if} diff --git a/frontend/src/lib/components/DisplayResult.svelte b/frontend/src/lib/components/DisplayResult.svelte index d88f927a66..5842ab17a5 100644 --- a/frontend/src/lib/components/DisplayResult.svelte +++ b/frontend/src/lib/components/DisplayResult.svelte @@ -119,7 +119,7 @@ let length = roughSizeOfObject(result) // Otherwise, check if the result is too large (10kb) for json - largeObject = length > 100000 + largeObject = length > 50000 if (largeObject) { return 'json' @@ -547,9 +547,9 @@
diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index 8492e07e22..aaa8f52688 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -754,20 +754,20 @@ ] } ) - } else if (lang === 'javascript') { + } else if (lang === 'typescript') { const stdLib = { content: libStdContent, filePath: 'es6.d.ts' } if (scriptLang == 'bun') { - languages.typescript.javascriptDefaults.setExtraLibs([stdLib]) + languages.typescript.typescriptDefaults.setExtraLibs([stdLib]) } else { const denoFetch = { content: denoFetchContent, filePath: 'deno_fetch.d.ts' } - languages.typescript.javascriptDefaults.setExtraLibs([stdLib, denoFetch]) + languages.typescript.typescriptDefaults.setExtraLibs([stdLib, denoFetch]) } if (scriptLang == 'bun' && ata == undefined) { const addLibraryToRuntime = async (code: string, _path: string) => { const path = 'file://' + _path let uri = mUri.parse(path) console.log('adding library to runtime', path) - languages.typescript.javascriptDefaults.addExtraLib(code, path) + languages.typescript.typescriptDefaults.addExtraLib(code, path) try { await vscode.workspace.fs.writeFile(uri, new TextEncoder().encode(code)) } catch (e) { @@ -1028,18 +1028,24 @@ initialized = true - languages.typescript.typescriptDefaults.setModeConfiguration({ - completionItems: false, - definitions: false, - hovers: false - }) - languages.typescript.typescriptDefaults.setCompilerOptions({ target: languages.typescript.ScriptTarget.Latest, allowNonTsExtensions: true, noSemanticValidation: false, noSyntaxValidation: false, - + completionItems: true, + hovers: true, + documentSymbols: true, + definitions: true, + references: true, + documentHighlights: true, + rename: true, + diagnostics: true, + documentRangeFormattingEdits: true, + signatureHelp: true, + onTypeFormattingEdits: true, + codeActions: true, + inlayHints: true, checkJs: true, allowJs: true, noUnusedLocals: true, @@ -1064,7 +1070,25 @@ inlayHints: true }) + languages.typescript.typescriptDefaults.setModeConfiguration({ + completionItems: true, + hovers: true, + documentSymbols: true, + definitions: true, + references: true, + documentHighlights: true, + rename: true, + diagnostics: true, + documentRangeFormattingEdits: true, + signatureHelp: true, + onTypeFormattingEdits: true, + codeActions: true, + inlayHints: true + }) + languages.typescript.javascriptDefaults.setEagerModelSync(true) + languages.typescript.typescriptDefaults.setEagerModelSync(true) + languages.typescript.javascriptDefaults.setDiagnosticsOptions({ noSemanticValidation: false, noSyntaxValidation: false, @@ -1072,6 +1096,13 @@ diagnosticCodesToIgnore: [1108] }) + languages.typescript.typescriptDefaults.setDiagnosticsOptions({ + noSemanticValidation: false, + noSyntaxValidation: false, + noSuggestionDiagnostics: false, + diagnosticCodesToIgnore: [1108] + }) + languages.typescript.javascriptDefaults.setCompilerOptions({ target: languages.typescript.ScriptTarget.Latest, allowNonTsExtensions: true, @@ -1083,8 +1114,7 @@ noUnusedParameters: true, noUnusedLocals: true, strict: true, - noLib: false, - + noLib: true, moduleResolution: languages.typescript.ModuleResolutionKind.NodeJs }) diff --git a/frontend/src/lib/components/FlowBuilder.svelte b/frontend/src/lib/components/FlowBuilder.svelte index 6410c62b63..d9ee7563a9 100644 --- a/frontend/src/lib/components/FlowBuilder.svelte +++ b/frontend/src/lib/components/FlowBuilder.svelte @@ -67,11 +67,10 @@ import FlowTutorials from './FlowTutorials.svelte' import { ignoredTutorials } from './tutorials/ignoredTutorials' import type DiffDrawer from './DiffDrawer.svelte' - import UnsavedConfirmationModal from './common/confirmationModal/UnsavedConfirmationModal.svelte' import { cloneDeep } from 'lodash' - import { goto } from '$app/navigation' export let initialPath: string = '' + export let pathStoreInit: string | undefined = undefined export let newFlow: boolean export let selectedId: string | undefined export let initialArgs: Record = {} @@ -84,6 +83,7 @@ }) | undefined = undefined export let diffDrawer: DiffDrawer | undefined = undefined + export let gotoEdit: (path: string, selected: string) => void const dispatch = createEventDispatcher() @@ -194,7 +194,8 @@ dispatch('saveInitial', $pathStore) } else if (savedFlow?.draft_only && $pathStore !== initialPath) { initialPath = $pathStore - goto(`/flows/edit/${$pathStore}?selected=${getSelectedId()}`) + // this is so we can use the flow builder outside of sveltekit + gotoEdit($pathStore, getSelectedId()) } sendUserToast('Saved as draft') } catch (error) { @@ -359,9 +360,9 @@ const scriptEditorDrawer = writable(undefined) const moving = writable<{ module: FlowModule; modules: FlowModule[] } | undefined>(undefined) const history = initHistory($flowStore) - const pathStore = writable(initialPath) + const pathStore = writable(pathStoreInit ?? initialPath) - $: $pathStore = initialPath + $: initialPath && ($pathStore = initialPath) const testStepStore = writable>({}) @@ -982,14 +983,7 @@ - + {#key renderCount} {#if !$userStore?.operator} diff --git a/frontend/src/lib/components/FlowStatusViewer.svelte b/frontend/src/lib/components/FlowStatusViewer.svelte index 3205a39a83..1e7efe1914 100644 --- a/frontend/src/lib/components/FlowStatusViewer.svelte +++ b/frontend/src/lib/components/FlowStatusViewer.svelte @@ -9,7 +9,7 @@ export let jobId: string export let workspaceId: string | undefined = undefined - export let flowStateStore: Writable | undefined = undefined + export let flowStateStore: Writable = writable({}) export let selectedJobStep: string | undefined = undefined export let isOwner = false diff --git a/frontend/src/lib/components/FlowStatusViewerInner.svelte b/frontend/src/lib/components/FlowStatusViewerInner.svelte index 934b9097b5..130cec48de 100644 --- a/frontend/src/lib/components/FlowStatusViewerInner.svelte +++ b/frontend/src/lib/components/FlowStatusViewerInner.svelte @@ -60,6 +60,7 @@ export let globalModuleStates: Writable>[] export let globalDurationStatuses: Writable>[] export let childFlow: boolean = false + export let reducedPolling = false let jobResults: any[] = [] let jobFailures: boolean[] = [] @@ -118,25 +119,6 @@ ) } - if (flowJobIds) { - let common = { - iteration_from: Math.max(flowJobIds.flowJobs.length - 20, 0), - iteration_total: flowJobIds?.length - } - let modId = flowJobIds?.moduleId ?? '' - $localDurationStatuses[modId] = { - ...($localDurationStatuses[modId] ?? { byJob: {} }), - ...common - } - let prefixed = modId - globalDurationStatuses.forEach((x) => - x.update((x) => { - x[prefixed] = { ...(x[prefixed] ?? { byJob: {} }), ...common } - return x - }) - ) - } - function updateForloop(len: number) { forloop_selected = flowJobIds?.flowJobs[len - 1] ?? '' lastSize = len @@ -224,17 +206,36 @@ } } if (job?.type !== 'CompletedJob' && errorCount < 4) { - timeout = setTimeout(() => loadJobInProgress(), 500) + timeout = setTimeout(() => loadJobInProgress(), reducedPolling ? 5000 : 1000) } } async function updateJobId() { if (jobId !== job?.id) { $localModuleStates = {} - $localDurationStatuses = {} flowTimeline?.reset() timeout && clearTimeout(timeout) innerModules = [] + if (flowJobIds) { + let common = { + iteration_from: Math.max(flowJobIds.flowJobs.length - 20, 0), + iteration_total: flowJobIds?.length + } + let modId = flowJobIds?.moduleId ?? '' + $localDurationStatuses[modId] = { + ...($localDurationStatuses[modId] ?? { byJob: {} }), + ...common + } + let prefixed = modId + globalDurationStatuses.forEach((x) => + x.update((x) => { + x[prefixed] = { ...(x[prefixed] ?? { byJob: {} }), ...common } + return x + }) + ) + } else { + $localDurationStatuses = {} + } await loadJobInProgress() } } @@ -312,6 +313,12 @@ ) { let modId = flowJobIds?.moduleId if (modId) { + if ($flowStateStore && $flowStateStore?.[modId] == undefined) { + $flowStateStore[modId] = { + ...$flowStateStore[modId], + previewResult: jobLoaded.args + } + } if ($flowStateStore?.[modId]) { if (!childFlow) { if ( @@ -402,6 +409,31 @@ let flowTimeline: FlowTimeline let rightColumnSelect: 'timeline' | 'detail' = 'timeline' + + let slicedListJobIds: string[] = [] + + $: flowJobIds && !deepEqual(flowJobIds, lastFlowJobIds) && updateSlicedListJobIds() + let lastFlowJobIds: any = undefined + function updateSlicedListJobIds() { + lastFlowJobIds = flowJobIds + slicedListJobIds = + (flowJobIds?.flowJobs.length ?? 0) > 20 + ? flowJobIds?.flowJobs?.slice( + $localDurationStatuses[flowJobIds?.moduleId ?? '']?.iteration_from ?? 0 + ) ?? [] + : flowJobIds?.flowJobs ?? [] + } + + function loadPreviousIters(lenToAdd: number) { + let r = $localDurationStatuses[flowJobIds?.moduleId ?? ''] + if (r.iteration_from) { + r.iteration_from -= lenToAdd + $localDurationStatuses = $localDurationStatuses + globalDurationStatuses.forEach((x) => x.update((x) => x)) + } + jobResults = [...new Array(lenToAdd), ...jobResults] + updateSlicedListJobIds() + } {#if job} @@ -418,19 +450,24 @@ )} {#if (flowJobIds?.flowJobs.length ?? 0) > 20 && lenToAdd > 0} + {@const allToAdd = (flowJobIds?.length ?? 0) - (slicedListJobIds.length ?? 0)}

For performance reasons, only the last 20 items are shown by default + {#if allToAdd > 0} + + {/if}

{/if} {#if render} @@ -520,22 +557,28 @@ Embedded flows: ({flowJobIds?.flowJobs.length} items) {#if (flowJobIds?.flowJobs.length ?? 0) > 20 && lenToAdd > 0} + {@const allToAdd = (flowJobIds?.length ?? 0) - (slicedListJobIds.length ?? 0)} +

For performance reasons, only the last 20 items are shown by default + {#if allToAdd > 0} + + {/if}

{/if} - {#each (flowJobIds?.flowJobs.length ?? 0) > 20 ? flowJobIds?.flowJobs?.slice($localDurationStatuses[flowJobIds?.moduleId ?? '']?.iteration_from ?? 0) ?? [] : flowJobIds?.flowJobs ?? [] as loopJobId, j (loopJobId)} + {#each slicedListJobIds as loopJobId, j (loopJobId)} {#if render} {/key} diff --git a/frontend/src/lib/components/apps/components/display/AppCustomComponent.svelte b/frontend/src/lib/components/apps/components/display/AppCustomComponent.svelte index 4382c9d1c8..5d99d9c4e3 100644 --- a/frontend/src/lib/components/apps/components/display/AppCustomComponent.svelte +++ b/frontend/src/lib/components/apps/components/display/AppCustomComponent.svelte @@ -62,18 +62,21 @@ //@ts-ignore await import( /* @vite-ignore */ + /* webpackIgnore: true */ `https://unpkg.com/react@${reactVersion}/umd/react.production.min.js` ) //@ts-ignore await import( /* @vite-ignore */ + /* webpackIgnore: true */ `https://unpkg.com/react-dom@${reactVersion}/umd/react-dom.production.min.js` ) } //@ts-ignore await import( /* @vite-ignore */ + /* webpackIgnore: true */ `/api/w/${workspace ?? 'NO_W'}/resources_u/custom_component/${customComponent.name}` ) loaded = true diff --git a/frontend/src/lib/components/apps/components/display/AppDownload.svelte b/frontend/src/lib/components/apps/components/display/AppDownload.svelte index 133f3fdfa9..8b06d11130 100644 --- a/frontend/src/lib/components/apps/components/display/AppDownload.svelte +++ b/frontend/src/lib/components/apps/components/display/AppDownload.svelte @@ -34,18 +34,30 @@ let beforeIconComponent: any let afterIconComponent: any - $: resolvedConfig.beforeIcon && handleBeforeIcon() - $: resolvedConfig.afterIcon && handleAfterIcon() + $: resolvedConfig.beforeIcon && beforeIconComponent && handleBeforeIcon() + $: resolvedConfig.afterIcon && afterIconComponent && handleAfterIcon() async function handleBeforeIcon() { if (resolvedConfig.beforeIcon) { - beforeIconComponent = await loadIcon(resolvedConfig.beforeIcon) + beforeIconComponent = await loadIcon( + resolvedConfig.beforeIcon, + beforeIconComponent, + 14, + undefined, + undefined + ) } } async function handleAfterIcon() { if (resolvedConfig.afterIcon) { - afterIconComponent = await loadIcon(resolvedConfig.afterIcon) + afterIconComponent = await loadIcon( + resolvedConfig.afterIcon, + afterIconComponent, + 14, + undefined, + undefined + ) } } @@ -101,14 +113,18 @@ nonCaptureEvent > - {#if resolvedConfig.beforeIcon && beforeIconComponent} - + {#if resolvedConfig.beforeIcon} + {#key resolvedConfig.beforeIcon} +
+ {/key} {/if} {#if resolvedConfig.label && resolvedConfig.label?.length > 0}
{resolvedConfig.label}
{/if} - {#if resolvedConfig.afterIcon && afterIconComponent} - + {#if resolvedConfig.afterIcon} + {#key resolvedConfig.afterIcon} +
+ {/key} {/if} diff --git a/frontend/src/lib/components/apps/components/display/AppHtml.svelte b/frontend/src/lib/components/apps/components/display/AppHtml.svelte index 701d95243e..7d0b4e873c 100644 --- a/frontend/src/lib/components/apps/components/display/AppHtml.svelte +++ b/frontend/src/lib/components/apps/components/display/AppHtml.svelte @@ -5,7 +5,6 @@ import type { AppViewerContext, ComponentCustomCSS } from '../../types' import { initCss } from '../../utils' import RunnableWrapper from '../helpers/RunnableWrapper.svelte' - import { twMerge } from 'tailwind-merge' import ResolveStyle from '../helpers/ResolveStyle.svelte' export let id: string @@ -14,7 +13,7 @@ export let customCss: ComponentCustomCSS<'htmlcomponent'> | undefined = undefined export let render: boolean - const { app, worldStore, mode } = getContext('AppViewerContext') + const { app, worldStore } = getContext('AppViewerContext') const outputs = initOutput($worldStore, id, { result: undefined, @@ -22,8 +21,6 @@ }) let result: string | undefined = undefined - let h: number | undefined = undefined - let w: number | undefined = undefined let css = initCss($app.css?.htmlcomponent, customCss) @@ -43,8 +40,6 @@ e?.preventDefault() }} class="h-full w-full" - bind:clientHeight={h} - bind:clientWidth={w} > - {#key result} -