Compare commits

...
146 Commits
Author SHA1 Message Date
Ruben Fiszelandrubenfiszel 0fb96ec3c3 chore(main): release 1.341.0 (#3861)
* chore(main): release 1.341.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-06-03 17:24:33 +02:00
Ruben Fiszel 44c36cdeb5 fix: fix python client for S3Object 2024-06-03 17:20:29 +02:00
Ruben Fiszel fb953b7fc7 fix rawresult 2024-06-03 16:10:26 +02:00
203264b871 feat: warn when jobs spent a long time waiting in queue (#3856)
* Store jobs that waited for too long

* Add warnings as badges for long waited jobs

* Separate into self_wait_time and aggregate

Change the UI accordingly

* Prepare sqlx

* Update backend/windmill-queue/src/jobs.rs

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Fix incorrect query

* Prepare sqlx

* Move insert to pull + UI fixes

Insert as soon as the job is pulled and therefore started.
Add a badge on the lfow timeline to show the self wait time

* Move to after the pull in the worker

Move the logic to after the pull in the worker in the case its not a
noop

* Remove weird line

* Remove unnecessary async

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2024-06-03 16:05:15 +02:00
Faton Ramadani 76b65771a0 feat(frontend): Fix how runnable tied to a table actions are triggered + Display the sync columnDef error only in the editor (#3862) 2024-06-03 16:02:21 +02:00
Ruben Fiszel 5ff7477c7d fix rawresult 2024-06-03 15:46:19 +02:00
Ruben Fiszel 181cb7dec9 fix: further restrict job api to logged in workspace users or anonymous jobs only" (#3860) 2024-06-03 15:13:15 +02:00
Ruben Fiszelandrubenfiszel 2c19fde250 chore(main): release 1.340.2 (#3855)
* chore(main): release 1.340.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-31 22:37:23 +02:00
Ruben Fiszel 2359cdc128 fix: add audit log exception to schedules 2024-05-31 22:29:15 +02:00
Ruben Fiszel 326446e5ce fix: fix csv preview for storage renderer 2024-05-31 14:23:27 +02:00
Ruben Fiszelandrubenfiszel 5c5b475261 chore(main): release 1.340.1 (#3854)
* chore(main): release 1.340.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-31 13:30:01 +02:00
Ruben Fiszel 9e822d4c75 fix: typescript file upload supports arbitrary storage 2024-05-31 13:26:51 +02:00
Ruben Fiszelandrubenfiszel 2c16a20814 chore(main): release 1.340.0 (#3849)
* chore(main): release 1.340.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-31 12:58:38 +02:00
Ruben Fiszel 8ffceb9a31 fix go client build 2024-05-31 12:58:17 +02:00
Ruben Fiszel be160f6e46 fix: simple subflow approval step triggering timeouts 2024-05-31 12:50:29 +02:00
Ruben Fiszel 9308e2a63c fix compile issue 2024-05-31 12:30:58 +02:00
Ruben Fiszel d53fbfc039 fix compile issue 2024-05-31 12:15:25 +02:00
Ruben Fiszel a22dc985fa feat: support multiple object storage + parquet_csv + polars -> datafusion" (#3853)
* multiple storage

* all

* rm symlinks

* all

* all
2024-05-31 11:59:51 +02:00
wendrul 5156e291fa feat: chart interactivity: click points on the graph to select the corresponding jobs (#3851)
* Make click on RunChart higlight and select job

* Select job when clicking on graph point

* Fix type of chart data object

* Persist selection on refresh and other changes
2024-05-30 19:26:11 +02:00
Ruben Fiszel 9b7b650d8b table small improvements 2024-05-30 15:05:42 +02:00
Ruben Fiszel 24889fb3a0 further fix to normal tables 2024-05-30 11:31:45 +02:00
Ruben Fiszel 96246cd697 fix: wait for api to be read to load explorer table 2024-05-30 11:30:18 +02:00
Ruben Fiszel cefa12b551 remove donePromise 2024-05-30 11:01:55 +02:00
Ruben Fiszel 660f38ecd0 remove donePromise 2024-05-30 10:59:10 +02:00
Ruben Fiszel 198ee29110 add renew license key for tests 2024-05-30 08:19:42 +02:00
Ruben Fiszel 3b051c4992 improve sort and search for parquet preview 2024-05-30 00:50:52 +02:00
Ruben Fiszel 76d517ef01 fix ee.rs 2024-05-29 23:51:38 +02:00
Ruben Fiszel e07c2621e9 feat: replace polars with datafusion for data preview 2024-05-29 23:38:36 +02:00
Ruben Fiszelandrubenfiszel 2558cfa9f5 chore(main): release 1.339.2 (#3846)
* chore(main): release 1.339.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-29 19:16:18 +02:00
HugoCasa e052dd5f6e fix: worker memory usage (#3845) 2024-05-29 18:16:41 +02:00
Ruben Fiszelandrubenfiszel 8a4d9c9ff3 chore(main): release 1.339.1 (#3844)
* chore(main): release 1.339.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-29 17:18:49 +02:00
Ruben Fiszel 7238274d1c fix: allow_user_resoruces default deserialization 2024-05-29 17:10:20 +02:00
Ruben Fiszelandrubenfiszel 3dea341a30 chore(main): release 1.339.0 (#3843)
* chore(main): release 1.339.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-29 16:32:13 +02:00
HugoCasa dc2d7e1c8f feat: display last key renewal attempt (#3839)
* feat: display last key renewal attempt

* feat: improve UI + add renew button + dev instance

* fix: nits

* chore: update ee ref

* fix: nit

* fix: tests
2024-05-29 16:28:00 +02:00
Ruben Fiszel 6b2299f7a8 resource others page fix 2024-05-29 15:02:52 +02:00
Ruben Fiszelandrubenfiszel 2294ce2f3b chore(main): release 1.338.3 (#3841)
* chore(main): release 1.338.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-29 13:00:48 +02:00
Ruben Fiszel 717ecb93dd remove unecessary formatter black since ruff format now 2024-05-29 12:54:24 +02:00
Ruben Fiszel b01e33523d fix: fix resource type search 2024-05-29 12:09:24 +02:00
Ruben Fiszelandrubenfiszel 08b16f86b1 chore(main): release 1.338.2 (#3840)
* chore(main): release 1.338.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-29 01:49:50 +02:00
Ruben Fiszel e7763375d6 jemalloc for all 2024-05-29 01:44:37 +02:00
Ruben Fiszel b6b5eef0f3 remove heap profiling by default 2024-05-29 01:20:23 +02:00
HugoCasa 5d2b244869 fix: worker metrics (#3837)
* fix: worker metrics

* chore: sqlx

* chore: update ee ref

* fix: remove jemalloc stats unwrap
2024-05-29 01:12:00 +02:00
Ruben Fiszelandrubenfiszel c904d9c041 chore(main): release 1.338.1 (#3831)
* chore(main): release 1.338.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-28 17:01:20 +02:00
Ruben Fiszel 8b66636a89 fix: remove quotes around interpolated arg values of tags 2024-05-28 16:56:27 +02:00
Henri Courdentandellipsis-dev[bot] ac8118c409 Links update & stroke width icons (#3833)
* Links update & stroke width icons

* Update frontend/src/lib/components/StringTypeNarrowing.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2024-05-28 16:05:56 +02:00
Ruben Fiszel 6166c4d7aa fix: fix retry not working on single step flow due to opt 2024-05-28 10:48:41 +02:00
Ruben Fiszelandrubenfiszel e5db421b1b chore(main): release 1.338.0 (#3819)
* chore(main): release 1.338.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-27 20:45:46 +02:00
Faton Ramadani c246bb0705 feat(frontend): add open/close state of the modal in the outputs (#3822)
* feat(frontend): add open/close state of the modal in the outputs

* feat(frontend): add onOpen/onClose event handlers

* feat(frontend): add onOpen/onClose event hander

* feat(frontend): improve close logic for drawers

* feat(frontend): refactor handleSideEffect into an util file

* feat(frontend): improve code

* feat(frontend): improve naming

* feat(frontend): improve code

* feat(frontend): improve code

* feat(frontend): remove on Open/Close actions

* feat(frontend): simplify the implementation

* feat(frontend): fix callbacks
2024-05-27 20:32:07 +02:00
HugoCasa 621464b550 feat: worker vcpus/memory limits + mem usage (#3828) 2024-05-27 18:43:02 +02:00
HugoCasa 256185308e feat(frontend): upgrade to gpt-4o + add AI support for php (#3820)
* feat: upgrade to gpt-4o

* feat: improve code completion + UI stuff
2024-05-27 18:29:42 +02:00
wendrul 1f7be465ad Improve filter on queue (#3829) 2024-05-27 18:21:53 +02:00
Ruben Fiszel adcf37d313 add opensearchpy to lib.rs mapping 2024-05-27 16:41:30 +02:00
Henri Courdent ecc8466b88 Changelog update frontend (#3824) 2024-05-27 15:58:31 +02:00
wendrul 47df9f33cc fix: filtering not always working with concurrency keys (#3823)
* fix missing filtering on ommision of obscured jobs

Also allow cron and scheduled jobs for the filtering security

* Revert incorrect change

* Revert frontend change
2024-05-27 15:58:07 +02:00
Ruben Fiszel b58c6257a6 set last_ping to null when requeuing because of concurrency limits 2024-05-27 15:53:32 +02:00
Ruben Fiszel 40045e0c0f clarify iframe for apps 2024-05-27 14:06:27 +02:00
Ruben Fiszel b13f42ab4e fix sqlx 2024-05-27 13:08:47 +02:00
Ruben Fiszel e2a1219373 feat: public apps can require login (#3825) 2024-05-27 13:03:41 +02:00
Ruben Fiszel 999d2e4745 remove supabase_wizard from oauth connects 2024-05-27 09:47:55 +02:00
Ruben Fiszel b5caf0777d fix resources connects 2024-05-27 09:26:41 +02:00
Ruben Fiszel 5877727c16 feat: allow user resources in apps with a toggle (#3821)
* all

* all

* all

* all

* all

* all

* all

* all

* all

* all

* nits

* nits
2024-05-27 07:51:49 +02:00
Ruben Fiszel 3c74da4116 increase min re-scheduling 2024-05-26 05:20:11 +02:00
Ruben Fiszel e397a385e2 reschedule to at least 1secs in future 2024-05-26 05:04:42 +02:00
Ruben Fiszel 7a36f30fe3 fix: make all error strings more verbose 2024-05-25 22:15:15 +02:00
Ruben Fiszel 7a664b5cd4 nit improvements for concurrency jobs 2024-05-25 17:28:32 +02:00
Ruben Fiszel 545d982419 nit improvements for concurrency jobs 2024-05-25 17:26:08 +02:00
Ruben Fiszel f2d9c3c777 fix: improve concurrency re-scheduling at scale 2024-05-25 17:20:11 +02:00
Ruben Fiszel e187fa6263 fix: improve concurrency re-scheduling at scale 2024-05-25 15:56:56 +02:00
Ruben Fiszelandrubenfiszel af5c31e6d4 chore(main): release 1.337.0 (#3811)
* chore(main): release 1.337.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-25 12:00:58 +02:00
Ruben Fiszel 7fdfb9b006 fix build 2024-05-25 11:47:47 +02:00
Ruben Fiszel 664dcee837 fix build 2024-05-25 10:54:14 +02:00
HugoCasa 47bb5d2492 fix: use hub script language as tag instead of 'hub' (#3816)
* fix: use hub script language as tag instead of 'hub'

* fix: remove hub tag
2024-05-25 10:38:03 +02:00
Ruben Fiszel c070320add fix oss build 2024-05-25 10:34:11 +02:00
Ruben Fiszel e351a93efb fix build 2024-05-25 09:59:38 +02:00
Ruben Fiszel ee22ec5fd1 fix build 2024-05-25 09:54:02 +02:00
HugoCasaandRuben Fiszel 831cf89b63 feat: automatic key renewal (#3815)
* feat: automatic ee key renewal

* chore: sqlx

* chore: update ee repo ref

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2024-05-24 19:49:45 +02:00
HugoCasa 7584c2b0bb fix: rename email_from_username to username_to_email (#3813) 2024-05-24 17:03:44 +02:00
William Butez 59f980f75a feat: add GetResumeUrls to go client (#3810)
* feat: add GetResumeUrls to go client

* add type ResumeUrls
2024-05-24 12:47:50 +02:00
Ruben Fiszelandrubenfiszel 319cfb7dc1 chore(main): release 1.336.1 (#3809)
* chore(main): release 1.336.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-24 08:23:47 +02:00
Ruben Fiszel ba9cdb1ae2 fix: revert bun to 1.1.8 2024-05-24 08:07:41 +02:00
Ruben Fiszelandrubenfiszel 141ae06ad1 chore(main): release 1.336.0 (#3796)
* chore(main): release 1.336.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-23 22:19:05 +02:00
Ruben Fiszel 3680c292f8 add more infos about hanging monitor last ping 2024-05-23 22:14:31 +02:00
Faton Ramadani a0acdc1217 fix(frontend): Add missing loading state for non-runnable components … (#3797)
* fix(frontend): Add missing loading state for non-runnable components + fix select and aggrid styling

* fix(frontend): remove log

* fix(frontend): improve code

* fix(frontend): improve code

* fix(frontend): Fix refreshIndicator styling
2024-05-23 20:36:39 +02:00
HugoCasa 001278cddd feat: improve parsers when no main func (#3805)
* feat: improve parsers when no main func

* chore: update parser version
2024-05-23 20:36:16 +02:00
d11e350de3 feat(frontend): improve graph edges + fix depedencies detection (#3802)
* feat(frontend): improve graph edges + fix depedencies detection

* Update frontend/src/lib/components/graph/svelvet/edges/views/Edges/SimpleBezierEdge.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2024-05-23 20:17:34 +02:00
Ruben Fiszel 62e88169ea feat: store failed_retries per module state and display failed retries in flow status viewer 2024-05-23 19:26:20 +02:00
Ruben Fiszel 7e0be8914b feat: store failed_retries per module state and display failed retries in flow status viewer 2024-05-23 19:16:26 +02:00
HugoCasa 62f318077c feat: improve permissioned audit logs (#3799)
* fix: increase token label size in db

* Revert "Revert "feat:  improve premissioned audit logs (#3793)" (#3798)"

This reverts commit 43a24d997e.

* feat: add username to email function

* fix: nit

* fix: add docstring to global func
2024-05-23 17:23:50 +02:00
wendrul 1745a9dd16 fix: show code option in tree view (#3803)
* fix: show code option in tree view

* Update TreeViewRoot.svelte
2024-05-23 16:49:18 +02:00
wendrul a8d9a400e2 Add concurrency key for inline scripts in flows (#3801) 2024-05-23 14:59:18 +02:00
Ruben Fiszel 43a24d997e Revert "feat: improve premissioned audit logs (#3793)" (#3798)
This reverts commit 21a077ecfa.
2024-05-23 11:12:51 +02:00
Ruben Fiszel bfd2d27415 fix: update bun to 1.1.9 2024-05-23 09:24:38 +02:00
HugoCasa 21a077ecfa feat: improve premissioned audit logs (#3793)
* feat:  improve premissioned audit logs

* chore: update ee ref

* fix: build

* fix: sqlx
2024-05-23 08:55:48 +02:00
Jeremy Worden 068190f922 Update lib.rs (#3795)
add ldap=>python-ldap remapping
2024-05-23 08:53:42 +02:00
Ruben Fiszelandrubenfiszel 3f49d3e061 chore(main): release 1.335.0 (#3792)
* chore(main): release 1.335.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-22 23:20:31 +02:00
Ruben Fiszel ebe2212982 add concurrency_key to exported workspace scripts 2024-05-22 23:12:13 +02:00
Ruben Fiszel 4d28a38750 fix(cli): add concurrency key to script 2024-05-22 22:22:19 +02:00
wendrulandRuben Fiszel 59b0adea8a Add warning for omitted obscured jobs (#3790)
* Add warning for omitted obscured jobs

* Update RunsTable.svelte

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2024-05-22 21:14:52 +02:00
Faton Ramadani 85cd8b4c0e fix(frontend): Fix aggrid infinite refresh (#3789)
* fix(frontend): Fix AgGrid infinit refresh when args changed

* fix(frontend): Fix AgGrid infinit refresh when args changed

* fix(frontend): remove dead code
2024-05-22 16:57:45 +02:00
HugoCasa 2f370de628 feat: improve user audit logs and stats (#3786)
* fix: improve user audit logs and stats

* chore: sqlx

* fix: no features build

* fix: sqlx

* fix: no features build

* chore: update ee ref
2024-05-22 16:51:04 +02:00
Ruben Fiszel 2883fc9f8e make drop cache not an error 2024-05-22 13:16:53 +02:00
Ruben Fiszel 4d88dadb1f remove jemalloc specific image 2024-05-22 11:44:37 +02:00
Ruben Fiszelandrubenfiszel 686c188ad5 chore(main): release 1.334.0 (#3785)
* chore(main): release 1.334.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-22 00:44:47 +02:00
Ruben Fiszel b30d239a2b nit 2024-05-22 00:44:25 +02:00
Ruben Fiszel 4631c3fd08 fix: add allow http toggle to object store settings 2024-05-22 00:36:04 +02:00
Faton Ramadani 59c0abae3d feat(frontend): Added support for title and placeholder for ArgInputs (#3779)
* feat(frontend): Added support for customLabel and placeholder

* feat(frontend): correctly handle labels

* feat(frontend): rename customLabel into title

* feat(frontend): fix layout

* feat(frontend): properly implement placeholder

* feat(frontend): properly implement placeholder

* feat(frontend): add missing undefined check

* feat(frontend): remove code duplication
2024-05-21 21:58:48 +02:00
Faton Ramadani 36df8389cd feat(frontend): Improve multiselect perf (#3770)
* feat(frontend): wip

* feat(frontend): Fork multiselect

* feat(frontend): cleanup

* feat(frontend): fix design

* feat(frontend): trie search

* feat(frontend): simplify search

* feat(frontend): simplify search

* feat(frontend): fix open
2024-05-21 19:47:19 +02:00
Faton Ramadani 518d8b916b fix(frontend): Fix path overflow on the Runs page (#3781) 2024-05-21 19:46:53 +02:00
wendrul 2efe5f9f10 Win 130 concurrency observability fixes (#3782)
* Resize badge and add filter by key button

* Make status filters icononly with tooltip

* nit: replace current job None with empty

* tooltip should be on the same row with flex

* Expand selected on ToggleButtonMore

* Make a common definition of UnifiedJob fields
2024-05-21 19:28:05 +02:00
Ruben Fiszelandrubenfiszel 7a8a08f31e chore(main): release 1.333.5 (#3776)
* chore(main): release 1.333.5

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-21 12:26:03 +02:00
wendrulandRuben Fiszel 1001b1e664 Fix list jobs and intervals mismatch (#3767)
* fix: mismatch when filtering on concurrency key

Fix a mismatch between to endpoints when filtering by concurrency key

* Add ObscuredJob type on openapi spec

* Correct unit for graph

* Finish frontend changes

* Add field indicating if obscured jobs were omitted

* impl from for ListQueueQuery and factor logic

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2024-05-21 12:21:25 +02:00
Ruben Fiszel b56fbdf898 fix: improve concurrency key migration 2024-05-21 12:18:05 +02:00
Ruben Fiszel 0268dd1206 fix: drop the linux file cache regularly to avoid triggering OOM killer 2024-05-21 10:21:14 +02:00
Faton Ramadani edf3015cc4 fix(frontend): Fix full height component for public apps (#3777)
* fix(frontend): fix fullHeight component for public apps

* fix(frontend): fix fullHeight component for public apps

* fix(frontend): fix fullHeight component for public apps
2024-05-21 10:07:00 +02:00
Faton Ramadani 31c47774cd fix(frontend): Fix selected value when the default value of a select component is null (#3778) 2024-05-21 09:06:12 +02:00
Ruben Fiszel da3b0434e9 fix: lighten watermark on public apps for ee 2024-05-21 07:50:47 +02:00
Ruben Fiszel aa60952ac3 frontend nits 2024-05-21 07:28:31 +02:00
Ruben Fiszelandrubenfiszel 240a96d4f1 chore(main): release 1.333.4 (#3775)
* chore(main): release 1.333.4

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-20 23:30:48 +02:00
Ruben Fiszel b2958be7c1 fix(cli): make bun the default language in absence of wmill defaultTs 2 2024-05-20 23:27:08 +02:00
Ruben Fiszelandrubenfiszel 158be28a52 chore(main): release 1.333.3 (#3774)
* chore(main): release 1.333.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-20 23:16:05 +02:00
Ruben Fiszel fbfad5e654 update git sync hub script 2024-05-20 23:15:05 +02:00
Ruben Fiszel 83990869bc fix(cli): make bun the default language in absence of wmill defaultTs 2024-05-20 23:09:38 +02:00
Ruben Fiszel 8cee11e32c use jemalloc for normal ee 2024-05-20 20:03:01 +02:00
Ruben Fiszel 0d78a31415 nit compile 2024-05-20 19:45:00 +02:00
Ruben Fiszelandrubenfiszel e7e7360259 chore(main): release 1.333.2 (#3772)
* chore(main): release 1.333.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-20 19:19:42 +02:00
d10sfanandellipsis-dev[bot] a3d81dfdce AgGrid - Allow to de-select all rows with setSelectedIndex (#3760)
* AgGrid - Allow to de-select all rows with setSelectedIndex

* Update frontend/src/lib/components/apps/components/display/table/AppAggridTable.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Else & check for null instead of -1

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2024-05-20 18:59:56 +02:00
Ruben Fiszel da091cbad7 only enable profiling if env variable is present 2024-05-20 18:57:26 +02:00
Ruben Fiszel f451748faa allow dynamic heap profiling using jemalloc live prof_active 2024-05-20 18:44:03 +02:00
Faton Ramadani ccc2699d4e fix(frontend): fix AgGrid pagination refresh (#3773)
* feat(frontend): fix AgGrid pagination refresh

* feat(frontend): fix AgGrid pagination refresh
2024-05-20 15:25:18 +02:00
Ruben Fiszelandrubenfiszel 73ddc46ce7 chore(main): release 1.333.1 (#3771)
* chore(main): release 1.333.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-20 12:35:28 +02:00
Ruben Fiszel d167053878 remove extra tracing 2024-05-20 12:34:15 +02:00
Ruben Fiszel cd8b14a2fa further memory reduction 2024-05-20 11:38:11 +02:00
Ruben Fiszel 46c440f41a use RawValue for Flow value and hub script schema 2024-05-20 10:45:52 +02:00
d10sfan 158a83b0a9 Add support for form schema property setting textarea rows value (#3759) 2024-05-20 10:24:46 +02:00
Ruben Fiszel f1bb7cfcbd fix(backend): improve memory usage by making schema RawValue instead of serde_json::Value 2024-05-20 10:11:47 +02:00
Ruben Fiszelandrubenfiszel 4a49dc6df4 chore(main): release 1.333.0 (#3769)
* chore(main): release 1.333.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-19 22:31:57 +02:00
Ruben Fiszel f63c8349f4 sleep handle f64 2024-05-19 22:21:18 +02:00
Ruben Fiszel 5eeadb9240 handle early stop for simple flows 2024-05-19 22:07:06 +02:00
Ruben Fiszel 7a1808e951 feat: reduce memory usage (#3768)
* all

* all

* optimize deserialize

* all

* all

* fix issue

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile

* fix compile
2024-05-19 21:58:38 +02:00
Ruben Fiszelandrubenfiszel 03519f5cac chore(main): release 1.332.1 (#3766)
* chore(main): release 1.332.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-18 10:12:45 +02:00
Ruben Fiszel 32bf061627 fix(cli): improve handling of schema for script bundles 2024-05-18 10:00:19 +02:00
HugoCasaandellipsis-dev[bot] f0b3527e53 fix(frontend): improve json display for large table objects (#3765)
* fix(frontend): fix check for displaying table-col

* fix: improve display result json limit for tables

* fix: nit

* Update frontend/src/lib/components/DisplayResult.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* fix: nit

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2024-05-17 18:45:13 +02:00
Ruben Fiszel ed54974ebd chore: fix tag_latest to wait for build 2024-05-17 01:05:50 +02:00
Ruben Fiszelandrubenfiszel 583e132da9 chore(main): release 1.332.0 (#3755)
* chore(main): release 1.332.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-05-17 00:35:22 +02:00
Faton RamadaniandRuben Fiszel e11a3751c3 feat(frontend): Fix App Select component initial value (#3752)
* feat(frontend): Fix App Select component initial value

* Update AppSelect.svelte

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2024-05-17 00:31:32 +02:00
Ruben Fiszel 2b06d9ae79 fix: fix args interpolation for tag and concurrency key for non string values 2024-05-17 00:27:38 +02:00
340 changed files with 10798 additions and 34661 deletions
+5 -66
View File
@@ -74,7 +74,7 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
build-args: |
features=embedding,parquet,openidconnect
features=embedding,parquet,openidconnect,jemalloc
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:dev
${{ steps.meta-public.outputs.tags }}
@@ -136,7 +136,7 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee:dev
${{ steps.meta-ee-public.outputs.tags }}
@@ -199,7 +199,7 @@ jobs:
platforms: linux/amd64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc
PYTHON_IMAGE=python:3.12.2-slim-bookworm
tags: |
${{ steps.meta-ee-public-py312.outputs.tags }}
@@ -207,67 +207,6 @@ jobs:
${{ steps.meta-ee-public-py312.outputs.labels }}
org.opencontainers.image.licenses=Windmill-Enterprise-License
build_ee_jemalloc:
runs-on: ubicloud
if: ${{ startsWith(github.ref, 'refs/tags/') }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Read EE repo commit hash
run: |
echo "ee_repo_ref=$(cat ./backend/ee-repo-ref.txt)" >> "$GITHUB_ENV"
- uses: actions/checkout@v3
with:
repository: windmill-labs/windmill-ee-private
path: ./windmill-ee-private
ref: ${{ env.ee_repo_ref }}
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
fetch-depth: 0
# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v2
- uses: depot/setup-action@v1
- name: Docker meta
id: meta-ee-public-jemalloc
uses: docker/metadata-action@v4
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-jemalloc
flavor: |
latest=false
tags: |
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Login to registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Substitute EE code
run: |
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
- name: Build and push publicly ee
uses: depot/build-push-action@v1
with:
context: .
platforms: linux/amd64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc
tags: |
${{ steps.meta-ee-public-jemalloc.outputs.tags }}
labels: |
${{ steps.meta-ee-public-jemalloc.outputs.labels }}
org.opencontainers.image.licenses=Windmill-Enterprise-License
# disabled until we make it 100% reliable and add more meaningful tests
# playwright:
# runs-on: [self-hosted, new]
@@ -415,7 +354,7 @@ jobs:
tag_latest:
runs-on: ubicloud
needs: [run_integration_test]
needs: [run_integration_test, build]
steps:
- uses: actions/checkout@v3
with:
@@ -433,7 +372,7 @@ jobs:
tag_latest_ee:
runs-on: ubicloud
needs: [run_integration_test]
needs: [run_integration_test, build_ee]
steps:
- uses: actions/checkout@v3
with:
+239
View File
@@ -1,5 +1,244 @@
# Changelog
## [1.341.0](https://github.com/windmill-labs/windmill/compare/v1.340.2...v1.341.0) (2024-06-03)
### Features
* **frontend:** Fix how runnable tied to a table actions are triggered + Display the sync columnDef error only in the editor ([#3862](https://github.com/windmill-labs/windmill/issues/3862)) ([76b6577](https://github.com/windmill-labs/windmill/commit/76b65771a03e35b6d489731f210e24640efda54b))
* warn when jobs spent a long time waiting in queue ([#3856](https://github.com/windmill-labs/windmill/issues/3856)) ([203264b](https://github.com/windmill-labs/windmill/commit/203264b87174b9774819bcf008bc4c41b866ccd9))
### Bug Fixes
* fix python client for S3Object ([44c36cd](https://github.com/windmill-labs/windmill/commit/44c36cdeb53eeb577dc7af6c2d64b75824492e1d))
* further restrict job api to logged in workspace users or anonymous jobs only" ([#3860](https://github.com/windmill-labs/windmill/issues/3860)) ([181cb7d](https://github.com/windmill-labs/windmill/commit/181cb7dec99d92b6e7450e4a0f5af75994c82ec3))
## [1.340.2](https://github.com/windmill-labs/windmill/compare/v1.340.1...v1.340.2) (2024-05-31)
### Bug Fixes
* add audit log exception to schedules ([2359cdc](https://github.com/windmill-labs/windmill/commit/2359cdc128ebfdd3fc2eff97877ae9957def9270))
* fix csv preview for storage renderer ([326446e](https://github.com/windmill-labs/windmill/commit/326446e5cefb8e99142d13ea030d51c5d317eaf9))
## [1.340.1](https://github.com/windmill-labs/windmill/compare/v1.340.0...v1.340.1) (2024-05-31)
### Bug Fixes
* typescript file upload supports arbitrary storage ([9e822d4](https://github.com/windmill-labs/windmill/commit/9e822d4c75152e7a651f31c74ee0d2c9783cd993))
## [1.340.0](https://github.com/windmill-labs/windmill/compare/v1.339.2...v1.340.0) (2024-05-31)
### Features
* chart interactivity: click points on the graph to select the corresponding jobs ([#3851](https://github.com/windmill-labs/windmill/issues/3851)) ([5156e29](https://github.com/windmill-labs/windmill/commit/5156e291fa818388bcf5734cb05a3095f6bf1b11))
* replace polars with datafusion for data preview ([e07c262](https://github.com/windmill-labs/windmill/commit/e07c2621e91a44fa6de7244469aa80e20b562b01))
* support multiple object storage + parquet_csv + polars -&gt; datafusion" ([#3853](https://github.com/windmill-labs/windmill/issues/3853)) ([a22dc98](https://github.com/windmill-labs/windmill/commit/a22dc985fa6f1b49e56fa0f3d4f5152a50e16a04))
### Bug Fixes
* simple subflow approval step triggering timeouts ([be160f6](https://github.com/windmill-labs/windmill/commit/be160f6e46d766bbdc0dd2f60b5fb5e6222809d7))
* wait for api to be read to load explorer table ([96246cd](https://github.com/windmill-labs/windmill/commit/96246cd697bfa82d0890f37a3708c7a376a5de28))
## [1.339.2](https://github.com/windmill-labs/windmill/compare/v1.339.1...v1.339.2) (2024-05-29)
### Bug Fixes
* worker memory usage ([#3845](https://github.com/windmill-labs/windmill/issues/3845)) ([e052dd5](https://github.com/windmill-labs/windmill/commit/e052dd5f6e7d8f1f7799204dab2f98e023efaec1))
## [1.339.1](https://github.com/windmill-labs/windmill/compare/v1.339.0...v1.339.1) (2024-05-29)
### Bug Fixes
* allow_user_resoruces default deserialization ([7238274](https://github.com/windmill-labs/windmill/commit/7238274d1c7b80e831aa91eac3a6577d9ab462d4))
## [1.339.0](https://github.com/windmill-labs/windmill/compare/v1.338.3...v1.339.0) (2024-05-29)
### Features
* display last key renewal attempt ([#3839](https://github.com/windmill-labs/windmill/issues/3839)) ([dc2d7e1](https://github.com/windmill-labs/windmill/commit/dc2d7e1c8f5f7c50be04cfea6986ce03a3e33c7b))
## [1.338.3](https://github.com/windmill-labs/windmill/compare/v1.338.2...v1.338.3) (2024-05-29)
### Bug Fixes
* fix resource type search ([b01e335](https://github.com/windmill-labs/windmill/commit/b01e33523da72050bc08b47bd84e0d8fc88f6dda))
## [1.338.2](https://github.com/windmill-labs/windmill/compare/v1.338.1...v1.338.2) (2024-05-28)
### Bug Fixes
* worker metrics ([#3837](https://github.com/windmill-labs/windmill/issues/3837)) ([5d2b244](https://github.com/windmill-labs/windmill/commit/5d2b244869fb9a6a7d006cfc95b22d9e83d3b9bb))
## [1.338.1](https://github.com/windmill-labs/windmill/compare/v1.338.0...v1.338.1) (2024-05-28)
### Bug Fixes
* fix retry not working on single step flow due to opt ([6166c4d](https://github.com/windmill-labs/windmill/commit/6166c4d7aae9eddcee92f950959b9d2290bc917a))
* remove quotes around interpolated arg values of tags ([8b66636](https://github.com/windmill-labs/windmill/commit/8b66636a8908c0043d2be63c6462ce28acc43fd9))
## [1.338.0](https://github.com/windmill-labs/windmill/compare/v1.337.0...v1.338.0) (2024-05-27)
### Features
* allow user resources in apps with a toggle ([#3821](https://github.com/windmill-labs/windmill/issues/3821)) ([5877727](https://github.com/windmill-labs/windmill/commit/5877727c167bf9b62bedaa7eeafad3c913b1089d))
* **frontend:** add open/close state of the modal in the outputs ([#3822](https://github.com/windmill-labs/windmill/issues/3822)) ([c246bb0](https://github.com/windmill-labs/windmill/commit/c246bb07052e65e9b336529ad638bcb9cc9686cd))
* **frontend:** upgrade to gpt-4o + add AI support for php ([#3820](https://github.com/windmill-labs/windmill/issues/3820)) ([2561853](https://github.com/windmill-labs/windmill/commit/256185308e2c0f1b5395a76bc7de5d3857f867d4))
* public apps can require login ([#3825](https://github.com/windmill-labs/windmill/issues/3825)) ([e2a1219](https://github.com/windmill-labs/windmill/commit/e2a1219373cace1bf4130004c27b9bf3595f7dd9))
* worker vcpus/memory limits + mem usage ([#3828](https://github.com/windmill-labs/windmill/issues/3828)) ([621464b](https://github.com/windmill-labs/windmill/commit/621464b55025d601f747f611cbb3485d363a480a))
### Bug Fixes
* filtering not always working with concurrency keys ([#3823](https://github.com/windmill-labs/windmill/issues/3823)) ([47df9f3](https://github.com/windmill-labs/windmill/commit/47df9f33cce5a20231b6b38d4eb1ff370699fc38))
* improve concurrency re-scheduling at scale ([f2d9c3c](https://github.com/windmill-labs/windmill/commit/f2d9c3c77729fe32366a1c0628d5c0af4d603dff))
* improve concurrency re-scheduling at scale ([e187fa6](https://github.com/windmill-labs/windmill/commit/e187fa6263100cb26a24726123bcc3bbe641a6e8))
* make all error strings more verbose ([7a36f30](https://github.com/windmill-labs/windmill/commit/7a36f30fe3138089df5c3a4ce87744c4a459044d))
## [1.337.0](https://github.com/windmill-labs/windmill/compare/v1.336.1...v1.337.0) (2024-05-25)
### Features
* add GetResumeUrls to go client ([#3810](https://github.com/windmill-labs/windmill/issues/3810)) ([59f980f](https://github.com/windmill-labs/windmill/commit/59f980f75a9a507f22349f822579a5542f69b988))
* automatic key renewal ([#3815](https://github.com/windmill-labs/windmill/issues/3815)) ([831cf89](https://github.com/windmill-labs/windmill/commit/831cf89b6367009d0d861975cb8f78b616b0868e))
### Bug Fixes
* rename email_from_username to username_to_email ([#3813](https://github.com/windmill-labs/windmill/issues/3813)) ([7584c2b](https://github.com/windmill-labs/windmill/commit/7584c2b0bbc216896daa6a366028cfc3ab5af00c))
* use hub script language as tag instead of 'hub' ([#3816](https://github.com/windmill-labs/windmill/issues/3816)) ([47bb5d2](https://github.com/windmill-labs/windmill/commit/47bb5d2492856c5cecd77d386c802958f0aa7211))
## [1.336.1](https://github.com/windmill-labs/windmill/compare/v1.336.0...v1.336.1) (2024-05-24)
### Bug Fixes
* revert bun to 1.1.8 ([ba9cdb1](https://github.com/windmill-labs/windmill/commit/ba9cdb1ae2aca13fd06876b48e0acdb65f2a1b00))
## [1.336.0](https://github.com/windmill-labs/windmill/compare/v1.335.0...v1.336.0) (2024-05-23)
### Features
* **frontend:** improve graph edges + fix depedencies detection ([#3802](https://github.com/windmill-labs/windmill/issues/3802)) ([d11e350](https://github.com/windmill-labs/windmill/commit/d11e350de395811daad8a49c0eef7b3b19460ead))
* improve parsers when no main func ([#3805](https://github.com/windmill-labs/windmill/issues/3805)) ([001278c](https://github.com/windmill-labs/windmill/commit/001278cddd6e91f767f090e358db4299611f0451))
* improve permissioned audit logs ([#3799](https://github.com/windmill-labs/windmill/issues/3799)) ([62f3180](https://github.com/windmill-labs/windmill/commit/62f318077cd77d8332bbe02ac279a5bca7351e51))
* improve premissioned audit logs ([#3793](https://github.com/windmill-labs/windmill/issues/3793)) ([21a077e](https://github.com/windmill-labs/windmill/commit/21a077ecfaa2dfabe6a46e425214182845b5259e))
* store failed_retries per module state and display failed retries in flow status viewer ([62e8816](https://github.com/windmill-labs/windmill/commit/62e88169ea47e6357931bafd564ab45df40a62ff))
* store failed_retries per module state and display failed retries in flow status viewer ([7e0be89](https://github.com/windmill-labs/windmill/commit/7e0be8914bcb33caf680358f083e80edfb83d00f))
### Bug Fixes
* **frontend:** Add missing loading state for non-runnable components … ([#3797](https://github.com/windmill-labs/windmill/issues/3797)) ([a0acdc1](https://github.com/windmill-labs/windmill/commit/a0acdc1217967562bb349a2b718c82af74b8bc45))
* show code option in tree view ([#3803](https://github.com/windmill-labs/windmill/issues/3803)) ([1745a9d](https://github.com/windmill-labs/windmill/commit/1745a9dd1617de4686480e0cfc9ba2ef2da0c625))
* update bun to 1.1.9 ([bfd2d27](https://github.com/windmill-labs/windmill/commit/bfd2d27415a906f9133777b69653ddacf659de41))
## [1.335.0](https://github.com/windmill-labs/windmill/compare/v1.334.0...v1.335.0) (2024-05-22)
### Features
* improve user audit logs and stats ([#3786](https://github.com/windmill-labs/windmill/issues/3786)) ([2f370de](https://github.com/windmill-labs/windmill/commit/2f370de62805e1291901cf19368ae4270d70a916))
### Bug Fixes
* **cli:** add concurrency key to script ([4d28a38](https://github.com/windmill-labs/windmill/commit/4d28a38750c94dc4362778ace6a227472bd4cd9b))
* **frontend:** Fix aggrid infinite refresh ([#3789](https://github.com/windmill-labs/windmill/issues/3789)) ([85cd8b4](https://github.com/windmill-labs/windmill/commit/85cd8b4c0ef7aa0b8325db2f99b31ed31a051804))
## [1.334.0](https://github.com/windmill-labs/windmill/compare/v1.333.5...v1.334.0) (2024-05-21)
### Features
* **frontend:** Added support for title and placeholder for ArgInputs ([#3779](https://github.com/windmill-labs/windmill/issues/3779)) ([59c0aba](https://github.com/windmill-labs/windmill/commit/59c0abae3df7397f32b65360b6740ca71a91444b))
* **frontend:** Improve multiselect perf ([#3770](https://github.com/windmill-labs/windmill/issues/3770)) ([36df838](https://github.com/windmill-labs/windmill/commit/36df8389cd5d75c4332e0f0a1da61433dac88195))
### Bug Fixes
* add allow http toggle to object store settings ([4631c3f](https://github.com/windmill-labs/windmill/commit/4631c3fd08341858b97a1a9673664e7220bbef63))
* **frontend:** Fix path overflow on the Runs page ([#3781](https://github.com/windmill-labs/windmill/issues/3781)) ([518d8b9](https://github.com/windmill-labs/windmill/commit/518d8b916b41ba35d623deeb27c6f6f82e171060))
## [1.333.5](https://github.com/windmill-labs/windmill/compare/v1.333.4...v1.333.5) (2024-05-21)
### Bug Fixes
* drop the linux file cache regularly to avoid triggering OOM killer ([0268dd1](https://github.com/windmill-labs/windmill/commit/0268dd1206ac3e84eec571a6ff53f921f05ed6c4))
* **frontend:** Fix full height component for public apps ([#3777](https://github.com/windmill-labs/windmill/issues/3777)) ([edf3015](https://github.com/windmill-labs/windmill/commit/edf3015cc4944340e52b5d65a2c72f421b97b548))
* **frontend:** Fix selected value when the default value of a select component is null ([#3778](https://github.com/windmill-labs/windmill/issues/3778)) ([31c4777](https://github.com/windmill-labs/windmill/commit/31c47774cd64279100a5d23a076af0519cf6ee89))
* improve concurrency key migration ([b56fbdf](https://github.com/windmill-labs/windmill/commit/b56fbdf898792c68c535ca491b79c501993173a4))
* lighten watermark on public apps for ee ([da3b043](https://github.com/windmill-labs/windmill/commit/da3b0434e92f1ce95e3e7ede07d4bce0460de9af))
## [1.333.4](https://github.com/windmill-labs/windmill/compare/v1.333.3...v1.333.4) (2024-05-20)
### Bug Fixes
* **cli:** make bun the default language in absence of wmill defaultTs 2 ([b2958be](https://github.com/windmill-labs/windmill/commit/b2958be7c10d932ae4076e0cde49fff37d5e9f41))
## [1.333.3](https://github.com/windmill-labs/windmill/compare/v1.333.2...v1.333.3) (2024-05-20)
### Bug Fixes
* **cli:** make bun the default language in absence of wmill defaultTs ([8399086](https://github.com/windmill-labs/windmill/commit/83990869bc5edb98f633944410242de19dbe5d01))
## [1.333.2](https://github.com/windmill-labs/windmill/compare/v1.333.1...v1.333.2) (2024-05-20)
### Bug Fixes
* **frontend:** fix AgGrid pagination refresh ([#3773](https://github.com/windmill-labs/windmill/issues/3773)) ([ccc2699](https://github.com/windmill-labs/windmill/commit/ccc2699d4ef18a765c3f9e968b4cd5ea1f600fa1))
## [1.333.1](https://github.com/windmill-labs/windmill/compare/v1.333.0...v1.333.1) (2024-05-20)
### Bug Fixes
* **backend:** improve memory usage by making schema RawValue instead of serde_json::Value ([f1bb7cf](https://github.com/windmill-labs/windmill/commit/f1bb7cfcbdbfee7488f59256522be18f8d2eb0a3))
## [1.333.0](https://github.com/windmill-labs/windmill/compare/v1.332.1...v1.333.0) (2024-05-19)
### Features
* reduce memory usage ([#3768](https://github.com/windmill-labs/windmill/issues/3768)) ([7a1808e](https://github.com/windmill-labs/windmill/commit/7a1808e951a2f359902138d1bb964cf52986665d))
## [1.332.1](https://github.com/windmill-labs/windmill/compare/v1.332.0...v1.332.1) (2024-05-18)
### Bug Fixes
* **cli:** improve handling of schema for script bundles ([32bf061](https://github.com/windmill-labs/windmill/commit/32bf061627f087e1ec4e88a3e03be0ca1b7fa9f7))
* **frontend:** improve json display for large table objects ([#3765](https://github.com/windmill-labs/windmill/issues/3765)) ([f0b3527](https://github.com/windmill-labs/windmill/commit/f0b3527e53e077f9c9ab4c9c6373f35cee77e566))
## [1.332.0](https://github.com/windmill-labs/windmill/compare/v1.331.2...v1.332.0) (2024-05-16)
### Features
* **frontend:** Fix App Select component initial value ([#3752](https://github.com/windmill-labs/windmill/issues/3752)) ([e11a375](https://github.com/windmill-labs/windmill/commit/e11a3751c3d188522360010a03e1fbc92311f554))
### Bug Fixes
* fix args interpolation for tag and concurrency key for non string values ([2b06d9a](https://github.com/windmill-labs/windmill/commit/2b06d9ae793f9e5fddee4ca0889634429ff53416))
## [1.331.2](https://github.com/windmill-labs/windmill/compare/v1.331.1...v1.331.2) (2024-05-16)
+1 -1
View File
@@ -171,7 +171,7 @@ COPY --from=builder /windmill/target/release/windmill ${APP}/windmill
COPY --from=downloader --chmod=755 /deno /usr/bin/deno
COPY --from=oven/bun:1.1.7 /usr/local/bin/bun /usr/bin/bun
COPY --from=oven/bun:1.1.8 /usr/local/bin/bun /usr/bin/bun
COPY --from=php:8.3.7-cli /usr/local/bin/php /usr/bin/php
COPY --from=composer:2.7.6 /usr/bin/composer /usr/bin/composer
+2 -1
View File
@@ -3,4 +3,5 @@ target/
oauth.json
oauth2.json
windmill-api/openapi-deref.yaml
tracing.folded
tracing.folded
heaptrack*
@@ -1,70 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by from app, app_version \n WHERE app.workspace_id = $1 AND app_version.id = app.versions[array_upper(app.versions, 1)]",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "versions",
"type_info": "Int8Array"
},
{
"ordinal": 4,
"name": "policy",
"type_info": "Jsonb"
},
{
"ordinal": 5,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "value",
"type_info": "Json"
},
{
"ordinal": 7,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "023fffd0a042a28b5be991169a506aff92f64f84e49b4c041cd369b045c31e73"
}
@@ -1,48 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT running, substr(concat(coalesce(queue.logs, ''), job_logs.logs), greatest($1 - job_logs.log_offset, 0)) as logs, mem_peak, \n CASE WHEN is_flow_step is true then NULL else flow_status END as flow_status,\n job_logs.log_offset + char_length(job_logs.logs) + 1 as log_offset\n FROM queue\n LEFT JOIN job_logs ON job_logs.job_id = queue.id \n WHERE queue.workspace_id = $2 AND queue.id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "running",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "mem_peak",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "flow_status",
"type_info": "Jsonb"
},
{
"ordinal": 4,
"name": "log_offset",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Int4",
"Text",
"Uuid"
]
},
"nullable": [
false,
null,
true,
null,
null
]
},
"hash": "04be51a152d7c9644f11173da2cc386a71e178685364e7da4b910d1648ea55ba"
}
@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE queue\n SET running = false\n , started_at = null\n , scheduled_for = $1\n , last_ping = null\n WHERE id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Timestamptz",
"Uuid"
]
},
"nullable": []
},
"hash": "126be8832776644e0d2c5d004acb26f6d4820a6a1fc8e028c3550c438248a82b"
}
@@ -0,0 +1,24 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM queue LEFT JOIN concurrency_key ON concurrency_key.job_id = queue.id\n WHERE key = $1 AND running = false AND canceled = false AND scheduled_for >= $2 AND scheduled_for < $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Timestamptz",
"Timestamptz"
]
},
"nullable": [
null
]
},
"hash": "293054a4d6a2b00228a5029a81c026e8891576c7e87cdab41d7fcc3afc32d583"
}
@@ -1,20 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT owner FROM workspace WHERE owner NOT LIKE '%@windmill.dev'",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "owner",
"type_info": "Varchar"
}
],
"parameters": {
"Left": []
},
"nullable": [
false
]
},
"hash": "2fa6e9c2cfc4f4ddbaa91793686feb9773b36993dd417019db51fa59fd4952c3"
}
@@ -1,23 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT path, value from flow WHERE workspace_id = $1 LIMIT $2",
"query": "SELECT value, created_at FROM metrics WHERE id = $1 ORDER BY created_at DESC LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
"name": "value",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "value",
"type_info": "Jsonb"
"name": "created_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Text",
"Int8"
"Text"
]
},
"nullable": [
@@ -25,5 +24,5 @@
false
]
},
"hash": "efbd9dc28ab5e53d070684b2e99d945872791171a1c8cef6088ea662f3b2cebb"
"hash": "360d13c0a776e794063c99acad935a424f79017f3769e1150faa87cbb91367a8"
}
@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM usr WHERE email = $1 AND workspace_id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "3da14e6c89a33871e4bd40524e2fd9222aa707ee76de6ce348337c3e403eb955"
}
@@ -1,71 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by from app, app_version \n WHERE app_version.id = $1 AND app.id = app_version.app_id AND app.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "versions",
"type_info": "Int8Array"
},
{
"ordinal": 4,
"name": "policy",
"type_info": "Jsonb"
},
{
"ordinal": 5,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "value",
"type_info": "Json"
},
{
"ordinal": 7,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int8",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "438fb925ee90d5115bd3c3be8ae48b56ba86017af3ca519bd3a15829edaa7d1b"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, current_job_id = NULL, current_job_workspace_id = NULL WHERE worker = $4",
"query": "UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, memory_usage = $4, wm_memory_usage = $5, current_job_id = NULL, current_job_workspace_id = NULL WHERE worker = $6",
"describe": {
"columns": [],
"parameters": {
@@ -8,10 +8,12 @@
"Int4",
"TextArray",
"Float4",
"Int8",
"Int8",
"Text"
]
},
"nullable": []
},
"hash": "54fef88cc6b9e8db7c07fccbaa845edfefa339153a32e468faad9f063008863d"
"hash": "4398bc6f701dcba647a259ec2d091a70938a3ecd7ff8a89277cc35d119e2bad4"
}
@@ -1,38 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT success, result, started_at FROM completed_job WHERE workspace_id = $1 AND schedule_path = $2 AND script_path = $3 AND id != $4 ORDER BY created_at DESC LIMIT $5",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "success",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "result",
"type_info": "Jsonb"
},
{
"ordinal": 2,
"name": "started_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Text",
"Text",
"Text",
"Uuid",
"Int8"
]
},
"nullable": [
false,
true,
false
]
},
"hash": "4a3917318d967d96c4b6e70786a034302f04da9d1e9eec59b1eb6052c2d947be"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT worker, worker_instance, EXTRACT(EPOCH FROM (now() - ping_at))::integer as last_ping, started_at, ip, jobs_executed, CASE WHEN $4 IS TRUE THEN current_job_id ELSE NULL END as current_job_id, CASE WHEN $4 IS TRUE THEN current_job_workspace_id ELSE NULL END as current_job_workspace_id, custom_tags, worker_group, wm_version, occupancy_rate\n FROM worker_ping\n WHERE ($1::integer IS NULL AND ping_at > now() - interval '5 minute') OR (ping_at > now() - ($1 || ' seconds')::interval)\n ORDER BY ping_at desc LIMIT $2 OFFSET $3",
"query": "SELECT worker, worker_instance, EXTRACT(EPOCH FROM (now() - ping_at))::integer as last_ping, started_at, ip, jobs_executed, CASE WHEN $4 IS TRUE THEN current_job_id ELSE NULL END as current_job_id, CASE WHEN $4 IS TRUE THEN current_job_workspace_id ELSE NULL END as current_job_workspace_id, custom_tags, worker_group, wm_version, occupancy_rate, memory, vcpus, memory_usage, wm_memory_usage\n FROM worker_ping\n WHERE ($1::integer IS NULL AND ping_at > now() - interval '5 minute') OR (ping_at > now() - ($1 || ' seconds')::interval)\n ORDER BY ping_at desc LIMIT $2 OFFSET $3",
"describe": {
"columns": [
{
@@ -62,6 +62,26 @@
"ordinal": 11,
"name": "occupancy_rate",
"type_info": "Float4"
},
{
"ordinal": 12,
"name": "memory",
"type_info": "Int8"
},
{
"ordinal": 13,
"name": "vcpus",
"type_info": "Int8"
},
{
"ordinal": 14,
"name": "memory_usage",
"type_info": "Int8"
},
{
"ordinal": 15,
"name": "wm_memory_usage",
"type_info": "Int8"
}
],
"parameters": {
@@ -84,8 +104,12 @@
true,
false,
false,
true,
true,
true,
true,
true
]
},
"hash": "e00171cc3fc8f32922562d4fc4d3db56955fbc6ee9872d4b2e99157ebed131e0"
"hash": "55d6c6f887f1cceb311d9ab034d3485b8ccb2d07d723f184cef2696760d3ccf9"
}
@@ -1,20 +1,25 @@
{
"db_name": "PostgreSQL",
"query": "SELECT CONCAT(coalesce(queue.logs, ''), coalesce(job_logs.logs, '')) as logs, job_logs.log_offset, job_logs.log_file_index\n FROM queue \n LEFT JOIN job_logs ON job_logs.job_id = queue.id \n WHERE queue.id = $1 AND queue.workspace_id = $2",
"query": "SELECT created_by, CONCAT(coalesce(queue.logs, ''), coalesce(job_logs.logs, '')) as logs, job_logs.log_offset, job_logs.log_file_index\n FROM queue \n LEFT JOIN job_logs ON job_logs.job_id = queue.id \n WHERE queue.id = $1 AND queue.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "created_by",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 1,
"ordinal": 2,
"name": "log_offset",
"type_info": "Int4"
},
{
"ordinal": 2,
"ordinal": 3,
"name": "log_file_index",
"type_info": "TextArray"
}
@@ -26,10 +31,11 @@
]
},
"nullable": [
false,
null,
false,
true
]
},
"hash": "bd213fca18a04d9e34405fd753c02398b72afb17b1ce650dbac947490634009d"
"hash": "57111a97ff906fd79ecd8a571212cc4fea9cb9c16fe950f082ad5469bfeefc82"
}
@@ -1,187 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO schedule (workspace_id, path, schedule, timezone, edited_by, script_path, is_flow, args, enabled, email, on_failure, on_failure_times, on_failure_exact, on_failure_extra_args, on_recovery, on_recovery_times, on_recovery_extra_args, ws_error_handler_muted, retry, summary, no_flow_overlap, tag ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22 ) RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Varchar",
"Bool",
"Jsonb",
"Bool",
"Varchar",
"Varchar",
"Int4",
"Bool",
"Json",
"Varchar",
"Int4",
"Json",
"Bool",
"Jsonb",
"Varchar",
"Bool",
"Varchar"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "597335a4a1eda7799303e0d930b5468af2364f5d2075aab48787b93e5774336d"
}
@@ -1,11 +1,11 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT payload\n FROM capture\n WHERE workspace_id = $1\n AND path = $2\n ",
"query": "SELECT large_file_storage->'secondary_storage'->$2 FROM workspace_settings WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "payload",
"name": "?column?",
"type_info": "Jsonb"
}
],
@@ -16,8 +16,8 @@
]
},
"nullable": [
false
null
]
},
"hash": "f4960efbb4189b595541608c9ab5cbbd56eb42059e961b6338b685105626a5c7"
"hash": "5bdf8d82eed7e14cb3feb2ca597aac374c160428329526715d840fc46fdb0501"
}
@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM usr WHERE email = $1 AND workspace_id = $2 RETURNING username",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "62cd69e3dc0f8757db3481d078921f4722bbc93d52e05656b82cb42ba9803ef6"
}
@@ -1,29 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT path, app_version.value from app LEFT JOIN app_version ON app_version.id = versions[array_upper(versions, 1)] WHERE workspace_id = $1 LIMIT $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "value",
"type_info": "Json"
}
],
"parameters": {
"Left": [
"Text",
"Int8"
]
},
"nullable": [
false,
false
]
},
"hash": "644335d376b6554ab222d25dfa8722234661f2456b469f21b175e8607584614e"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email FROM password WHERE super_admin IS true AND email NOT LIKE '%@windmill.dev'",
"query": "SELECT email FROM password WHERE super_admin IS true AND email NOT LIKE '%@windmill.dev' LIMIT 1",
"describe": {
"columns": [
{
@@ -16,5 +16,5 @@
false
]
},
"hash": "3dd6ba886b214274d9453667e3732421251c3a0d84b0909206447a3927bad8b3"
"hash": "71ad5448cba8da6677edd02e090cc158e09af72dd31585ed2ddc1cc06cbfd189"
}
@@ -1,182 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET schedule = $1, timezone = $2, args = $3, on_failure = $4, on_failure_times = $5, on_failure_exact = $6, on_failure_extra_args = $7, on_recovery = $8, on_recovery_times = $9, on_recovery_extra_args = $10, ws_error_handler_muted = $11, retry = $12, summary = $13, no_flow_overlap = $14, tag = $15\n WHERE path = $16 AND workspace_id = $17 RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Jsonb",
"Varchar",
"Int4",
"Bool",
"Json",
"Varchar",
"Int4",
"Json",
"Bool",
"Jsonb",
"Varchar",
"Bool",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "90435687152ccd37db7e0a6a5baeb558db50f5f96b1e8eff0b10e4398566f325"
}
@@ -1,168 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET path = $1, script_path = $1 WHERE path = $2 AND workspace_id = $3 AND is_flow IS true RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "911b1e1f2a5ba6d5159916e5598020e680c45043b0736ad0153ee261a151dd90"
}
@@ -1,16 +1,18 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE worker_ping SET ping_at = now(), current_job_id = $1, current_job_workspace_id = $2 WHERE worker = $3",
"query": "UPDATE worker_ping SET ping_at = now(), current_job_id = $1, current_job_workspace_id = $2, memory_usage = $3, wm_memory_usage = $4 WHERE worker = $5",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Varchar",
"Int8",
"Int8",
"Text"
]
},
"nullable": []
},
"hash": "8c62e3bb264c7336b3b3a68677993ba3b729c7358cc3da14513d8b447ce65aaf"
"hash": "95cb1fe8658f98fb736d899fa21cd7378b0c9d3b5f3d6bd6cafcba273f8277d4"
}
@@ -1,169 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET enabled = $1, email = $2 WHERE path = $3 AND workspace_id = $4 RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "96dc1cd308f3c21cfb50b88048054dc03f93e261d25969d66aa48e9d0502960f"
}
@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM app WHERE id = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Int8",
"Text"
]
},
"nullable": [
null
]
},
"hash": "98c11a7d870a997c74e533a75bb48f39b0ec43816f05ac1d1eb39ea1903138f9"
}
@@ -1,71 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by from app, app_version \n WHERE app.id = $1 AND app.workspace_id = $2 AND app_version.id = app.versions[array_upper(app.versions, 1)]",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "versions",
"type_info": "Int8Array"
},
{
"ordinal": 4,
"name": "policy",
"type_info": "Jsonb"
},
{
"ordinal": 5,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "value",
"type_info": "Json"
},
{
"ordinal": 7,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int8",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "9ae98fbcea508dfc7113621c00b856f98f38dfb701a4660ea1a4058a6d7564f2"
}
@@ -0,0 +1,20 @@
{
"db_name": "PostgreSQL",
"query": "SELECT created_at FROM metrics WHERE id = 'license_key_renewal' ORDER BY created_at DESC LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "created_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": []
},
"nullable": [
false
]
},
"hash": "9ed77e78e6295c62745ac3ac3b7e5f544f654d7cddc13acb5d3f4fdc12a8875f"
}
@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT CAST(ROUND(AVG(duration_ms) / 1000, 0) AS BIGINT) AS avg_duration_s FROM\n (SELECT duration_ms FROM completed_job WHERE script_path = $1\n ORDER BY started_at\n DESC LIMIT 10) AS t",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "avg_duration_s",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "a0ce703def7e976947513029874fb571893c75730e0a8feeb609852423404cf0"
}
@@ -1,23 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT username FROM usr WHERE workspace_id = $1 AND email = $2",
"query": "SELECT concurrency_key FROM script WHERE hash = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "username",
"name": "concurrency_key",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text",
"Int8",
"Text"
]
},
"nullable": [
false
true
]
},
"hash": "da5da57ea48ddc6ab271b6c18baa5f7360008e082e2fb8d58faff4461e18c83a"
"hash": "a3ccf362b4f6df400b3c7a084795dbf541eb14c5c374656ffb96da7283a2a6f1"
}
@@ -1,42 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT substr(concat(coalesce(completed_job.logs, ''), job_logs.logs), greatest($1 - job_logs.log_offset, 0)) as logs, mem_peak, \n CASE WHEN is_flow_step is true then NULL else flow_status END as flow_status,\n job_logs.log_offset + char_length(job_logs.logs) + 1 as log_offset\n FROM completed_job \n LEFT JOIN job_logs ON job_logs.job_id = completed_job.id \n WHERE completed_job.workspace_id = $2 AND id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "mem_peak",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "flow_status",
"type_info": "Jsonb"
},
{
"ordinal": 3,
"name": "log_offset",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Int4",
"Text",
"Uuid"
]
},
"nullable": [
null,
true,
null,
null
]
},
"hash": "a73b57229602d68cc25a8d963753271619e74df9fd7fc6cb05fc0614b10e6001"
}
@@ -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"
}
@@ -1,167 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT * FROM schedule WHERE path = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "aa2800113a8a8805f47cdc1dd0f29d94c546fe531e7edd3e91da4978af5442fb"
}
@@ -0,0 +1,26 @@
{
"db_name": "PostgreSQL",
"query": "WITH active_users as (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login')),\n active_user_count as (SELECT count(email)::INT as count from active_users),\n active_author_count as (SELECT count(distinct email)::INT as count FROM usr WHERE usr.operator IS false AND email IN (SELECT email FROM active_users))\n SELECT active_author_count.count as author_count, active_user_count.count - active_author_count.count as operator_count FROM active_user_count, active_author_count",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "author_count",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "operator_count",
"type_info": "Int4"
}
],
"parameters": {
"Left": []
},
"nullable": [
null,
null
]
},
"hash": "ad8d9c00bd2d3515ad4afa87aa24b243615484bbad5a793438e23908c3f20c2f"
}
@@ -1,83 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by,\n app.draft_only, draft.value as \"draft?\"\n from app\n INNER JOIN app_version ON\n app_version.id = app.versions[array_upper(app.versions, 1)]\n LEFT JOIN draft ON \n app.path = draft.path AND draft.workspace_id = $2 AND draft.typ = 'app' \n WHERE app.path = $1 AND app.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "versions",
"type_info": "Int8Array"
},
{
"ordinal": 4,
"name": "policy",
"type_info": "Jsonb"
},
{
"ordinal": 5,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "value",
"type_info": "Json"
},
{
"ordinal": 7,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "created_by",
"type_info": "Varchar"
},
{
"ordinal": 9,
"name": "draft_only",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "draft?",
"type_info": "Json"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
false
]
},
"hash": "aedba9cff117a7069dfd56602110b7f66903d6afb4f87fbffe0175982ea8741f"
}
@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT self_wait_time_ms, aggregate_wait_time_ms FROM outstanding_wait_time WHERE job_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "self_wait_time_ms",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "aggregate_wait_time_ms",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
true,
true
]
},
"hash": "b2ce29f663cfe1f10dd506dd28b8ce31c58bd40dc130e05df6ef804b2800d6cb"
}
@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO outstanding_wait_time(job_id, aggregate_wait_time_ms) VALUES ($1, $2)\n ON CONFLICT (job_id) DO UPDATE SET aggregate_wait_time_ms =\n COALESCE(outstanding_wait_time.aggregate_wait_time_ms, 0) + EXCLUDED.aggregate_wait_time_ms",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Int8"
]
},
"nullable": []
},
"hash": "b3d13bdc40c19d0f94937633053a213057f09e853ea48dc8034a4a586c44ee55"
}
@@ -0,0 +1,41 @@
{
"db_name": "PostgreSQL",
"query": "SELECT created_by, CONCAT(coalesce(completed_job.logs, ''), coalesce(job_logs.logs, '')) as logs, job_logs.log_offset, job_logs.log_file_index\n FROM completed_job \n LEFT JOIN job_logs ON job_logs.job_id = completed_job.id \n WHERE completed_job.id = $1 AND completed_job.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "created_by",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "log_offset",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "log_file_index",
"type_info": "TextArray"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
false,
null,
false,
true
]
},
"hash": "b4c4b1aa4bcf7e5f49ce3bd93fff3b7c49e812271e4888d33eb73dd638486488"
}
@@ -1,168 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET script_path = $1 WHERE script_path = $2 AND path != $2 AND workspace_id = $3 AND is_flow IS false RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "c10348d26e3e3dc9e345d9044db35db9906617eb9c98aaf58a55d9681ffb85e3"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "WITH all_users as (SELECT count(*)::INT as count FROM usr WHERE disabled IS false),\n authors as (SELECT count(distinct email)::INT as count FROM usr WHERE usr.operator IS false AND disabled IS false)\n SELECT authors.count as author_count, all_users.count - authors.count as operator_count FROM all_users, authors",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "author_count",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "operator_count",
"type_info": "Int4"
}
],
"parameters": {
"Left": []
},
"nullable": [
null,
null
]
},
"hash": "c584aeec21716f7405c355d5684ff3ac1be3f70849d67b8c2d4787e809b7ea2b"
}
@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT CAST(ROUND(AVG(duration_ms), 0) AS BIGINT) AS avg_duration_s FROM\n (SELECT duration_ms FROM concurrency_key LEFT JOIN completed_job ON completed_job.id = concurrency_key.job_id WHERE key = $1 AND ended_at IS NOT NULL\n ORDER BY ended_at\n DESC LIMIT 10) AS t",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "avg_duration_s",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "c845c06aa46b52a1e3672fd379dbcec167f4044e45e932aeeefd3d9237e5042c"
}
@@ -1,20 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM worker_ping WHERE ping_at > NOW() - INTERVAL '2 minutes'",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": []
},
"nullable": [
null
]
},
"hash": "cdfc8e9af4414b7ee7525bc74d9caad74b5479c64337c401a7a9550a3434cdfa"
}
@@ -1,71 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.id, app.path, app.summary, app.versions, app.policy,\n app.extra_perms, app_version.value, \n app_version.created_at, app_version.created_by from app, app_version \n WHERE app.path = $1 AND app.workspace_id = $2 AND app_version.id = app.versions[array_upper(app.versions, 1)]",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "versions",
"type_info": "Int8Array"
},
{
"ordinal": 4,
"name": "policy",
"type_info": "Jsonb"
},
{
"ordinal": 5,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "value",
"type_info": "Json"
},
{
"ordinal": 7,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "d07faf1c9501d1bc5f6fd9588bb3da7b7f4897fcfd26dcb3b8ce406b1f653077"
}
@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT CONCAT(coalesce(completed_job.logs, ''), coalesce(job_logs.logs, '')) as logs, job_logs.log_offset, job_logs.log_file_index\n FROM completed_job \n LEFT JOIN job_logs ON job_logs.job_id = completed_job.id \n WHERE completed_job.id = $1 AND completed_job.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "log_offset",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "log_file_index",
"type_info": "TextArray"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
null,
false,
true
]
},
"hash": "d0ce6a8ff7b89a0e99902989e57e7cae736e346c067261de34100f4fb97ca6db"
}
@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO metrics (id, value) VALUES ('license_key_renewal', $1)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Jsonb"
]
},
"nullable": []
},
"hash": "d113bc301f2f094c3a2a4c6ed385da65edde2fbfee0fac5103ba7bd18c64563d"
}
@@ -1,168 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET path = $1, script_path = $1 WHERE path = $2 AND workspace_id = $3 AND is_flow IS false RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "dd74fa9468b5fe8c8ad657ded06076c11a78d0206af2af20685c691d4d9520bb"
}
@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT author.count as author_count, operator.count as operator_count FROM (SELECT count(*)::INT FROM usr where usr.operator IS false) as author, (SELECT count(*)::INT FROM usr where usr.operator IS true) as operator",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "author_count",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "operator_count",
"type_info": "Int4"
}
],
"parameters": {
"Left": []
},
"nullable": [
null,
null
]
},
"hash": "e70835de2b70a01a2e85f44f3cb80f41288d8e68b762de80ae724ed69ef1908c"
}
@@ -1,168 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET script_path = $1 WHERE script_path = $2 AND path != $2 AND workspace_id = $3 AND is_flow IS true RETURNING *",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "eced0a09ba547ce1dccb54a5419b22373603c9d01f77047b3553bde125bf71e8"
}
@@ -1,12 +1,12 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow_status FROM queue WHERE id = $1 AND workspace_id = $2",
"query": "SELECT parent_job FROM queue WHERE id = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "flow_status",
"type_info": "Jsonb"
"name": "parent_job",
"type_info": "Uuid"
}
],
"parameters": {
@@ -19,5 +19,5 @@
true
]
},
"hash": "0a7212dd507ed8f7a311724185e39ecc1809abb208a681ad711614c27baadd83"
"hash": "f33dd637181439ba7fa441dbd7d7430c1ccc0f410c377cde71c70c9211f9c1df"
}
@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO outstanding_wait_time(job_id, self_wait_time_ms) VALUES ($1, $2)\n ON CONFLICT (job_id) DO UPDATE SET self_wait_time_ms = EXCLUDED.self_wait_time_ms",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Int8"
]
},
"nullable": []
},
"hash": "f367a1c8f80dd414dcbcd949374eeb5770796f00b5b3d547163bcfdaed65d8ae"
}
@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO concurrency_key (job_id, key) SELECT id, $1 FROM unnest($2::uuid[]) as id",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"UuidArray"
]
},
"nullable": []
},
"hash": "f5a0346034f3bef54260962f7783b3fde7b1aa1f37a72058e292eebbcae08d74"
}
@@ -1,166 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT * FROM schedule\n WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "edited_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "schedule",
"type_info": "Varchar"
},
{
"ordinal": 5,
"name": "enabled",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "script_path",
"type_info": "Varchar"
},
{
"ordinal": 7,
"name": "args",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "extra_perms",
"type_info": "Jsonb"
},
{
"ordinal": 9,
"name": "is_flow",
"type_info": "Bool"
},
{
"ordinal": 10,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "error",
"type_info": "Text"
},
{
"ordinal": 12,
"name": "timezone",
"type_info": "Varchar"
},
{
"ordinal": 13,
"name": "on_failure",
"type_info": "Varchar"
},
{
"ordinal": 14,
"name": "on_recovery",
"type_info": "Varchar"
},
{
"ordinal": 15,
"name": "on_failure_times",
"type_info": "Int4"
},
{
"ordinal": 16,
"name": "on_failure_exact",
"type_info": "Bool"
},
{
"ordinal": 17,
"name": "on_failure_extra_args",
"type_info": "Json"
},
{
"ordinal": 18,
"name": "on_recovery_times",
"type_info": "Int4"
},
{
"ordinal": 19,
"name": "on_recovery_extra_args",
"type_info": "Json"
},
{
"ordinal": 20,
"name": "ws_error_handler_muted",
"type_info": "Bool"
},
{
"ordinal": 21,
"name": "retry",
"type_info": "Jsonb"
},
{
"ordinal": 22,
"name": "summary",
"type_info": "Varchar"
},
{
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true
]
},
"hash": "fdd3710a381dac33ef5ee5ec5564a4874e6d7807d43fa6ea7b8408cad9e97480"
}
+1033 -896
View File
File diff suppressed because it is too large Load Diff
+14 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.331.2"
version = "1.341.0"
authors.workspace = true
edition.workspace = true
@@ -24,7 +24,7 @@ members = [
]
[workspace.package]
version = "1.331.2"
version = "1.341.0"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
@@ -51,7 +51,7 @@ prometheus = ["windmill-common/prometheus", "windmill-api/prometheus", "windmill
flow_testing = ["windmill-worker/flow_testing"]
openidconnect = ["windmill-api/openidconnect"]
cloud = ["windmill-queue/cloud"]
jemalloc = ["dep:tikv-jemallocator"]
jemalloc = ["windmill-common/jemalloc", "dep:tikv-jemallocator", "dep:tikv-jemalloc-sys", "dep:tikv-jemalloc-ctl"]
[dependencies]
anyhow.workspace = true
@@ -65,7 +65,6 @@ windmill-worker.workspace = true
futures.workspace = true
tracing.workspace = true
sqlx.workspace = true
tokio-metrics.workspace = true
rand.workspace = true
chrono.workspace = true
git-version.workspace = true
@@ -84,7 +83,9 @@ deno_core.workspace = true
pg-embed = {git = "https://github.com/faokunega/pg-embed", optional = true, default-features = false, features = ['rt_tokio']}
[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = { optional = true, version = "0.5" }
tikv-jemallocator = { optional = true, workspace = true }
tikv-jemalloc-sys = { optional = true, workspace = true }
tikv-jemalloc-ctl = { optional = true, workspace = true }
[dev-dependencies]
serde_json.workspace = true
@@ -189,7 +190,6 @@ dotenv = "^0"
ulid = { version = "^1", features = ["uuid"] }
futures = "^0"
futures-core = "^0"
tokio-metrics = "0.1.0"
lazy_static = "1.4.0"
serde_derive = "1.0.147"
const_format = { version = "0.2", features = ["rust_1_64", "rust_1_51"] }
@@ -234,8 +234,7 @@ tiberius = { git = "https://github.com/prisma/tiberius", rev = "8f66a699dfa041e7
pin-project = "1"
indexmap = { version = "2.2.5", features = ["serde"]}
polars = { version = "0.38.3", features = ["lazy", "parquet", "aws", "azure", "csv", "dtype-full", "serde", "strings", "extract_groups"] }
polars-io = { version = "0.38.3", features = ["csv"] }
datafusion = "38.0.0"
object_store = { version = "0.9.1", features = ["aws", "azure"] }
openidconnect = { version = "3.4.0" }
@@ -246,3 +245,10 @@ crc = "^3"
tar = "^0"
http = "^1"
async-stream = "^0"
tikv-jemallocator = { version = "0.5" }
tikv-jemalloc-sys = { version = "^0.5" }
tikv-jemalloc-ctl = { version = "^0.5" }
# 0.1.12 broken (nested dependency of swc_common)
triomphe = "<0.1.12"
+1 -1
View File
@@ -1 +1 @@
e0b0494c26b63efa4aa3f41a9fb42c7733dcca2e
76f66b0a9738d8c0f676ebf808ee82fa5073d77d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
-- Add down migration script here
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE token ALTER COLUMN label TYPE VARCHAR(1000)
@@ -0,0 +1 @@
-- Add down migration script here
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE worker_ping ADD COLUMN memory_usage BIGINT;
@@ -0,0 +1 @@
-- Add down migration script here
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE worker_ping ADD COLUMN wm_memory_usage BIGINT;
@@ -0,0 +1,2 @@
-- Add down migration script here
DROP TABLE outstanding_wait_time;
@@ -0,0 +1,6 @@
-- Add up migration script here
CREATE TABLE outstanding_wait_time (
job_id UUID PRIMARY KEY,
self_wait_time_ms BIGINT DEFAULT NULL,
aggregate_wait_time_ms BIGINT DEFAULT NULL
);
@@ -0,0 +1,2 @@
-- Add down migration script here
DROP POLICY "schedule_audit" on audit;
@@ -0,0 +1,4 @@
-- Add up migration script here
CREATE POLICY "schedule_audit" on audit FOR INSERT
TO windmill_user
WITH CHECK (((parameters->>'end_user')::text ~~ 'schedule-%'::text));
@@ -11,7 +11,7 @@ pub fn parse_bash_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_bash_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing bash script".to_string()))
}
@@ -21,7 +21,7 @@ pub fn parse_powershell_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_powershell_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing powershell script".to_string()))
}
@@ -160,7 +160,8 @@ non_required="${5:-}"
default: Some(json!("")),
has_default: true
}
]
],
no_main_func: None
}
);
+14 -3
View File
@@ -30,9 +30,19 @@ pub fn parse_go_sig(code: &str) -> anyhow::Result<MainArgSignature> {
Arg { name: get_name(param), otyp, typ, default: None, has_default: false }
})
.collect_vec();
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args,
no_main_func: Some(false),
})
} else {
Err(anyhow::anyhow!("no main function found".to_string(),))
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args: vec![],
no_main_func: Some(true),
})
}
}
@@ -216,7 +226,8 @@ func main(x int, y string, z bool, l []string, o struct { Name string `json:"nam
default: None,
has_default: false
},
]
],
no_main_func: Some(false)
}
);
@@ -10,7 +10,7 @@ pub fn parse_graphql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_graphql_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -101,7 +101,8 @@ query($s: String, $arr: [String]) {
default: None,
has_default: false
},
]
],
no_main_func: None
}
);
+14 -5
View File
@@ -89,11 +89,19 @@ pub fn parse_php_signature(
})
.collect();
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args,
no_main_func: Some(false),
})
} else {
Err(anyhow::anyhow!(
"main function was not findable".to_string(),
))
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args: vec![],
no_main_func: Some(true),
})
}
}
@@ -157,7 +165,8 @@ function main(string $input1 = \"hey\", bool $input2 = false, int $input3 = 3, f
has_default: false,
default: None
}
]
],
no_main_func: Some(false)
}
);
@@ -53,6 +53,9 @@ static PYTHON_IMPORTS_REPLACEMENT: phf::Map<&'static str, &'static str> = phf_ma
"pymsql" => "PyMySQL",
"haystack" => "haystack-ai",
"github" => "PyGithub",
"ldap" => "python-ldap",
"opensearchpy" => "opensearch-py",
};
fn replace_import(x: String) -> String {
+15 -7
View File
@@ -117,11 +117,15 @@ pub fn parse_python_signature(
}
})
.collect(),
no_main_func: Some(false),
})
} else {
Err(anyhow::anyhow!(
"main function was not findable".to_string(),
))
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args: vec![],
no_main_func: Some(true),
})
}
}
@@ -308,7 +312,8 @@ def main(test1: str, name: datetime.datetime = datetime.now(), byte: bytes = byt
default: Some(json!(true)),
has_default: true
},
]
],
no_main_func: Some(false),
}
);
@@ -367,7 +372,8 @@ def main(test1: str,
default: Some(json!("$res:g/all/resource")),
has_default: true
}
]
],
no_main_func: Some(false),
}
);
@@ -421,7 +427,8 @@ def main(test1: str,
default: Some(json!("<function call>")),
has_default: true
}
]
],
no_main_func: Some(false),
}
);
@@ -461,7 +468,8 @@ def main(test1: Literal["foo", "bar"], test2: List[Literal["foo", "bar"]]): retu
default: None,
has_default: false
}
]
],
no_main_func: Some(false),
}
);
@@ -11,7 +11,7 @@ pub fn parse_mysql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_mysql_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -21,7 +21,7 @@ pub fn parse_pgsql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_pg_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -31,7 +31,7 @@ pub fn parse_bigquery_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_bigquery_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -41,7 +41,7 @@ pub fn parse_snowflake_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_snowflake_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -51,7 +51,7 @@ pub fn parse_mssql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_mssql_file(&code)?;
if let Some(x) = parsed {
let args = x;
Ok(MainArgSignature { star_args: false, star_kwargs: false, args })
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
} else {
Err(anyhow!("Error parsing sql".to_string()))
}
@@ -396,7 +396,8 @@ SELECT * FROM table WHERE token=$1::TEXT AND image=$2::BIGINT
default: None,
has_default: false
},
]
],
no_main_func: None
}
);
@@ -431,7 +432,8 @@ SELECT * FROM table WHERE token=@token AND image=@image
default: None,
has_default: false
},
]
],
no_main_func: None
}
);
@@ -16,6 +16,7 @@ serde-wasm-bindgen.workspace = true
[dependencies]
windmill-parser.workspace = true
swc_common.workspace = true
triomphe.workspace = true
swc_ecma_parser.workspace = true
swc_ecma_ast.workspace = true
swc_ecma_visit.workspace = true
@@ -176,13 +176,16 @@ pub fn parse_deno_signature(
.into_iter()
.map(|x| parse_param(x, &cm, skip_dflt, &mut c))
.collect::<anyhow::Result<Vec<Arg>>>()?,
no_main_func: Some(false),
};
Ok(r)
} else {
Err(anyhow::anyhow!(
"main function was not findable (expected to find 'export function main(...)'"
.to_string(),
))
Ok(MainArgSignature {
star_args: false,
star_kwargs: false,
args: vec![],
no_main_func: Some(true),
})
}
}
@@ -3,7 +3,7 @@
"collaborators": [
"Ruben Fiszel <ruben@windmill.dev>"
],
"version": "1.327.0",
"version": "1.335.0",
"files": [
"windmill_parser_wasm_bg.wasm",
"windmill_parser_wasm.js",
@@ -587,10 +587,6 @@ function __wbg_get_imports() {
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_eval_f2b8ae7add53626d = function(arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
@@ -639,6 +635,10 @@ function __wbg_get_imports() {
const ret = getObject(arg0) in getObject(arg1);
return ret;
};
imports.wbg.__wbg_eval_4ecb84501b3abc94 = function(arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
const ret = getObject(arg0) == getObject(arg1);
return ret;
@@ -116,7 +116,8 @@ export function main(test1?: string, test2: string = \"burkina\",
default: None,
has_default: true
}
]
],
no_main_func: Some(false)
}
);
@@ -185,7 +186,8 @@ export function main(test2 = \"burkina\",
default: Some(json!({"a": "test", "b": 42})),
has_default: true
}
]
],
no_main_func: Some(false)
}
);
@@ -230,7 +232,8 @@ export function main(foo: FooBar, {a, b}: FooBar, {c, d}: FooBar = {a: \"foo\",
default: Some(json!({"a": "foo", "b": 42})),
has_default: true
}
]
],
no_main_func: Some(false)
}
);
@@ -258,7 +261,8 @@ export function main(foo: (\"foo\" | \"bar\")[]) {
])))),
default: None,
has_default: false
}]
}],
no_main_func: Some(false)
}
);
@@ -388,7 +392,8 @@ Write-Output 'Testing...'
default: None,
has_default: false
}
]
],
no_main_func: None,
}
);
@@ -14,6 +14,7 @@ pub struct MainArgSignature {
pub star_args: bool,
pub star_kwargs: bool,
pub args: Vec<Arg>,
pub no_main_func: Option<bool>,
}
#[derive(Serialize, Clone, Debug, PartialEq)]
+46 -31
View File
@@ -16,6 +16,10 @@ use std::{
};
use tokio::fs::DirBuilder;
use windmill_api::HTTP_CLIENT;
#[cfg(feature = "enterprise")]
use windmill_common::ee::schedule_key_renewal;
use windmill_common::{
global_settings::{
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, CRITICAL_ERROR_CHANNELS_SETTING,
@@ -32,6 +36,9 @@ use windmill_common::{
DB, METRICS_ENABLED,
};
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
use monitor::monitor_mem;
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
use tikv_jemallocator::Jemalloc;
@@ -52,13 +59,13 @@ use windmill_worker::{
};
use crate::monitor::{
initial_load, load_keep_job_dir, load_require_preexisting_user, load_tag_per_workspace_enabled,
monitor_db, monitor_pool, reload_base_url_setting, reload_bunfig_install_scopes_setting,
reload_critical_error_channels_setting, reload_extra_pip_index_url_setting,
reload_hub_base_url_setting, reload_job_default_timeout_setting, reload_license_key,
reload_npm_config_registry_setting, reload_pip_index_url_setting,
reload_retention_period_setting, reload_scim_token_setting, reload_server_config,
reload_worker_config,
initial_load, load_keep_job_dir, load_metrics_debug_enabled, load_require_preexisting_user,
load_tag_per_workspace_enabled, monitor_db, monitor_pool, reload_base_url_setting,
reload_bunfig_install_scopes_setting, reload_critical_error_channels_setting,
reload_extra_pip_index_url_setting, reload_hub_base_url_setting,
reload_job_default_timeout_setting, reload_license_key, reload_npm_config_registry_setting,
reload_pip_index_url_setting, reload_retention_period_setting, reload_scim_token_setting,
reload_server_config, reload_worker_config,
};
#[cfg(feature = "parquet")]
@@ -321,6 +328,11 @@ Windmill Community Edition {GIT_VERSION}
monitor_pool(&db).await;
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
if !worker_mode {
monitor_mem().await;
}
let addr = SocketAddr::from((server_bind_address, port));
let rsmq2 = rsmq.clone();
@@ -347,7 +359,7 @@ Windmill Community Edition {GIT_VERSION}
base_internal_tx
.send(base_internal_url.clone())
.map_err(|e| {
anyhow::anyhow!("Could not send base_internal_url to agent: {e}")
anyhow::anyhow!("Could not send base_internal_url to agent: {e:#}")
})?;
}
Ok(()) as anyhow::Result<()>
@@ -447,7 +459,7 @@ Windmill Community Edition {GIT_VERSION}
},
DEFAULT_TAGS_PER_WORKSPACE_SETTING => {
if let Err(e) = load_tag_per_workspace_enabled(&db).await {
tracing::error!("Error loading default tag per workpsace: {e}");
tracing::error!("Error loading default tag per workpsace: {e:#}");
}
},
RETENTION_PERIOD_SECS_SETTING => {
@@ -481,8 +493,8 @@ Windmill Community Edition {GIT_VERSION}
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING => {
load_require_preexisting_user(&db).await;
},
EXPOSE_METRICS_SETTING | EXPOSE_DEBUG_METRICS_SETTING => {
if n.payload() != EXPOSE_DEBUG_METRICS_SETTING || worker_mode {
EXPOSE_METRICS_SETTING => {
if worker_mode {
tracing::info!("Metrics setting changed, restarting");
// we wait a bit randomly to avoid having all serverss and workers shutdown at same time
let rd_delay = rand::thread_rng().gen_range(0..4);
@@ -492,6 +504,11 @@ Windmill Community Edition {GIT_VERSION}
}
}
},
EXPOSE_DEBUG_METRICS_SETTING => {
if let Err(e) = load_metrics_debug_enabled(&db).await {
tracing::error!(error = %e, "Could not reload debug metrics setting");
}
},
REQUEST_SIZE_LIMIT_SETTING => {
if server_mode {
tracing::info!("Request limit size change detected, killing server expecting to be restarted");
@@ -546,7 +563,7 @@ Windmill Community Edition {GIT_VERSION}
});
if let Err(e) = h.await {
tracing::error!("Error waiting for monitor handle:{e}")
tracing::error!("Error waiting for monitor handle:{e:#}")
}
Ok(()) as anyhow::Result<()>
};
@@ -564,15 +581,13 @@ Windmill Community Edition {GIT_VERSION}
};
let instance_name = rd_string(8);
if mode != Mode::Agent {
schedule_stats(
instance_name,
mode.clone(),
&db,
&HTTP_CLIENT,
cfg!(feature = "enterprise"),
)
.await;
if mode == Mode::Server || mode == Mode::Standalone {
schedule_stats(instance_name, &db, &HTTP_CLIENT).await;
}
#[cfg(feature = "enterprise")]
if mode == Mode::Server || mode == Mode::Standalone {
schedule_key_renewal(&HTTP_CLIENT, &db).await;
}
futures::try_join!(shutdown_signal, workers_f, monitor_f, server_f, metrics_f)?;
@@ -672,8 +687,8 @@ pub async fn run_workers<R: rsmq_async::RsmqConnection + Send + Sync + Clone + '
})
.unwrap_or_else(|| rd_string(5));
#[cfg(tokio_unstable)]
let monitor = tokio_metrics::TaskMonitor::new();
// #[cfg(tokio_unstable)]
// let monitor = tokio_metrics::TaskMonitor::new();
let ip = windmill_common::external_ip::get_ip()
.await
@@ -732,15 +747,15 @@ pub async fn run_workers<R: rsmq_async::RsmqConnection + Send + Sync + Clone + '
agent_mode,
);
#[cfg(tokio_unstable)]
{
monitor.monitor(f, "worker").await
}
// #[cfg(tokio_unstable)]
// {
// monitor.monitor(f, "worker").await
// }
#[cfg(not(tokio_unstable))]
{
f.await
}
// #[cfg(not(tokio_unstable))]
// {
f.await
// }
}));
}
+119 -33
View File
@@ -22,10 +22,7 @@ use windmill_api::{
DEFAULT_BODY_LIMIT, IS_SECURE, OAUTH_CLIENTS, REQUEST_SIZE_LIMIT, SAML_METADATA, SCIM_TOKEN,
};
use windmill_common::{
ee::CriticalErrorChannel,
error,
flow_status::FlowStatusModule,
global_settings::{
ee::CriticalErrorChannel, error, flow_status::FlowStatusModule, global_settings::{
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, CRITICAL_ERROR_CHANNELS_SETTING,
DEFAULT_TAGS_PER_WORKSPACE_SETTING, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
EXTRA_PIP_INDEX_URL_SETTING, HUB_BASE_URL_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING,
@@ -33,17 +30,10 @@ use windmill_common::{
PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING,
},
jobs::QueuedJob,
oauth2::REQUIRE_PREEXISTING_USER_FOR_OAUTH,
server::load_server_config,
users::truncate_token,
worker::{
}, jobs::QueuedJob, oauth2::REQUIRE_PREEXISTING_USER_FOR_OAUTH, server::load_server_config, stats_ee::get_user_usage, users::truncate_token, utils::now_from_db, worker::{
load_worker_config, reload_custom_tags_setting, DEFAULT_TAGS_PER_WORKSPACE, SERVER_CONFIG,
WORKER_CONFIG,
},
BASE_URL, CRITICAL_ERROR_CHANNELS, DB, DEFAULT_HUB_BASE_URL, HUB_BASE_URL,
METRICS_DEBUG_ENABLED, METRICS_ENABLED,
}, BASE_URL, CRITICAL_ERROR_CHANNELS, DB, DEFAULT_HUB_BASE_URL, HUB_BASE_URL, METRICS_DEBUG_ENABLED, METRICS_ENABLED
};
use windmill_queue::cancel_job;
use windmill_worker::{
@@ -114,15 +104,15 @@ pub async fn initial_load(
_is_agent: bool,
) {
if let Err(e) = load_metrics_enabled(db).await {
tracing::error!("Error loading expose metrics: {e}");
tracing::error!("Error loading expose metrics: {e:#}");
}
if let Err(e) = load_metrics_debug_enabled(db).await {
tracing::error!("Error loading expose debug metrics: {e}");
tracing::error!("Error loading expose debug metrics: {e:#}");
}
if let Err(e) = load_tag_per_workspace_enabled(db).await {
tracing::error!("Error loading default tag per workpsace: {e}");
tracing::error!("Error loading default tag per workpsace: {e:#}");
}
if server_mode {
@@ -201,18 +191,113 @@ pub async fn load_tag_per_workspace_enabled(db: &DB) -> error::Result<()> {
pub async fn load_metrics_debug_enabled(db: &DB) -> error::Result<()> {
let metrics_enabled = load_value_from_global_settings(db, EXPOSE_DEBUG_METRICS_SETTING).await;
match metrics_enabled {
Ok(Some(serde_json::Value::Bool(t))) => METRICS_DEBUG_ENABLED.store(t, Ordering::Relaxed),
Ok(Some(serde_json::Value::Bool(t))) => {
METRICS_DEBUG_ENABLED.store(t, Ordering::Relaxed);
//_RJEM_MALLOC_CONF=prof:true,prof_active:false,lg_prof_interval:30,lg_prof_sample:21,prof_prefix:/tmp/jeprof
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
if std::env::var("_RJEM_MALLOC_CONF").is_ok() {
if let Err(e) = set_prof_active(t) {
tracing::error!("Error setting jemalloc prof_active: {e:?}");
}
}
},
_ => (),
};
Ok(())
}
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
#[derive(Debug, Clone)]
pub struct MallctlError { pub code: i32 }
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
fn set_prof_active(new_value: bool) -> Result<(), MallctlError> {
let option_name = std::ffi::CString::new("prof.active").unwrap();
tracing::info!("Setting jemalloc prof_active to {}", new_value);
let result = unsafe {
tikv_jemalloc_sys::mallctl(
option_name.as_ptr(), // const char *name
std::ptr::null_mut(), // void *oldp
std::ptr::null_mut(), // size_t *oldlenp
&new_value as *const _ as *mut _, // void *newp
std::mem::size_of_val(&new_value) // size_t newlen
)
};
if result != 0 {
return Err(MallctlError { code: result });
}
Ok(())
}
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
pub fn bytes_to_mb(bytes: u64) -> f64 {
const BYTES_PER_MB: f64 = 1_048_576.0;
bytes as f64 / BYTES_PER_MB
}
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
pub async fn monitor_mem() {
use std::time::Duration;
use tikv_jemalloc_ctl::{stats, epoch};
tokio::spawn(async move {
// Obtain a MIB for the `epoch`, `stats.allocated`, and
// `atats.resident` keys:
let e = match epoch::mib() {
Ok(mib) => mib,
Err(e) => {
tracing::error!("Error getting jemalloc epoch mib: {:?}", e);
return;
}
};
let allocated = match stats::allocated::mib() {
Ok(mib) => mib,
Err(e) => {
tracing::error!("Error getting jemalloc allocated mib: {:?}", e);
return;
}
};
let resident = match stats::resident::mib() {
Ok(mib) => mib,
Err(e) => {
tracing::error!("Error getting jemalloc resident mib: {:?}", e);
return;
}
};
loop {
// Many statistics are cached and only updated
// when the epoch is advanced:
match e.advance() {
Ok(_) => {
// Read statistics using MIB key:
let allocated = allocated.read().unwrap_or_default();
let resident = resident.read().unwrap_or_default();
tracing::info!("{} mb allocated/{} mb resident", bytes_to_mb(allocated as u64), bytes_to_mb(resident as u64));
},
Err(e) => {
tracing::error!("Error advancing jemalloc epoch: {:?}", e);
}
}
tokio::time::sleep(Duration::from_secs(30)).await;
}
});
}
pub async fn load_keep_job_dir(db: &DB) {
let value = load_value_from_global_settings(db, KEEP_JOB_DIR_SETTING).await;
match value {
Ok(Some(serde_json::Value::Bool(t))) => KEEP_JOB_DIR.store(t, Ordering::Relaxed),
Err(e) => {
tracing::error!("Error loading keep job dir metrics: {e}");
tracing::error!("Error loading keep job dir metrics: {e:#}");
}
_ => (),
};
@@ -226,7 +311,7 @@ pub async fn load_require_preexisting_user(db: &DB) {
REQUIRE_PREEXISTING_USER_FOR_OAUTH.store(t, Ordering::Relaxed)
}
Err(e) => {
tracing::error!("Error loading keep job dir metrics: {e}");
tracing::error!("Error loading keep job dir metrics: {e:#}");
}
_ => (),
};
@@ -794,20 +879,13 @@ pub async fn save_usage_metrics(db: &Pool<Postgres>) {
.map(|last_check| chrono::Utc::now() - last_check > chrono::Duration::hours(24) - chrono::Duration::minutes(random_nb % 60))
.unwrap_or(true)
{
let counts = sqlx::query!(
"WITH all_users as (SELECT count(*)::INT as count FROM usr WHERE disabled IS false),
authors as (SELECT count(distinct email)::INT as count FROM usr WHERE usr.operator IS false AND disabled IS false)
SELECT authors.count as author_count, all_users.count - authors.count as operator_count FROM all_users, authors"
)
.fetch_one(&mut *tx)
.await
.ok();
let user_usage = get_user_usage(&mut *tx).await.ok();
if let Some(counts) = counts {
if let Some(user_usage) = user_usage {
sqlx::query!(
"INSERT INTO metrics (id, value) VALUES ('author_count', $1), ('operator_count', $2)",
serde_json::json!(counts.author_count),
serde_json::json!(counts.operator_count)
serde_json::json!(user_usage.author_count.unwrap_or(0)),
serde_json::json!(user_usage.operator_count.unwrap_or(0))
)
.execute(&mut *tx)
.await
@@ -896,7 +974,7 @@ pub async fn reload_worker_config(
tracing::info!("Waiting 5 seconds to allow others workers to start potential jobs that depend on a potential shared cache volume");
tokio::time::sleep(Duration::from_secs(5)).await;
if let Err(e) = windmill_worker::common::clean_cache().await {
tracing::error!("Error cleaning the cache: {e}");
tracing::error!("Error cleaning the cache: {e:#}");
}
}
}
@@ -1025,11 +1103,16 @@ async fn handle_zombie_jobs<R: rsmq_async::RsmqConnection + Send + Sync + Clone>
mpsc::channel::<SameWorkerPayload>(1);
let (send_result_never_used, _send_result_rx_never_used) = mpsc::channel::<SendResult>(1);
let label = if job.permissioned_as != format!("u/{}", job.created_by) && job.permissioned_as != job.created_by {
format!("ephemeral-script-end-user-{}", job.created_by)
} else {
"ephemeral-script".to_string()
};
let token = create_token_for_owner(
&db,
&job.workspace_id,
&job.permissioned_as,
"ephemeral-script",
&label,
*SCRIPT_TOKEN_EXPIRY,
&job.email,
&job.id,
@@ -1105,11 +1188,13 @@ async fn handle_zombie_flows(
.await?;
} else {
let id = flow.id.clone();
let last_ping = flow.last_ping.clone();
let now = now_from_db(db).await?;
cancel_zombie_flow_job(
db,
flow,
&rsmq,
format!("Flow {} cancelled as it was hanging in between 2 steps", id),
format!("Flow {} cancelled as it was hanging in between 2 steps. Last ping: {last_ping:?} (now: {now})", id),
)
.await?;
}
@@ -1171,6 +1256,7 @@ async fn cancel_zombie_flow_job(
db,
rsmq.clone(),
false,
false
)
.await?;
sqlx::query!(
+1 -1
View File
@@ -71,7 +71,7 @@ if [ "$REVERT" == "YES" ]; then
ce_file="${ee_file/${EE_CODE_DIR}/.}"
ce_file="${root_dirpath}/backend/${ce_file}"
if [ "$REVERT_PREVIOUS" == "YES" ]; then
git checkout HEAD@{5} ${ce_file} || true
git checkout HEAD@{3} ${ce_file} || true
else
git restore --staged ${ce_file} || true
git restore ${ce_file} || true
+24 -21
View File
@@ -8,7 +8,6 @@ use futures::StreamExt;
use futures::{stream, Stream};
use serde::Deserialize;
use serde_json::json;
use sqlx::types::Json;
use sqlx::{postgres::PgListener, types::Uuid, Pool, Postgres};
#[cfg(feature = "enterprise")]
@@ -868,13 +867,17 @@ impl RunJob {
async fn push(self, db: &Pool<Postgres>) -> Uuid {
let RunJob { payload, args } = self;
let mut hm_args = std::collections::HashMap::new();
for (k, v) in args {
hm_args.insert(k, windmill_common::worker::to_raw_value(&v));
}
let tx = PushIsolationLevel::IsolatedRoot(db.clone(), None);
let (uuid, tx) = windmill_queue::push::<_, rsmq_async::MultiplexedRsmq>(
let (uuid, tx) = windmill_queue::push::<rsmq_async::MultiplexedRsmq>(
&db,
tx,
"test-workspace",
payload,
Json(args),
hm_args.into(),
/* user */ "test-user",
/* email */ "test@windmill.dev",
/* permissioned_as */ "u/test-user".to_string(),
@@ -1070,7 +1073,7 @@ async fn test_deno_flow(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1108,7 +1111,7 @@ async fn test_deno_flow(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1121,7 +1124,7 @@ async fn test_deno_flow(db: Pool<Postgres>) {
delete_after_use: None,
continue_on_error: None,
}],
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1207,12 +1210,12 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
input_transforms: [
(
"loop".to_string(),
InputTransform::Static { value: json!(false) },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&false) },
),
("i".to_string(), InputTransform::Static { value: json!(1) }),
("i".to_string(), InputTransform::Static { value: windmill_common::worker::to_raw_value(&1) }),
(
"path".to_string(),
InputTransform::Static { value: json!("outer.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"outer.txt") },
),
]
.into(),
@@ -1224,7 +1227,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1240,7 +1243,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
FlowModule {
id: "b".to_string(),
value: FlowModuleValue::ForloopFlow {
iterator: InputTransform::Static { value: json!([1, 2, 3]) },
iterator: InputTransform::Static { value: windmill_common::worker::to_raw_value(&[1, 2, 3]) },
skip_failures: false,
parallel: false,
parallelism: None,
@@ -1257,11 +1260,11 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
),
(
"loop".to_string(),
InputTransform::Static { value: json!(true) },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&true) },
),
(
"path".to_string(),
InputTransform::Static { value: json!("inner.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"inner.txt") },
),
]
.into(),
@@ -1273,7 +1276,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1291,10 +1294,10 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
value: FlowModuleValue::RawScript {
input_transforms: [(
"path".to_string(),
InputTransform::Static { value: json!("inner.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"inner.txt") },
), (
"path2".to_string(),
InputTransform::Static { value: json!("outer.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"outer.txt") },
)]
.into(),
language: ScriptLang::Deno,
@@ -1308,7 +1311,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1323,7 +1326,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
},
],
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
@@ -1346,11 +1349,11 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
),
(
"path".to_string(),
InputTransform::Static { value: json!("outer.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"outer.txt") },
),
(
"path2".to_string(),
InputTransform::Static { value: json!("inner.txt") },
InputTransform::Static { value: windmill_common::worker::to_raw_value(&"inner.txt") },
),
]
.into(),
@@ -1365,7 +1368,7 @@ async fn test_deno_flow_same_worker(db: Pool<Postgres>) {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}.into(),
stop_after_if: Default::default(),
summary: Default::default(),
suspend: Default::default(),
+6 -4
View File
@@ -15,7 +15,7 @@ stripe = ["dep:async-stripe"]
enterprise_saml = ["dep:samael"]
benchmark = []
embedding = ["dep:tinyvector", "dep:hf-hub", "dep:tokenizers", "dep:candle-core", "dep:candle-transformers", "dep:candle-nn"]
parquet = ["dep:polars", "dep:polars-io", "dep:object_store", "windmill-common/parquet"]
parquet = ["dep:datafusion", "dep:object_store", "dep:url", "windmill-common/parquet"]
prometheus = ["windmill-common/prometheus", "windmill-queue/prometheus", "dep:prometheus"]
openidconnect = ["dep:openidconnect"]
@@ -82,11 +82,13 @@ tokenizers = { workspace = true, optional = true}
candle-core = { workspace = true, optional = true}
candle-transformers = { workspace = true, optional = true}
candle-nn = { workspace = true, optional = true}
polars = { workspace = true, optional = true}
polars-io = { workspace = true, optional = true}
datafusion = { workspace = true, optional = true}
object_store = { workspace = true, optional = true}
openidconnect = { workspace = true, optional = true}
url = { workspace = true, optional = true}
pin-project.workspace = true
crc.workspace = true
http.workspace = true
async-stream.workspace = true
async-stream.workspace = true
ulid.workspace = true
+297 -46
View File
@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.331.2
version: 1.341.0
title: Windmill API
contact:
@@ -766,6 +766,45 @@ paths:
schema:
type: string
/settings/latest_key_renewal_attempt:
get:
summary: get latest key renewal attempt
operationId: getLatestKeyRenewalAttempt
tags:
- setting
responses:
"200":
description: status
content:
application/json:
schema:
type: object
properties:
result:
type: string
attempted_at:
type: string
format: date-time
required:
- result
- attempted_at
nullable: true
/settings/renew_license_key:
post:
summary: renew license key
operationId: renewLicenseKey
tags:
- setting
responses:
"200":
description: status
content:
text/plain:
schema:
type: string
/saml/test_metadata:
post:
summary: test metadata
@@ -2025,6 +2064,27 @@ paths:
items:
type: string
/w/{workspace}/users/username_to_email/{username}:
get:
summary: get email from username
operationId: usernameToEmail
tags:
- user
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: username
in: path
required: true
schema:
type: string
responses:
"200":
description: email
content:
text/plain:
schema:
type: string
/users/tokens/create:
post:
summary: create token
@@ -2557,16 +2617,40 @@ paths:
content:
application/json:
schema:
additionalProperties:
type: object
properties:
extra_params:
additionalProperties:
type: string
scopes:
type: array
items:
type: string
type: array
items:
type: string
/oauth/get_connect/{client}:
get:
summary: get oauth connect
operationId: getOAuthConnect
tags:
- oauth
parameters:
- name: client
description: client name
in: path
required: true
schema:
type: string
responses:
"200":
description: get
content:
application/json:
schema:
type: object
properties:
extra_params:
type: object
scopes:
type: array
items:
type: string
/w/{workspace}/resources/create:
post:
@@ -4900,6 +4984,8 @@ paths:
type: string
path:
type: string
lock:
type: string
cache_ttl:
type: integer
required:
@@ -4909,6 +4995,10 @@ paths:
type: object
force_viewer_one_of_fields:
type: object
force_viewer_allow_user_resources:
type: array
items:
type: string
required:
- args
- component
@@ -5622,6 +5712,22 @@ paths:
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/JobId"
- name: suspended_job
in: query
schema:
type: string
- name: resume_id
in: query
schema:
type: integer
- name: secret
in: query
schema:
type: string
- name: approver
in: query
schema:
type: string
responses:
"200":
description: result
@@ -5639,6 +5745,7 @@ paths:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/JobId"
- $ref: "#/components/parameters/GetStarted"
responses:
"200":
description: result
@@ -7626,12 +7733,16 @@ paths:
/w/{workspace}/job_helpers/test_connection:
get:
summary: Test connection to the workspace datasets storage
summary: Test connection to the workspace object storage
operationId: datasetStorageTestConnection
tags:
- helpers
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Connection settings
@@ -7641,7 +7752,7 @@ paths:
/w/{workspace}/job_helpers/list_stored_files:
get:
summary: List the file keys available in the workspace files storage (S3)
summary: List the file keys available in a workspace object storage
operationId: listStoredFiles
tags:
- helpers
@@ -7660,6 +7771,10 @@ paths:
in: query
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: List of file keys
@@ -7692,6 +7807,10 @@ paths:
required: true
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: FileMetadata
@@ -7737,6 +7856,10 @@ paths:
in: query
schema:
type: integer
- name: storage
in: query
schema:
type: string
responses:
"200":
description: FilePreview
@@ -7778,7 +7901,10 @@ paths:
in: query
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Parquet Preview
@@ -7786,6 +7912,50 @@ paths:
application/json:
schema: {}
/w/{workspace}/job_helpers/load_csv_preview/{path}:
get:
summary: Load a preview of a csv file
operationId: loadCsvPreview
tags:
- helpers
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/Path"
- name: offset
in: query
schema:
type: number
- name: limit
in: query
schema:
type: number
- name: sort_col
in: query
schema:
type: string
- name: sort_desc
in: query
schema:
type: boolean
- name: search_col
in: query
schema:
type: string
- name: search_term
in: query
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Csv Preview
content:
application/json:
schema: {}
/w/{workspace}/job_helpers/delete_s3_file:
delete:
summary: Permanently delete file from S3
@@ -7799,6 +7969,10 @@ paths:
required: true
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Confirmation
@@ -7824,6 +7998,10 @@ paths:
required: true
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Confirmation
@@ -7859,6 +8037,10 @@ paths:
required: false
schema:
type: string
- name: storage
in: query
schema:
type: string
requestBody:
description: File content
required: true
@@ -7903,6 +8085,10 @@ paths:
required: false
schema:
type: string
- name: storage
in: query
schema:
type: string
responses:
"200":
description: Chunk of the downloaded file
@@ -7912,6 +8098,37 @@ paths:
type: string
format: binary
/w/{workspace}/job_helpers/download_s3_parquet_file_as_csv:
get:
summary: Download file to S3 bucket
operationId: fileDownloadParquetAsCsv
tags:
- helpers
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: file_key
in: query
required: true
schema:
type: string
- name: s3_resource_path
in: query
required: false
schema:
type: string
- name: resource_type
in: query
required: false
schema:
type: string
responses:
"200":
description: The downloaded file
content:
text/csv:
schema:
type: string
/w/{workspace}/job_metrics/get/{id}:
post:
summary: get job metrics
@@ -8005,12 +8222,13 @@ paths:
application/json:
schema:
type: string
/w/{workspace}/concurrency_groups/intervals:
/w/{workspace}/concurrency_groups/list_jobs:
get:
summary: Get intervals of job runtime concurrency
operationId: getConcurrencyIntervals
operationId: listExtendedJobs
tags:
- concurrencyGroups
- job
parameters:
- name: concurrency_key
in: query
@@ -8078,7 +8296,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/ConcurrencyIntervals"
$ref: "#/components/schemas/ExtendedJobs"
components:
securitySchemes:
@@ -8516,6 +8734,8 @@ components:
type: integer
concurrency_time_window_s:
type: integer
concurrency_key:
type: string
cache_ttl:
type: number
dedicated_worker:
@@ -8822,6 +9042,10 @@ components:
type: string
priority:
type: integer
self_wait_time_ms:
type: number
aggregate_wait_time_ms:
type: number
required:
- id
- running
@@ -8939,6 +9163,10 @@ components:
type: array
items:
type: string
self_wait_time_ms:
type: number
aggregate_wait_time_ms:
type: number
required:
- id
- created_by
@@ -8955,6 +9183,16 @@ components:
- visible_to_owner
- tag
ObscuredJob:
type: object
properties:
typ:
type: string
started_at:
type: string
format: date-time
duration_ms:
type: number
Job:
oneOf:
- allOf:
@@ -9403,12 +9641,16 @@ components:
required:
- name
- typ
no_main_func:
type: boolean
nullable: true
required:
- star_args
- start_kwargs
- args
- type
- error
- no_main_func
Preview:
type: object
@@ -9838,6 +10080,14 @@ components:
type: string
occupancy_rate:
type: number
memory:
type: number
vcpus:
type: number
memory_usage:
type: number
wm_memory_usage:
type: number
required:
- worker
- worker_instance
@@ -10257,6 +10507,26 @@ components:
type: string
public_resource:
type: boolean
secondary_storage:
type: object
additionalProperties:
type: object
properties:
type:
type: string
enum:
[
"S3Storage",
"AzureBlobStorage",
"AzureWorkloadIdentity",
"S3AwsOidc",
]
s3_resource_path:
type: string
azure_blob_resource_path:
type: string
public_resource:
type: boolean
WindmillLargeFile:
type: object
@@ -10492,39 +10762,20 @@ components:
- concurrency_key
- total_running
ConcurrencyIntervals:
ExtendedJobs:
type: object
properties:
concurrency_key:
type: string
running_jobs:
jobs:
type: array
items:
type: object
properties:
job_id:
type: string
concurrency_key:
type: string
started_at:
type: string
format: date-time
completed_jobs:
$ref: "#/components/schemas/Job"
obscured_jobs:
type: array
items:
type: object
properties:
job_id:
type: string
concurrency_key:
type: string
started_at:
type: string
format: date-time
ended_at:
type: string
format: date-time
$ref : "#/components/schemas/ObscuredJob"
omitted_obscured_jobs:
description: "Obscured jobs omitted for security because of too specific filtering"
type: boolean
required:
- concurrency_key
- running_jobs
- completed_jobs
- jobs
- obscured_jobs
+196 -84
View File
@@ -9,7 +9,9 @@ use std::collections::HashMap;
*/
use crate::{
db::{ApiAuthed, DB},
resources::get_resource_value_interpolated_internal,
users::{require_owner_of_path, OptAuthed},
variables::encrypt,
webhook_util::{WebhookMessage, WebhookShared},
HTTP_CLIENT,
};
@@ -38,7 +40,8 @@ use windmill_common::{
utils::{
http_get_from_hub, not_found_if_none, paginate, query_elems_from_hub, Pagination, StripPath,
},
variables::build_crypt,
variables::{build_crypt, build_crypt_with_key_suffix},
worker::to_raw_value,
HUB_BASE_URL,
};
@@ -94,37 +97,37 @@ pub struct ListableApp {
pub struct AppVersion {
pub id: i64,
pub app_id: Uuid,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<RawValue>>,
pub created_by: String,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, FromRow)]
pub struct AppWithLastVersion {
pub id: i64,
pub path: String,
pub summary: String,
pub policy: serde_json::Value,
pub policy: sqlx::types::Json<Box<RawValue>>,
pub versions: Vec<i64>,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<RawValue>>,
pub created_by: String,
pub created_at: chrono::DateTime<chrono::Utc>,
pub extra_perms: serde_json::Value,
pub extra_perms: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, FromRow)]
pub struct AppWithLastVersionAndDraft {
pub id: i64,
pub path: String,
pub summary: String,
pub policy: serde_json::Value,
pub policy: sqlx::types::Json<Box<RawValue>>,
pub versions: Vec<i64>,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<RawValue>>,
pub created_by: String,
pub created_at: chrono::DateTime<chrono::Utc>,
pub extra_perms: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft: Option<serde_json::Value>,
pub draft: Option<sqlx::types::Json<Box<RawValue>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft_only: Option<bool>,
}
@@ -144,6 +147,7 @@ pub struct AppHistoryUpdate {
pub type StaticFields = HashMap<String, Box<RawValue>>;
pub type OneOfFields = HashMap<String, Vec<Box<RawValue>>>;
pub type AllowUserResources = Vec<String>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
@@ -157,6 +161,8 @@ pub enum ExecutionMode {
pub struct PolicyTriggerableInputs {
static_inputs: StaticFields,
one_of_inputs: OneOfFields,
#[serde(default)]
allow_user_resources: AllowUserResources,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -178,7 +184,7 @@ pub struct Policy {
pub struct CreateApp {
pub path: String,
pub summary: String,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<RawValue>>,
pub policy: Policy,
pub draft_only: Option<bool>,
pub deployment_message: Option<String>,
@@ -188,7 +194,7 @@ pub struct CreateApp {
pub struct EditApp {
pub path: Option<String>,
pub summary: Option<String>,
pub value: Option<serde_json::Value>,
pub value: Option<sqlx::types::Json<Box<RawValue>>>,
pub policy: Option<Policy>,
pub deployment_message: Option<String>,
}
@@ -196,7 +202,7 @@ pub struct EditApp {
#[derive(Serialize, FromRow)]
pub struct SearchApp {
path: String,
value: serde_json::Value,
value: sqlx::types::Json<Box<RawValue>>,
}
async fn list_search_apps(
authed: ApiAuthed,
@@ -210,12 +216,11 @@ async fn list_search_apps(
let n = 3;
let mut tx = user_db.begin(&authed).await?;
let rows = sqlx::query_as!(
SearchApp,
let rows = sqlx::query_as::<_, SearchApp>(
"SELECT path, app_version.value from app LEFT JOIN app_version ON app_version.id = versions[array_upper(versions, 1)] WHERE workspace_id = $1 LIMIT $2",
&w_id,
n
)
.bind(&w_id)
.bind(n)
.fetch_all(&mut *tx)
.await?
.into_iter()
@@ -293,15 +298,14 @@ async fn get_app(
let path = path.to_path();
let mut tx = user_db.begin(&authed).await?;
let app_o = sqlx::query_as!(
AppWithLastVersion,
let app_o = sqlx::query_as::<_, AppWithLastVersion>(
"SELECT app.id, app.path, app.summary, app.versions, app.policy,
app.extra_perms, app_version.value,
app_version.created_at, app_version.created_by from app, app_version
WHERE app.path = $1 AND app.workspace_id = $2 AND app_version.id = app.versions[array_upper(app.versions, 1)]",
path.to_owned(),
&w_id
)
.bind(path.to_owned())
.bind(&w_id)
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
@@ -318,21 +322,20 @@ async fn get_app_w_draft(
let path = path.to_path();
let mut tx = user_db.begin(&authed).await?;
let app_o = sqlx::query_as!(
AppWithLastVersionAndDraft,
let app_o = sqlx::query_as::<_, AppWithLastVersionAndDraft>(
r#"SELECT app.id, app.path, app.summary, app.versions, app.policy,
app.extra_perms, app_version.value,
app_version.created_at, app_version.created_by,
app.draft_only, draft.value as "draft?"
app.draft_only, draft.value as "draft"
from app
INNER JOIN app_version ON
app_version.id = app.versions[array_upper(app.versions, 1)]
LEFT JOIN draft ON
app.path = draft.path AND draft.workspace_id = $2 AND draft.typ = 'app'
WHERE app.path = $1 AND app.workspace_id = $2"#,
path.to_owned(),
&w_id
)
.bind(path.to_owned())
.bind(&w_id)
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
@@ -406,15 +409,14 @@ async fn get_app_by_id(
) -> JsonResult<AppWithLastVersion> {
let mut tx = user_db.begin(&authed).await?;
let app_o = sqlx::query_as!(
AppWithLastVersion,
let app_o = sqlx::query_as::<_, AppWithLastVersion>(
"SELECT app.id, app.path, app.summary, app.versions, app.policy,
app.extra_perms, app_version.value,
app_version.created_at, app_version.created_by from app, app_version
WHERE app_version.id = $1 AND app.id = app_version.app_id AND app.workspace_id = $2",
id,
&w_id
)
.bind(&id)
.bind(&w_id)
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
@@ -424,12 +426,12 @@ async fn get_app_by_id(
}
async fn get_public_app_by_secret(
OptAuthed(opt_authed): OptAuthed,
Extension(user_db): Extension<UserDB>,
Extension(db): Extension<DB>,
Path((w_id, secret)): Path<(String, String)>,
) -> JsonResult<AppWithLastVersion> {
let mut tx = db.begin().await?;
let mc = build_crypt(&mut tx, &w_id).await?;
let mc = build_crypt(&db, &w_id).await?;
let decrypted = mc
.decrypt_bytes_to_bytes(&(hex::decode(secret)?))
@@ -438,27 +440,46 @@ async fn get_public_app_by_secret(
let id: i64 = bytes.parse().map_err(to_anyhow)?;
let app_o = sqlx::query_as!(
AppWithLastVersion,
let app_o = sqlx::query_as::<_, AppWithLastVersion>(
"SELECT app.id, app.path, app.summary, app.versions, app.policy,
app.extra_perms, app_version.value,
null as extra_perms, app_version.value,
app_version.created_at, app_version.created_by from app, app_version
WHERE app.id = $1 AND app.workspace_id = $2 AND app_version.id = app.versions[array_upper(app.versions, 1)]",
id,
&w_id
)
.fetch_optional(&mut *tx)
WHERE app.id = $1 AND app.workspace_id = $2 AND app_version.id = app.versions[array_upper(app.versions, 1)]")
.bind(&id)
.bind(&w_id)
.fetch_optional(&db)
.await?;
tx.commit().await?;
let app = not_found_if_none(app_o, "App", id.to_string())?;
let policy = serde_json::from_value::<Policy>(app.policy.clone()).map_err(to_anyhow)?;
let policy = serde_json::from_str::<Policy>(app.policy.0.get()).map_err(to_anyhow)?;
if !matches!(policy.execution_mode, ExecutionMode::Anonymous) {
return Err(Error::NotAuthorized(
"App visibility does not allow public access".to_string(),
));
if matches!(policy.execution_mode, ExecutionMode::Anonymous) {
return Ok(Json(app));
}
if opt_authed.is_none() {
{
return Err(Error::NotAuthorized(
"App visibility does not allow public access and you are not logged in".to_string(),
));
}
} else {
let authed = opt_authed.unwrap();
let mut tx = user_db.begin(&authed).await?;
let is_visible = sqlx::query_scalar!(
"SELECT EXISTS(SELECT 1 FROM app WHERE id = $1 AND workspace_id = $2)",
id,
&w_id
)
.fetch_one(&mut *tx)
.await?;
tx.commit().await?;
if !is_visible.unwrap_or(false) {
return Err(Error::NotAuthorized(
"App visibility does not allow public access and you are logged in but you have no read-access to that app".to_string(),
));
}
}
Ok(Json(app))
@@ -488,6 +509,7 @@ async fn get_public_resource(
async fn get_secret_id(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> Result<String> {
let path = path.to_path();
@@ -501,15 +523,14 @@ async fn get_secret_id(
)
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
let id = not_found_if_none(id_o, "App", path.to_string())?;
let mc = build_crypt(&mut tx, &w_id).await?;
let mc = build_crypt(&db, &w_id).await?;
let hx = hex::encode(mc.encrypt_str_to_bytes(id.to_string()));
tx.commit().await?;
Ok(hx)
}
@@ -590,7 +611,7 @@ async fn create_app(
audit_log(
&mut tx,
&authed.username,
&authed,
"apps.create",
ActionKind::Create,
&w_id,
@@ -599,9 +620,9 @@ async fn create_app(
)
.await?;
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
let mut args: HashMap<String, Box<serde_json::value::RawValue>> = HashMap::new();
if let Some(dm) = app.deployment_message {
args.insert("deployment_message".to_string(), json!(dm));
args.insert("deployment_message".to_string(), to_raw_value(&dm));
}
let tx = PushIsolationLevel::Transaction(tx);
@@ -610,7 +631,7 @@ async fn create_app(
tx,
&w_id,
JobPayload::AppDependencies { path: app.path.clone(), version: v_id },
args,
PushArgs { args, extra: HashMap::new() },
&authed.username,
&authed.email,
windmill_common::users::username_to_permissioned_as(&authed.username),
@@ -655,7 +676,7 @@ async fn list_hub_apps(Extension(db): Extension<DB>) -> impl IntoResponse {
pub async fn get_hub_app_by_id(
Path(id): Path<i32>,
Extension(db): Extension<DB>,
) -> JsonResult<serde_json::Value> {
) -> JsonResult<Box<serde_json::value::RawValue>> {
let value = http_get_from_hub(
&HTTP_CLIENT,
&format!("{}/apps/{}/json", *HUB_BASE_URL.read().await, id),
@@ -706,7 +727,7 @@ async fn delete_app(
audit_log(
&mut *tx,
&authed.username,
&authed,
"apps.delete",
ActionKind::Delete,
&w_id,
@@ -741,7 +762,7 @@ async fn delete_app(
.await
.map_err(|e| {
Error::InternalErr(format!(
"error deleting deployment metadata for script with path {path} in workspace {w_id}: {e}"
"error deleting deployment metadata for script with path {path} in workspace {w_id}: {e:#}"
))
})?;
@@ -878,7 +899,7 @@ async fn update_app(
audit_log(
&mut tx,
&authed.username,
&authed,
"apps.update",
ActionKind::Update,
&w_id,
@@ -889,18 +910,18 @@ async fn update_app(
let tx: PushIsolationLevel<'_, rsmq_async::MultiplexedRsmq> =
PushIsolationLevel::Transaction(tx);
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
let mut args: HashMap<String, Box<serde_json::value::RawValue>> = HashMap::new();
if let Some(dm) = ns.deployment_message {
args.insert("deployment_message".to_string(), json!(dm));
args.insert("deployment_message".to_string(), to_raw_value(&dm));
}
args.insert("parent_path".to_string(), json!(path));
args.insert("parent_path".to_string(), to_raw_value(&path));
let (dependency_job_uuid, new_tx) = push(
&db,
tx,
&w_id,
JobPayload::AppDependencies { path: npath.clone(), version: v_id },
args,
PushArgs { args, extra: HashMap::new() },
&authed.username,
&authed.email,
windmill_common::users::username_to_permissioned_as(&authed.username),
@@ -945,6 +966,7 @@ pub struct ExecuteApp {
// if set, the app is executed as viewer with the given static fields
pub force_viewer_static_fields: Option<StaticFields>,
pub force_viewer_one_of_fields: Option<OneOfFields>,
pub force_viewer_allow_user_resources: Option<AllowUserResources>,
}
fn digest(code: &str) -> String {
@@ -957,6 +979,7 @@ fn digest(code: &str) -> String {
async fn execute_component(
OptAuthed(opt_authed): OptAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Extension(rsmq): Extension<Option<rsmq_async::MultiplexedRsmq>>,
Path((w_id, path)): Path<(String, StripPath)>,
Json(payload): Json<ExecuteApp>,
@@ -981,6 +1004,7 @@ async fn execute_component(
ExecuteApp {
force_viewer_static_fields: Some(static_fields),
force_viewer_one_of_fields: Some(one_of_fields),
force_viewer_allow_user_resources: Some(allow_user_resources),
..
} => {
let mut hm = HashMap::new();
@@ -991,6 +1015,7 @@ async fn execute_component(
PolicyTriggerableInputs {
static_inputs: static_fields,
one_of_inputs: one_of_fields,
allow_user_resources,
},
);
} else {
@@ -1003,6 +1028,7 @@ async fn execute_component(
PolicyTriggerableInputs {
static_inputs: static_fields,
one_of_inputs: one_of_fields,
allow_user_resources,
},
);
}
@@ -1032,22 +1058,31 @@ async fn execute_component(
let (username, permissioned_as, email) = match policy.execution_mode {
ExecutionMode::Anonymous => {
let username = opt_authed
.map(|a| a.username)
.as_ref()
.map(|a| a.username.clone())
.unwrap_or_else(|| "anonymous".to_string());
let (permissioned_as, email) = get_on_behalf_of(&policy)?;
(username, permissioned_as, email)
}
ExecutionMode::Publisher => {
let username = opt_authed.map(|a| a.username).ok_or_else(|| {
Error::BadRequest("publisher execution mode requires authentication".to_string())
})?;
let username = opt_authed
.as_ref()
.map(|a| a.username.clone())
.ok_or_else(|| {
Error::BadRequest(
"publisher execution mode requires authentication".to_string(),
)
})?;
let (permissioned_as, email) = get_on_behalf_of(&policy)?;
(username, permissioned_as, email)
}
ExecutionMode::Viewer => {
let (username, email) = opt_authed.map(|a| (a.username, a.email)).ok_or_else(|| {
Error::BadRequest("Required to be authed in viewer mode".to_string())
})?;
let (username, email) = opt_authed
.as_ref()
.map(|a| (a.username.clone(), a.email.clone()))
.ok_or_else(|| {
Error::BadRequest("Required to be authed in viewer mode".to_string())
})?;
(
username.clone(),
username_to_permissioned_as(&username),
@@ -1056,17 +1091,37 @@ async fn execute_component(
}
};
let (job_payload, args, tag) = match payload {
let (job_payload, (args, job_id), tag) = match payload {
ExecuteApp { args, component, raw_code: Some(raw_code), path: None, .. } => {
let content = &raw_code.content;
let payload = JobPayload::Code(raw_code.clone());
let path = digest(content);
let args = build_args(policy, &component, path, args)?;
let args = build_args(
policy,
&component,
path,
args,
opt_authed.as_ref(),
&user_db,
&db,
&w_id,
)
.await?;
(payload, args, None)
}
ExecuteApp { args, component, raw_code: None, path: Some(path), .. } => {
let (payload, tag) = get_payload_tag_from_prefixed_path(&path, &db, &w_id).await?;
let args = build_args(policy, &component, path.to_string(), args)?;
let args = build_args(
policy,
&component,
path.to_string(),
args,
opt_authed.as_ref(),
&user_db,
&db,
&w_id,
)
.await?;
(payload, args, tag)
}
_ => unreachable!(),
@@ -1086,7 +1141,7 @@ async fn execute_component(
None,
None,
None,
None,
job_id,
false,
false,
None,
@@ -1155,17 +1210,21 @@ async fn exists_app(
Ok(Json(exists))
}
fn build_args(
async fn build_args(
policy: Policy,
component: &str,
path: String,
args: HashMap<String, Box<RawValue>>,
) -> Result<PushArgs<HashMap<String, Box<RawValue>>>> {
authed: Option<&ApiAuthed>,
user_db: &UserDB,
db: &DB,
w_id: &str,
) -> Result<(PushArgs, Option<Uuid>)> {
let mut job_id: Option<Uuid> = None;
let key = format!("{}:{}", component, &path);
let (static_inputs, one_of_inputs) = match policy {
let (static_inputs, one_of_inputs, allow_user_resources) = match policy {
Policy { triggerables_v2: Some(t), .. } => {
let PolicyTriggerableInputs { static_inputs, one_of_inputs } = t
let PolicyTriggerableInputs { static_inputs, one_of_inputs, allow_user_resources } = t
.get(&key)
.or_else(|| t.get(&path))
.map(|x| x.clone())
@@ -1174,6 +1233,7 @@ fn build_args(
Some(PolicyTriggerableInputs {
static_inputs: HashMap::new(),
one_of_inputs: HashMap::new(),
allow_user_resources: Vec::new(),
})
} else {
None
@@ -1183,7 +1243,7 @@ fn build_args(
Error::BadRequest(format!("path {} is not allowed in the app policy", path))
})?;
(static_inputs, one_of_inputs)
(static_inputs, one_of_inputs, allow_user_resources)
}
Policy { triggerables: Some(t), .. } => {
let static_inputs = t
@@ -1201,7 +1261,7 @@ fn build_args(
Error::BadRequest(format!("path {} is not allowed in the app policy", path))
})?;
(static_inputs, HashMap::new())
(static_inputs, HashMap::new(), Vec::new())
}
_ => Err(Error::BadRequest(format!(
"Policy is missing triggerables for {}",
@@ -1212,7 +1272,55 @@ fn build_args(
let mut args = args.clone();
let mut safe_args = HashMap::<String, Box<RawValue>>::new();
// tracing::error!("{:?}", allow_user_resources);
for k in allow_user_resources.iter() {
if let Some(arg_val) = args.get(k) {
let key = serde_json::from_str::<String>(arg_val.get()).ok();
if let Some(path) =
key.and_then(|x| x.clone().strip_prefix("$res:").map(|x| x.to_string()))
{
if let Some(authed) = authed {
let res = get_resource_value_interpolated_internal(
authed,
Some(user_db.clone()),
db,
w_id,
&path,
None,
"",
)
.await?;
if res.is_none() {
return Err(Error::BadRequest(format!(
"Resource {} not found or not allowed for viewer",
path
)));
}
let job_id = if let Some(job_id) = job_id {
job_id
} else {
job_id = Some(ulid::Ulid::new().into());
job_id.unwrap()
};
let mc = build_crypt_with_key_suffix(&db, &w_id, &job_id.to_string()).await?;
let encrypted = encrypt(&mc, to_raw_value(&res.unwrap()).get());
safe_args.insert(
k.to_string(),
to_raw_value(&format!("$encrypted:{encrypted}")),
);
} else {
return Err(Error::BadRequest(
"User resources are not allowed without being logged in".to_string(),
));
}
}
}
}
for (k, v) in one_of_inputs {
if safe_args.contains_key(&k) {
continue;
}
if let Some(arg_val) = args.get(&k) {
let arg_str = arg_val.get();
@@ -1245,9 +1353,13 @@ fn build_args(
}
for (k, v) in args {
let arg_str = serde_json::to_string(&v).unwrap_or_else(|_| "".to_string());
if safe_args.contains_key(&k) {
continue;
}
if !arg_str.contains("$var:") && !arg_str.contains("$res:") {
let arg_str = v.get();
if !arg_str.contains("\"$var:") && !arg_str.contains("\"$res:") {
safe_args.insert(k.to_string(), v);
} else {
safe_args.insert(
@@ -1260,7 +1372,7 @@ fn build_args(
)
.replace(
"$res:",
"The following resource has been omitted for security reasons: ",
"The following resource has been omitted for security reasons, to allow it, toggle: 'Allow resources from users' on that field input: ",
),
)
.map_err(|e| {
@@ -1276,5 +1388,5 @@ fn build_args(
for (k, v) in static_inputs {
extra.insert(k.to_string(), v.to_owned());
}
Ok(PushArgs { extra, args: sqlx::types::Json(safe_args) })
Ok((PushArgs { extra, args: safe_args }, job_id))
}
+11 -10
View File
@@ -6,15 +6,12 @@
* LICENSE-AGPL for a copy of the license.
*/
use std::collections::HashMap;
use axum::{
extract::{Extension, Path},
routing::{get, post, put},
Router,
};
use hyper::StatusCode;
use serde_json::value::RawValue;
use sqlx::types::Json;
use windmill_common::{
db::UserDB,
@@ -89,7 +86,7 @@ pub async fn new_payload(
pub async fn update_payload(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
args: PushArgs<HashMap<String, Box<RawValue>>>,
args: PushArgs,
) -> Result<StatusCode> {
let mut tx = db.begin().await?;
@@ -102,7 +99,7 @@ pub async fn update_payload(
",
&w_id,
&path.to_path(),
Json(args) as Json<PushArgs<HashMap<String, Box<RawValue>>>>,
Json(args) as Json<PushArgs>,
)
.execute(&mut *tx)
.await?;
@@ -112,27 +109,31 @@ pub async fn update_payload(
Ok(StatusCode::NO_CONTENT)
}
#[derive(sqlx::FromRow)]
struct Payload {
payload: sqlx::types::Json<Box<serde_json::value::RawValue>>,
}
pub async fn get_payload(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<serde_json::Value> {
) -> JsonResult<Box<serde_json::value::RawValue>> {
let mut tx = user_db.begin(&authed).await?;
let payload = sqlx::query_scalar!(
let payload = sqlx::query_as::<_, Payload>(
"
SELECT payload
FROM capture
WHERE workspace_id = $1
AND path = $2
",
&w_id,
&path.to_path(),
)
.bind(&w_id)
.bind(&path.to_path())
.fetch_optional(&mut *tx)
.await?;
tx.commit().await?;
not_found_if_none(payload, "capture", path.to_path()).map(axum::Json)
not_found_if_none(payload.map(|x| x.payload.0), "capture", path.to_path()).map(axum::Json)
}
+148 -167
View File
@@ -1,6 +1,7 @@
use crate::db::{ApiAuthed, DB};
use crate::jobs::{
filter_list_completed_query, filter_list_queue_query, ListCompletedQuery, ListQueueQuery,
filter_list_completed_query, filter_list_queue_query, Job, ListCompletedQuery, ListQueueQuery,
UnifiedJob,
};
use crate::users::check_scopes;
use axum::extract::Path;
@@ -13,12 +14,10 @@ use axum::Router;
use serde::Serialize;
use sql_builder::bind::Bind;
use sql_builder::SqlBuilder;
use sqlx::postgres::PgRow;
use sqlx::{FromRow, Row};
use uuid::Uuid;
use windmill_common::db::UserDB;
use windmill_common::error::Error::{InternalErr, PermissionDenied};
use windmill_common::error::JsonResult;
use windmill_common::error::{self, JsonResult};
use windmill_common::utils::require_admin;
pub fn global_service() -> Router {
@@ -29,7 +28,7 @@ pub fn global_service() -> Router {
}
pub fn workspaced_service() -> Router {
Router::new().route("/intervals", get(get_concurrent_intervals))
Router::new().route("/list_jobs", get(get_concurrent_intervals))
}
#[derive(Serialize)]
@@ -107,58 +106,30 @@ async fn prune_concurrency_group(
}
#[derive(Serialize)]
struct ConcurrencyIntervals {
concurrency_key: Option<String>,
running_jobs: Vec<RunningJobDuration>,
completed_jobs: Vec<CompletedJobDuration>,
struct ExtendedJobs {
jobs: Vec<Job>,
obscured_jobs: Vec<ObscuredJob>,
omitted_obscured_jobs: bool,
}
#[derive(Serialize)]
struct CompletedJobDuration {
job_id: Option<Uuid>,
concurrency_key: Option<String>,
started_at: chrono::DateTime<chrono::Utc>,
ended_at: chrono::DateTime<chrono::Utc>,
}
impl<'r> FromRow<'r, PgRow> for CompletedJobDuration {
fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
let duration_ms: i64 = row.try_get("duration_ms")?;
let started_at = row.try_get("started_at")?;
let ended_at: chrono::DateTime<chrono::Utc> =
started_at + std::time::Duration::from_millis(duration_ms.try_into().unwrap());
Ok(Self {
job_id: row.try_get("id")?,
concurrency_key: row.try_get("key")?,
started_at,
ended_at,
})
}
}
#[derive(Serialize, FromRow)]
struct RunningJobDuration {
#[sqlx(rename = "id")]
job_id: Option<Uuid>,
#[sqlx(rename = "key")]
concurrency_key: Option<String>,
struct ObscuredJob {
typ: String,
started_at: Option<chrono::DateTime<chrono::Utc>>,
duration_ms: Option<i64>,
}
#[derive(Deserialize)]
struct ConcurrentIntervalsParams {
struct ExtendedJobsParams {
concurrency_key: Option<String>,
row_limit: Option<i64>,
}
fn join_concurrency_key<'c>(concurrency_key: Option<&String>, mut sqlb: SqlBuilder) -> SqlBuilder {
match concurrency_key {
Some(key) => sqlb
.join("concurrency_key")
.on_eq("id", "job_id")
.and_where_eq("key", "?".bind(key)),
None => sqlb.left().join("concurrency_key").on_eq("id", "job_id"),
};
if let Some(key) = concurrency_key {
sqlb.join("concurrency_key")
.on_eq("id", "concurrency_key.job_id")
.and_where_eq("key", "?".bind(key));
}
sqlb
}
@@ -168,100 +139,49 @@ async fn get_concurrent_intervals(
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path(w_id): Path<String>,
Query(iq): Query<ConcurrentIntervalsParams>,
Query(iq): Query<ExtendedJobsParams>,
Query(lq): Query<ListCompletedQuery>,
) -> JsonResult<ConcurrencyIntervals> {
) -> JsonResult<ExtendedJobs> {
check_scopes(&authed, || format!("listjobs"))?;
if lq.success.is_some() && lq.running.is_some_and(|x| x) {
return Err(error::Error::BadRequest(
"cannot specify both success and running".to_string(),
));
}
let row_limit = iq.row_limit.unwrap_or(1000);
let concurrency_key = iq.concurrency_key;
let lq_copy = lq.clone();
let lqq = ListQueueQuery {
script_path_start: lq_copy.script_path_start,
script_path_exact: lq_copy.script_path_exact,
script_hash: lq_copy.script_hash,
created_by: lq_copy.created_by,
started_before: lq_copy.started_before,
started_after: lq_copy.started_after,
created_before: lq_copy.created_before,
created_after: lq_copy.created_after,
created_or_started_before: lq_copy.created_or_started_before,
created_or_started_after: lq_copy.created_or_started_after,
running: lq_copy.running,
parent_job: lq_copy.parent_job,
order_desc: Some(true),
job_kinds: lq_copy.job_kinds,
suspended: lq_copy.suspended,
args: lq_copy.args,
tag: lq_copy.tag,
schedule_path: lq_copy.schedule_path,
scheduled_for_before_now: lq_copy.scheduled_for_before_now,
all_workspaces: lq_copy.all_workspaces,
is_flow_step: lq_copy.is_flow_step,
has_null_parent: lq_copy.has_null_parent,
is_not_schedule: lq_copy.is_not_schedule,
};
let lq = ListCompletedQuery { order_desc: Some(true), ..lq };
let lqc = lq.clone();
let lqq: ListQueueQuery = lqc.into();
let mut sqlb_q = SqlBuilder::select_from("queue")
.fields(&["id", "key", "started_at"])
.fields(UnifiedJob::queued_job_fields())
.order_by("created_at", lq.order_desc.unwrap_or(true))
.limit(row_limit)
.clone();
let mut sqlb_c = SqlBuilder::select_from("completed_job")
.fields(&["id", "key", "started_at", "duration_ms"])
.fields(UnifiedJob::completed_job_fields())
.order_by("started_at", lq.order_desc.unwrap_or(true))
.limit(row_limit)
.clone();
let mut sqlb_q_user = SqlBuilder::select_from("queue")
.fields(&["id"])
.order_by("created_at", lq.order_desc.unwrap_or(true))
.limit(row_limit)
.clone();
let mut sqlb_c_user = SqlBuilder::select_from("completed_job")
.fields(&["id"])
.order_by("started_at", lq.order_desc.unwrap_or(true))
.limit(row_limit)
.clone();
sqlb_q = join_concurrency_key(concurrency_key.as_ref(), sqlb_q);
sqlb_c = join_concurrency_key(concurrency_key.as_ref(), sqlb_c);
sqlb_q_user = join_concurrency_key(concurrency_key.as_ref(), sqlb_q_user);
sqlb_c_user = join_concurrency_key(concurrency_key.as_ref(), sqlb_c_user);
sqlb_q.and_where_is_not_null("started_at");
// When we have a concurrency key defined, fetch jobs from other workspaces
// as obscured unless we're in the admins workspace. This is to show the
// potential concurrency races without showing jobs that don't belong to
// the workspace.
let sqlb_all_workspaces: Option<(SqlBuilder, SqlBuilder)> =
if concurrency_key.is_some() && w_id != "admins" {
Some((
filter_list_queue_query(
sqlb_q.clone(),
&ListQueueQuery { all_workspaces: Some(true), ..lqq.clone() },
"admins",
),
filter_list_completed_query(
sqlb_c.clone(),
&ListCompletedQuery { all_workspaces: Some(true), ..lq.clone() },
"admins",
),
))
} else {
None
};
sqlb_q = filter_list_queue_query(sqlb_q, &lqq, w_id.as_str());
sqlb_c = filter_list_completed_query(sqlb_c, &lq, w_id.as_str());
let sql_q = sqlb_q.query()?;
let sql_c = sqlb_c.query()?;
let mut tx = user_db.begin(&authed).await?;
let running_jobs_user: Vec<RunningJobDuration> = if lq.success.is_none() {
sqlx::query_as(&sql_q).fetch_all(&mut *tx).await?
} else {
vec![]
};
let completed_jobs_user: Vec<CompletedJobDuration> = if lq.running.is_none() {
sqlx::query_as(&sql_c).fetch_all(&mut *tx).await?
} else {
vec![]
};
tx.commit().await?;
// To avoid infering information through filtering, don't return obscured
// jobs if the filters are too specific
let should_fetch_obscured_jobs = match lq {
ListCompletedQuery {
script_path_start: None,
@@ -277,10 +197,10 @@ async fn get_concurrent_intervals(
args: None,
result: None,
tag: None,
scheduled_for_before_now: None,
has_null_parent: None,
label: None,
is_not_schedule: None,
scheduled_for_before_now: _,
is_not_schedule: _,
started_before: _,
started_after: _,
created_before: _,
@@ -291,69 +211,130 @@ async fn get_concurrent_intervals(
job_kinds: _,
is_flow_step: _,
all_workspaces: _,
} => true,
} => concurrency_key.is_some(),
_ => false,
};
// This second transaction using the raw db lets us get info for jobs that
// the user has no access to. Before returning that, we will hide the ids
if should_fetch_obscured_jobs && concurrency_key.is_some() {
let (sql_q, sql_c) = if let Some(sqlb) = sqlb_all_workspaces {
(sqlb.0.query()?, sqlb.1.query()?)
} else {
(sql_q, sql_c)
};
// When we have a concurrency key defined, fetch jobs from other workspaces
// as obscured unless we're in the admins workspace. This is to show the
// potential concurrency races without showing jobs that don't belong to
// the workspace.
// To avoid infering information through filtering, don't return obscured
// jobs if the filters are too specific
if should_fetch_obscured_jobs && w_id != "admins" {
// Get the obscured jobs from all workspaces (concurrency key could be global)
let (sqlb_q, sqlb_c) = (
filter_list_queue_query(
sqlb_q,
&ListQueueQuery { all_workspaces: Some(true), ..lqq.clone() },
"admins",
true,
),
filter_list_completed_query(
sqlb_c,
&ListCompletedQuery { all_workspaces: Some(true), ..lq.clone() },
"admins",
true,
),
);
let running_jobs_db: Vec<RunningJobDuration> = if lq.success.is_none() {
sqlb_q_user = filter_list_queue_query(sqlb_q_user, &lqq, w_id.as_str(), true);
sqlb_c_user = filter_list_completed_query(sqlb_c_user, &lq, w_id.as_str(), true);
let sql_q_user = sqlb_q_user.query()?;
let sql_c_user = sqlb_c_user.query()?;
let sql_q = sqlb_q.query()?;
let sql_c = sqlb_c.query()?;
// This first transaction uses the user_db to know which uuids are
// accessible to the user.
let mut tx = user_db.begin(&authed).await?;
let running_jobs_user: Vec<Uuid> = if lq.success.is_none() {
sqlx::query_scalar(&sql_q_user).fetch_all(&mut *tx).await?
} else {
vec![]
};
let completed_jobs_user: Vec<Uuid> = if lq.running.is_none() {
sqlx::query_scalar(&sql_c_user).fetch_all(&mut *tx).await?
} else {
vec![]
};
tx.commit().await?;
// This second transaction uses the db, so it will fetch information
// potentially forbidden to the user. It must be obscured before
// returning it
let running_jobs_db: Vec<UnifiedJob> = if lq.success.is_none() {
sqlx::query_as(&sql_q).fetch_all(&db).await?
} else {
vec![]
};
let completed_jobs_db: Vec<CompletedJobDuration> = if lq.running.is_none() {
let completed_jobs_db: Vec<UnifiedJob> = if lq.running.is_none() {
sqlx::query_as(&sql_c).fetch_all(&db).await?
} else {
vec![]
};
let running_jobs = running_jobs_db
.into_iter()
.map(|r| {
if running_jobs_user
let obscured_jobs = running_jobs_db
.iter()
.filter(|j| !running_jobs_user.iter().any(|id| j.id == *id))
.chain(
completed_jobs_db
.iter()
.any(|u| u.job_id.unwrap() == r.job_id.unwrap())
{
RunningJobDuration { ..r }
} else {
RunningJobDuration { job_id: None, ..r }
}
.filter(|j| !completed_jobs_user.iter().any(|id| j.id == *id)),
)
.map(|j| ObscuredJob {
typ: j.typ.clone(),
started_at: j.started_at,
duration_ms: j.duration_ms,
})
.collect();
let completed_jobs = completed_jobs_db
let jobs = running_jobs_db
.into_iter()
.map(|r| {
if completed_jobs_user
.iter()
.any(|u| u.job_id.unwrap() == r.job_id.unwrap())
{
CompletedJobDuration { ..r }
} else {
CompletedJobDuration { job_id: None, ..r }
}
})
.filter(|j| running_jobs_user.iter().any(|id| j.id == *id))
.chain(
completed_jobs_db
.into_iter()
.filter(|j| completed_jobs_user.iter().any(|id| j.id == *id)),
)
.map(From::from)
.collect();
Ok(Json(ExtendedJobs {
jobs,
obscured_jobs,
omitted_obscured_jobs: !should_fetch_obscured_jobs,
}))
} else {
sqlb_q = filter_list_queue_query(sqlb_q, &lqq, w_id.as_str(), true);
sqlb_c = filter_list_completed_query(sqlb_c, &lq, w_id.as_str(), true);
let sql_q = sqlb_q.query()?;
let sql_c = sqlb_c.query()?;
let mut tx = user_db.begin(&authed).await?;
let running_jobs: Vec<UnifiedJob> = if lq.success.is_none() {
sqlx::query_as(&sql_q).fetch_all(&mut *tx).await?
} else {
vec![]
};
let completed_jobs: Vec<UnifiedJob> = if lq.running.is_none() {
sqlx::query_as(&sql_c).fetch_all(&mut *tx).await?
} else {
vec![]
};
tx.commit().await?;
let jobs = running_jobs
.into_iter()
.chain(completed_jobs.into_iter())
.map(From::from)
.collect();
return Ok(Json(ConcurrencyIntervals {
concurrency_key,
running_jobs,
completed_jobs,
}));
Ok(Json(ExtendedJobs {
jobs,
obscured_jobs: vec![],
omitted_obscured_jobs: !should_fetch_obscured_jobs,
}))
}
Ok(Json(ConcurrencyIntervals {
concurrency_key,
running_jobs: running_jobs_user,
completed_jobs: completed_jobs_user,
}))
}
async fn get_concurrency_key(
+2 -2
View File
@@ -122,7 +122,7 @@ async fn update_config(
audit_log(
&mut *tx,
&authed.username,
&authed,
"worker_config.update",
ActionKind::Update,
"global",
@@ -149,7 +149,7 @@ async fn delete_config(
audit_log(
&mut *tx,
&authed.username,
&authed,
"worker_config.delete",
ActionKind::Delete,
"global",
+26 -3
View File
@@ -15,6 +15,7 @@ use sqlx::{
pool::PoolConnection,
PgConnection, Pool, Postgres,
};
use windmill_audit::audit_ee::{AuditAuthor, AuditAuthorable};
use windmill_common::{
db::{Authable, Authed},
error::Error,
@@ -85,7 +86,7 @@ impl Migrate for CustomMigrator {
.fetch_one(&mut *self.inner)
.await
.map_err(|e| {
tracing::error!("Error acquiring lock: {e}");
tracing::error!("Error acquiring lock: {e:#}");
sqlx::migrate::MigrateError::Execute(e)
})?
.unwrap_or(false);
@@ -174,7 +175,7 @@ pub async fn migrate(db: &DB) -> Result<(), Error> {
Err(sqlx::migrate::MigrateError::VersionMissing(e)) => {
tracing::error!("Database had been applied more migrations than this container.
This usually mean than another container on a more recent version migrated the database and this one is on an earlier version.
Please update the container to latest. Not critical, but may cause issues if migration introduced a breaking change. Version missing: {e}");
Please update the container to latest. Not critical, but may cause issues if migration introduced a breaking change. Version missing: {e:#}");
custom_migrator.unlock().await?;
Ok(())
}
@@ -183,7 +184,7 @@ pub async fn migrate(db: &DB) -> Result<(), Error> {
#[cfg(feature = "enterprise")]
if let Err(e) = windmill_migrations(&mut custom_migrator, db).await {
tracing::error!("Could not apply windmill custom migrations: {e}")
tracing::error!("Could not apply windmill custom migrations: {e:#}")
}
Ok(())
@@ -246,12 +247,34 @@ impl From<ApiAuthed> for Authed {
}
}
impl From<&ApiAuthed> for AuditAuthor {
fn from(value: &ApiAuthed) -> Self {
Self {
email: value.email.clone(),
username: value.username.clone(),
username_override: value.username_override.clone(),
}
}
}
impl ApiAuthed {
pub fn display_username(&self) -> &str {
self.username_override.as_ref().unwrap_or(&self.username)
}
}
impl AuditAuthorable for ApiAuthed {
fn username(&self) -> &str {
self.username.as_str()
}
fn email(&self) -> &str {
self.email.as_str()
}
fn username_override(&self) -> Option<&str> {
self.username_override.as_deref()
}
}
impl Authable for ApiAuthed {
fn is_admin(&self) -> bool {
self.is_admin
+1 -1
View File
@@ -38,7 +38,7 @@ pub enum DraftType {
#[derive(Deserialize, Serialize, Debug)]
pub struct Draft {
pub path: String,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<serde_json::value::Value>>,
pub typ: DraftType,
}
+59 -48
View File
@@ -25,12 +25,12 @@ use axum::{
use hyper::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json::json;
use sql_builder::prelude::*;
use sqlx::{FromRow, Postgres, Transaction};
use windmill_audit::audit_ee::audit_log;
use windmill_audit::ActionKind;
use windmill_common::utils::query_elems_from_hub;
use windmill_common::worker::to_raw_value;
use windmill_common::HUB_BASE_URL;
use windmill_common::{
db::UserDB,
@@ -71,7 +71,7 @@ pub fn global_service() -> Router {
#[derive(Serialize, FromRow)]
pub struct SearchFlow {
path: String,
value: serde_json::Value,
value: sqlx::types::Json<Box<serde_json::value::RawValue>>,
}
async fn list_search_flows(
authed: ApiAuthed,
@@ -85,12 +85,11 @@ async fn list_search_flows(
let n = 3;
let mut tx = user_db.begin(&authed).await?;
let rows = sqlx::query_as!(
SearchFlow,
let rows = sqlx::query_as::<_, SearchFlow>(
"SELECT path, value from flow WHERE workspace_id = $1 LIMIT $2",
&w_id,
n
)
.bind(&w_id)
.bind(n)
.fetch_all(&mut *tx)
.await?
.into_iter()
@@ -200,7 +199,7 @@ async fn list_paths(
pub async fn get_hub_flow_by_id(
Path(id): Path<i32>,
Extension(db): Extension<DB>,
) -> JsonResult<serde_json::Value> {
) -> JsonResult<Box<serde_json::value::RawValue>> {
let value = http_get_from_hub(
&HTTP_CLIENT,
&format!("{}/flows/{}/json", *HUB_BASE_URL.read().await, id),
@@ -349,7 +348,7 @@ async fn create_flow(
audit_log(
&mut tx,
&authed.username,
&authed,
"flows.create",
ActionKind::Create,
&w_id,
@@ -363,9 +362,9 @@ async fn create_flow(
)
.await?;
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
let mut args: HashMap<String, Box<serde_json::value::RawValue>> = HashMap::new();
if let Some(dm) = nf.deployment_message {
args.insert("deployment_message".to_string(), json!(dm));
args.insert("deployment_message".to_string(), to_raw_value(&dm));
}
let tx = PushIsolationLevel::Transaction(tx);
@@ -377,7 +376,7 @@ async fn create_flow(
path: nf.path.clone(),
dedicated_worker: nf.dedicated_worker,
},
args,
args.into(),
&authed.username,
&authed.email,
windmill_common::users::username_to_permissioned_as(&authed.username),
@@ -505,7 +504,7 @@ async fn update_flow(
nf.visible_to_runner_only.unwrap_or(false),
)
.execute(&mut tx)
.await?;
.await.map_err(|e| error::Error::InternalErr(format!("Error updating flow due to flow update: {e:#}")))?;
if nf.path != flow_path {
check_schedule_conflict(tx.transaction_mut(), &w_id, &nf.path).await?;
@@ -515,24 +514,21 @@ async fn update_flow(
}
}
let mut schedulables: Vec<Schedule> = sqlx::query_as!(
Schedule,
"UPDATE schedule SET script_path = $1 WHERE script_path = $2 AND path != $2 AND workspace_id = $3 AND is_flow IS true RETURNING *",
nf.path,
flow_path,
w_id,
)
let mut schedulables: Vec<Schedule> = sqlx::query_as::<_, Schedule>(
"UPDATE schedule SET script_path = $1 WHERE script_path = $2 AND path != $2 AND workspace_id = $3 AND is_flow IS true RETURNING *")
.bind(&nf.path)
.bind(&flow_path)
.bind(&w_id)
.fetch_all(&mut tx)
.await?;
.await.map_err(|e| error::Error::InternalErr(format!("Error updating flow due to related schedules update: {e:#}")))?;
let schedule = sqlx::query_as!(Schedule,
"UPDATE schedule SET path = $1, script_path = $1 WHERE path = $2 AND workspace_id = $3 AND is_flow IS true RETURNING *",
nf.path,
flow_path,
w_id,
)
let schedule = sqlx::query_as::<_, Schedule>(
"UPDATE schedule SET path = $1, script_path = $1 WHERE path = $2 AND workspace_id = $3 AND is_flow IS true RETURNING *")
.bind(&nf.path)
.bind(&flow_path)
.bind(&w_id)
.fetch_optional(&mut tx)
.await?;
.await.map_err(|e| error::Error::InternalErr(format!("Error updating flow due to related schedule update: {e:#}")))?;
if let Some(schedule) = schedule {
clear_schedule(tx.transaction_mut(), &flow_path, &w_id).await?;
@@ -557,7 +553,7 @@ async fn update_flow(
audit_log(
&mut tx,
&authed.username,
&authed,
"flows.update",
ActionKind::Create,
&w_id,
@@ -582,11 +578,11 @@ async fn update_flow(
let tx = PushIsolationLevel::Transaction(tx);
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
let mut args: HashMap<String, Box<serde_json::value::RawValue>> = HashMap::new();
if let Some(dm) = nf.deployment_message {
args.insert("deployment_message".to_string(), json!(dm));
args.insert("deployment_message".to_string(), to_raw_value(&dm));
}
args.insert("parent_path".to_string(), json!(flow_path));
args.insert("parent_path".to_string(), to_raw_value(&flow_path));
let (dependency_job_uuid, mut new_tx) = push(
&db,
@@ -596,7 +592,7 @@ async fn update_flow(
path: nf.path.clone(),
dedicated_worker: nf.dedicated_worker,
},
args,
windmill_queue::PushArgs { args, extra: HashMap::new() },
&authed.username,
&authed.email,
windmill_common::users::username_to_permissioned_as(&authed.username),
@@ -622,14 +618,24 @@ async fn update_flow(
w_id
)
.execute(&mut new_tx)
.await?;
.await
.map_err(|e| {
error::Error::InternalErr(format!(
"Error updating flow due to updating dependency job field: {e:#}"
))
})?;
if let Some(old_dep_job) = old_dep_job {
sqlx::query!(
"UPDATE queue SET canceled = true WHERE id = $1",
old_dep_job
)
.execute(&mut new_tx)
.await?;
.await
.map_err(|e| {
error::Error::InternalErr(format!(
"Error updating flow due to cancelling dependency job: {e:#}"
))
})?;
}
new_tx.commit().await?;
@@ -663,10 +669,10 @@ pub struct FlowWDraft {
pub summary: String,
pub description: String,
pub schema: Option<Schema>,
pub value: serde_json::Value,
pub value: sqlx::types::Json<Box<serde_json::value::RawValue>>,
pub extra_perms: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft: Option<serde_json::Value>,
pub draft: Option<sqlx::types::Json<Box<serde_json::value::RawValue>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft_only: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -750,7 +756,7 @@ async fn archive_flow_by_path(
audit_log(
&mut *tx,
&authed.username,
&authed,
"flows.archive",
ActionKind::Delete,
&w_id,
@@ -817,7 +823,7 @@ async fn delete_flow_by_path(
audit_log(
&mut *tx,
&authed.username,
&authed,
"flows.delete",
ActionKind::Delete,
&w_id,
@@ -848,7 +854,7 @@ async fn delete_flow_by_path(
.await
.map_err(|e| {
Error::InternalErr(format!(
"error deleting deployment metadata for script with path {path} in workspace {w_id}: {e}"
"error deleting deployment metadata for script with path {path} in workspace {w_id}: {e:#}"
))
})?;
@@ -881,16 +887,18 @@ mod tests {
modules: vec![
FlowModule {
id: "a".to_string(),
value: FlowModuleValue::Script {
value: windmill_common::worker::to_raw_value(&FlowModuleValue::Script {
path: "test".to_string(),
input_transforms: [(
"test".to_string(),
InputTransform::Static { value: serde_json::json!("test2") },
InputTransform::Static {
value: windmill_common::worker::to_raw_value(&"test2".to_string()),
},
)]
.into(),
hash: None,
tag_override: None,
},
}),
stop_after_if: None,
summary: None,
suspend: Default::default(),
@@ -905,7 +913,7 @@ mod tests {
},
FlowModule {
id: "b".to_string(),
value: FlowModuleValue::RawScript {
value: windmill_common::worker::to_raw_value(&FlowModuleValue::RawScript {
input_transforms: HashMap::new(),
content: "test".to_string(),
language: scripts::ScriptLang::Deno,
@@ -915,7 +923,7 @@ mod tests {
custom_concurrency_key: None,
concurrent_limit: None,
concurrency_time_window_s: None,
},
}),
stop_after_if: Some(StopAfterIf {
expr: "foo = 'bar'".to_string(),
skip_if_stopped: false,
@@ -933,13 +941,15 @@ mod tests {
},
FlowModule {
id: "c".to_string(),
value: FlowModuleValue::ForloopFlow {
iterator: InputTransform::Static { value: serde_json::json!([1, 2, 3]) },
value: windmill_common::worker::to_raw_value(&FlowModuleValue::ForloopFlow {
iterator: InputTransform::Static {
value: windmill_common::worker::to_raw_value(&[1, 2, 3]),
},
modules: vec![],
skip_failures: true,
parallel: false,
parallelism: None,
},
}),
stop_after_if: Some(StopAfterIf {
expr: "previous.isEmpty()".to_string(),
skip_if_stopped: false,
@@ -963,7 +973,8 @@ mod tests {
input_transforms: HashMap::new(),
hash: None,
tag_override: None,
},
}
.into(),
stop_after_if: Some(StopAfterIf {
expr: "previous.isEmpty()".to_string(),
skip_if_stopped: false,
+5 -5
View File
@@ -223,7 +223,7 @@ async fn create_folder(
audit_log(
&mut *tx,
&authed.username,
&authed,
"folder.create",
ActionKind::Create,
&w_id,
@@ -356,7 +356,7 @@ async fn update_folder(
audit_log(
&mut *tx,
&authed.username,
&authed,
"folder.update",
ActionKind::Update,
&w_id,
@@ -522,7 +522,7 @@ async fn delete_folder(
audit_log(
&mut *tx,
&authed.username,
&authed,
"folder.delete",
ActionKind::Delete,
&w_id,
@@ -585,7 +585,7 @@ async fn add_owner(
audit_log(
&mut *tx,
&authed.username,
&authed,
"folder.add_owner",
ActionKind::Update,
&w_id,
@@ -664,7 +664,7 @@ async fn remove_owner(
audit_log(
&mut *tx,
&authed.username,
&authed,
"folder.remove_owner",
ActionKind::Update,
&w_id,
+10 -10
View File
@@ -252,7 +252,7 @@ async fn create_group(
audit_log(
&mut *tx,
&authed.username,
&authed,
"group.create",
ActionKind::Create,
&w_id,
@@ -296,7 +296,7 @@ async fn create_igroup(
audit_log(
&mut *tx,
&authed.username,
&authed,
"igroup.create",
ActionKind::Create,
"global",
@@ -337,7 +337,7 @@ async fn update_igroup(
audit_log(
&mut *tx,
&authed.username,
&authed,
"igroup.updated",
ActionKind::Delete,
"global",
@@ -367,7 +367,7 @@ async fn delete_igroup(
audit_log(
&mut *tx,
&authed.username,
&authed,
"igroup.delete",
ActionKind::Delete,
"global",
@@ -472,7 +472,7 @@ async fn delete_group(
.await?;
audit_log(
&mut *tx,
&authed.username,
&authed,
"group.delete",
ActionKind::Delete,
&w_id,
@@ -522,7 +522,7 @@ async fn update_group(
audit_log(
&mut *tx,
&authed.username,
&authed,
"group.edit",
ActionKind::Update,
&w_id,
@@ -573,7 +573,7 @@ async fn add_user(
audit_log(
&mut *tx,
&authed.username,
&authed,
"group.adduser",
ActionKind::Update,
&w_id,
@@ -624,7 +624,7 @@ async fn add_user_igroup(
audit_log(
&mut *tx,
&authed.username,
&authed,
"igroup.adduser",
ActionKind::Update,
"global",
@@ -693,7 +693,7 @@ async fn remove_user_igroup(
audit_log(
&mut *tx,
&authed.username,
&authed,
"igroup.removeuser",
ActionKind::Update,
"global",
@@ -733,7 +733,7 @@ async fn remove_user(
audit_log(
&mut *tx,
&authed.username,
&authed,
"group.removeuser",
ActionKind::Update,
&w_id,
+9 -7
View File
@@ -47,7 +47,7 @@ pub struct InputRow {
pub runnable_id: String,
pub runnable_type: RunnableType,
pub name: String,
pub args: Value,
pub args: sqlx::types::Json<Box<serde_json::value::RawValue>>,
pub created_at: DateTime<Utc>,
pub created_by: String,
pub is_public: bool,
@@ -95,12 +95,12 @@ pub struct RunnableParams {
pub runnable_type: RunnableType,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct Input {
id: Uuid,
name: String,
created_at: chrono::DateTime<chrono::Utc>,
args: serde_json::Value,
args: sqlx::types::Json<Box<serde_json::value::RawValue>>,
created_by: String,
is_public: bool,
success: bool,
@@ -110,7 +110,7 @@ pub struct Input {
pub struct CompletedJobMini {
id: Uuid,
created_at: chrono::DateTime<chrono::Utc>,
args: Option<serde_json::Value>,
args: Option<sqlx::types::Json<Box<serde_json::value::RawValue>>>,
created_by: String,
success: bool,
}
@@ -161,7 +161,9 @@ async fn get_input_history(
row.created_by
),
created_at: row.created_at,
args: row.args.unwrap_or(serde_json::json!({})),
args: row.args.unwrap_or(sqlx::types::Json(
serde_json::value::RawValue::from_string("null".to_string()).unwrap(),
)),
created_by: row.created_by,
is_public: true,
success: row.success,
@@ -240,7 +242,7 @@ async fn list_saved_inputs(
#[derive(Debug, Serialize, Deserialize)]
pub struct CreateInput {
name: String,
args: serde_json::Value,
args: Box<serde_json::value::RawValue>,
}
async fn create_input(
@@ -262,7 +264,7 @@ async fn create_input(
.bind(&r.runnable_id)
.bind(&r.runnable_type)
.bind(&input.name)
.bind(&input.args)
.bind(sqlx::types::Json(&input.args))
.bind(&authed.username)
.execute(&mut *tx)
.await?;

Some files were not shown because too many files have changed in this diff Show More