Compare commits

..

1 Commits

Author SHA1 Message Date
hcourdent
4067425342 Result node message 2024-11-15 16:32:38 +01:00
316 changed files with 4976 additions and 11397 deletions

View File

@@ -31,7 +31,7 @@ jobs:
ports:
- 8000:8000
steps:
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: benchmark
@@ -72,7 +72,7 @@ jobs:
ports:
- 8000:8000
steps:
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: benchmark
@@ -146,7 +146,7 @@ jobs:
--pull always
steps:
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: benchmark
@@ -264,7 +264,7 @@ jobs:
options: >-
--pull always
steps:
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: benchmark
@@ -289,7 +289,7 @@ jobs:
- benchmark_4workers
- benchmark_8workers
steps:
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- uses: actions/checkout@v4

View File

@@ -3,7 +3,8 @@ env:
IMAGE_NAME: ${{ github.repository }}
name: Build and publish windmill for RHEL9
on: workflow_dispatch
on:
workflow_dispatch
permissions: write-all
@@ -64,7 +65,7 @@ jobs:
platforms: linux/amd64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core,kafka
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core
secrets: |
rh_username=${{ secrets.RH_USERNAME }}
rh_password=${{ secrets.RH_PASSWORD }}
@@ -73,7 +74,7 @@ jobs:
labels: |
${{ steps.meta-ee-public.outputs.labels }}-amd64
org.opencontainers.image.licenses=Windmill-Enterprise-License
- name: Build and push publicly ee arm64
uses: depot/build-push-action@v1
with:
@@ -81,7 +82,7 @@ jobs:
platforms: linux/arm64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core,kafka
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core
secrets: |
rh_username=${{ secrets.RH_USERNAME }}
rh_password=${{ secrets.RH_PASSWORD }}
@@ -107,7 +108,7 @@ jobs:
run: |
mv "${{ steps.extract-ee-amd64.outputs.destination }}/windmill" "${{ steps.extract-ee-amd64.outputs.destination }}/windmill-ee-amd64-rhel9"
mv "${{ steps.extract-ee-arm64.outputs.destination }}/windmill" "${{ steps.extract-ee-arm64.outputs.destination }}/windmill-ee-arm64-rhel9"
- uses: actions/upload-artifact@v4
with:
name: RHEL9-amd64 build

View File

@@ -62,7 +62,7 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core,kafka
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core
tags: |
${{ steps.meta-ee-public.outputs.tags }}
labels: |

View File

@@ -45,7 +45,7 @@ jobs:
$env:OPENSSL_DIR="${Env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows-static"
mkdir frontend/build && cd backend
New-Item -Path . -Name "windmill-api/openapi-deref.yaml" -ItemType "File" -Force
cargo build --release --features=enterprise,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core,kafka
cargo build --release --features=enterprise,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core
- name: Rename binary with corresponding architecture
run: |

View File

@@ -20,4 +20,4 @@ jobs:
run: |
cd backend
cargo generate-lockfile
- uses: stefanzweifel/git-auto-commit-action@v5
- uses: stefanzweifel/git-auto-commit-action@v4

View File

@@ -1,8 +1,10 @@
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.event_name != 'pull_request' && github.repository ||
IMAGE_NAME:
${{ github.event_name != 'pull_request' && github.repository ||
'windmill-labs/windmill-test' }}
DEV_SHA: ${{ github.event_name != 'pull_request' && 'dev' || format('pr-{0}',
DEV_SHA:
${{ github.event_name != 'pull_request' && 'dev' || format('pr-{0}',
github.event.number) }}
name: Build windmill:main
@@ -138,7 +140,7 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core,kafka
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee:${{ env.DEV_SHA }}
${{ steps.meta-ee-public.outputs.tags }}
@@ -200,7 +202,7 @@ jobs:
platforms: linux/amd64
push: true
build-args: |
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core,kafka
features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core
PYTHON_IMAGE=python:3.12.2-slim-bookworm
tags: |
${{ steps.meta-ee-public-py312.outputs.tags }}

View File

@@ -25,7 +25,7 @@ jobs:
with:
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
- uses: denoland/setup-deno@v2
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- run: cd cli && ./build.sh && cd npm && npm publish

View File

@@ -47,7 +47,7 @@ jobs:
$env:OPENSSL_DIR="${Env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows-static"
mkdir frontend/build && cd backend
New-Item -Path . -Name "windmill-api/openapi-deref.yaml" -ItemType "File" -Force
cargo build --release --features=enterprise,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core,kafka
cargo build --release --features=enterprise,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,tantivy,deno_core
- name: Rename binary with corresponding architecture
run: |

View File

@@ -15,7 +15,7 @@ jobs:
== 'I have read the CLA Document and I hereby sign the CLA') ||
github.event_name == 'pull_request_target'
# Beta Release
uses: cla-assistant/github-action@v2.6.1
uses: cla-assistant/github-action@v2.3.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_PAT }}

3
.gitignore vendored
View File

@@ -6,5 +6,4 @@ frontend/src/routes/test.svelte
CaddyfileRemoteMalo
*.swp
**/.idea/
.direnv
.vscode
.direnv

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"python.analysis.typeCheckingMode": "basic"
}

View File

@@ -1,169 +1,5 @@
# Changelog
## [1.433.0](https://github.com/windmill-labs/windmill/compare/v1.432.0...v1.433.0) (2024-11-29)
### Features
* **cache:** implement flow node caching ([#4808](https://github.com/windmill-labs/windmill/issues/4808)) ([3fbb2bf](https://github.com/windmill-labs/windmill/commit/3fbb2bfc8a191af9a1657824f2d9bff7e57e4b86))
### Bug Fixes
* fix windows build ([0a95b6f](https://github.com/windmill-labs/windmill/commit/0a95b6f9d241c59869c78919352e1bbacf7c1aa7))
## [1.432.0](https://github.com/windmill-labs/windmill/compare/v1.431.1...v1.432.0) (2024-11-29)
### Features
* Parallelize `uv install` ([#4774](https://github.com/windmill-labs/windmill/issues/4774)) ([96371bc](https://github.com/windmill-labs/windmill/commit/96371bc89dfaabdf1e7a9ecd34d13db819985b3f))
## [1.431.1](https://github.com/windmill-labs/windmill/compare/v1.431.0...v1.431.1) (2024-11-28)
### Bug Fixes
* invalid `null` comparison while inserting flow node ([#4815](https://github.com/windmill-labs/windmill/issues/4815)) ([390ee31](https://github.com/windmill-labs/windmill/commit/390ee3113bd203cad89ff7d7cb0cf2da154c40c4))
## [1.431.0](https://github.com/windmill-labs/windmill/compare/v1.430.2...v1.431.0) (2024-11-28)
### Features
* allow forcing dark/light theme on apps ([f69f743](https://github.com/windmill-labs/windmill/commit/f69f743b30f3fcfaf83979f2fe55c2e6e1cf9a03))
* **backend:** implement flow scripts ([#4748](https://github.com/windmill-labs/windmill/issues/4748)) ([e4784e8](https://github.com/windmill-labs/windmill/commit/e4784e89dac9fbfe492fa2d25fcaf373afc3b340))
* **backend:** store flow inner modules into `flow_node` table ([#4778](https://github.com/windmill-labs/windmill/issues/4778)) ([2911775](https://github.com/windmill-labs/windmill/commit/2911775d0a138220cc353aa40e416201130bbd1e))
* expose settable col id for app aggrid tables ([5d0eba2](https://github.com/windmill-labs/windmill/commit/5d0eba273ab7a5264b4ecb7270fb9f13423ccec7))
### Bug Fixes
* add missing export tab on mobile view of flow detail ([#4812](https://github.com/windmill-labs/windmill/issues/4812)) ([a9c31b3](https://github.com/windmill-labs/windmill/commit/a9c31b35f4d50ee399c1dc965e181504cc3bf8aa))
* disable `flow_version_lite` in dedicated workers ([#4800](https://github.com/windmill-labs/windmill/issues/4800)) ([150ca33](https://github.com/windmill-labs/windmill/commit/150ca33f0d022aec55a7c8c0f4516b635ea824d6))
* fix getting logs locally for ee without instance settings ([e81e239](https://github.com/windmill-labs/windmill/commit/e81e239f43fb4302940f0a9d910fafd560084da3))
* fix OAuth being stuck if following a public app login ([5656102](https://github.com/windmill-labs/windmill/commit/5656102b13d63bae5c4c78876d839be73f823450))
* global timeout not set correctly on load ([8f56456](https://github.com/windmill-labs/windmill/commit/8f564567018fa7ff5bfd74aeeb95699fefcf5a63))
* improve default formatters for deno ([2448026](https://github.com/windmill-labs/windmill/commit/24480260bd638fb819ccfb4ace68be844ae3776f))
* improve flow status viwer iteration picker ([ef721f9](https://github.com/windmill-labs/windmill/commit/ef721f9a5f03a06378941d382ce02fa069213ae6))
* invalid `jsonb` comparison while inserting flow node ([#4814](https://github.com/windmill-labs/windmill/issues/4814)) ([77937a4](https://github.com/windmill-labs/windmill/commit/77937a494ada78891cd5aa01e11c2d813fe8d45a))
* **python:** Merge to site-packages packages with same name ([#4793](https://github.com/windmill-labs/windmill/issues/4793)) ([e876ae4](https://github.com/windmill-labs/windmill/commit/e876ae4f42ed0655fa5e1f02e29a203785cfb4cd))
* service logs: aggregation query + killpill on index pull + retention period for logs on s3 ([#4795](https://github.com/windmill-labs/windmill/issues/4795)) ([09fe535](https://github.com/windmill-labs/windmill/commit/09fe535bdca548e0445ffb07d86a1c3cf656d5e5))
## [1.430.2](https://github.com/windmill-labs/windmill/compare/v1.430.1...v1.430.2) (2024-11-25)
### Bug Fixes
* rename `job` workspace as well ([#4785](https://github.com/windmill-labs/windmill/issues/4785)) ([29faefe](https://github.com/windmill-labs/windmill/commit/29faefe856041b29c58dbeef862320a13abcf8a8))
* retry on inserting completed job ([#4784](https://github.com/windmill-labs/windmill/issues/4784)) ([6768e5b](https://github.com/windmill-labs/windmill/commit/6768e5bbbd207fd21da2d63e43138a3a0488c0c4))
* retry on pushing next scheduled job of schedule ([278f593](https://github.com/windmill-labs/windmill/commit/278f5933587102f244047d4d6f54defe6d6066eb))
## [1.430.1](https://github.com/windmill-labs/windmill/compare/v1.430.0...v1.430.1) (2024-11-23)
### Bug Fixes
* expose DISABLE_DENO_LOCK ([495d448](https://github.com/windmill-labs/windmill/commit/495d4487bc2109a85ea3941c104f736b7f79c355))
## [1.430.0](https://github.com/windmill-labs/windmill/compare/v1.429.0...v1.430.0) (2024-11-22)
### Features
* Add a devops role to act as a "readonly admin" ([#4775](https://github.com/windmill-labs/windmill/issues/4775)) ([4facf3c](https://github.com/windmill-labs/windmill/commit/4facf3ca3ee10e07a82668f8594372b9bd6d8b63))
* allow labeled values in app multiselect ([d5da75c](https://github.com/windmill-labs/windmill/commit/d5da75c031b7ac560d4e6d2801937462ddb8eb9d))
* Indexer improvements: s3 backup logic reworked, settings on the frontend ([#4763](https://github.com/windmill-labs/windmill/issues/4763)) ([8f198ba](https://github.com/windmill-labs/windmill/commit/8f198ba68ceaa1f503cddfc246ecbbfc7f90f11d))
* **schedule:** support for extended cron syntax ([#4754](https://github.com/windmill-labs/windmill/issues/4754)) ([8909bea](https://github.com/windmill-labs/windmill/commit/8909bea935088918c5eab5b4508fa7014cfac253))
### Bug Fixes
* allow non already existing resources in audit logs ([b7a9cec](https://github.com/windmill-labs/windmill/commit/b7a9cec289c4e671b8deb3f39d60503135bed06d))
* garbage collect `job` table + delete leaked ones ([#4767](https://github.com/windmill-labs/windmill/issues/4767)) ([c99d360](https://github.com/windmill-labs/windmill/commit/c99d360c3c8ce2b95f086ebbdc1ff235286c46b9))
* infer python list inner type from default if unknown inner ([#4771](https://github.com/windmill-labs/windmill/issues/4771)) ([b49ba59](https://github.com/windmill-labs/windmill/commit/b49ba59da7bf0f419638d3f506c5f67b975e4e85))
## [1.429.0](https://github.com/windmill-labs/windmill/compare/v1.428.1...v1.429.0) (2024-11-20)
### Features
* app editor ctrl nav ([#4757](https://github.com/windmill-labs/windmill/issues/4757)) ([3731886](https://github.com/windmill-labs/windmill/commit/37318861ac356b73f6da652c0ef8b4fc23436e3f))
* svix integration ([#3814](https://github.com/windmill-labs/windmill/issues/3814)) ([68f781e](https://github.com/windmill-labs/windmill/commit/68f781ea6f5f53a3aafbc2c4b5dd71496254c68e))
### Bug Fixes
* add cancellable icons refresh in apps ([2c325ef](https://github.com/windmill-labs/windmill/commit/2c325ef8524e3c74844e566ecf42c245f87a2918))
* **frontend:** pdf viewer fullscreen z-index ([#4762](https://github.com/windmill-labs/windmill/issues/4762)) ([a23cd4f](https://github.com/windmill-labs/windmill/commit/a23cd4f9e7c3e327eea099aade8c3fcd30cc2b87))
## [1.428.1](https://github.com/windmill-labs/windmill/compare/v1.428.0...v1.428.1) (2024-11-20)
### Bug Fixes
* grant all to new job table ([#4758](https://github.com/windmill-labs/windmill/issues/4758)) ([ff7c94c](https://github.com/windmill-labs/windmill/commit/ff7c94c5a7caf94d571a2654f5dc48c494c7bc2e))
## [1.428.0](https://github.com/windmill-labs/windmill/compare/v1.427.0...v1.428.0) (2024-11-19)
### Features
* improve app connection UX [#4687](https://github.com/windmill-labs/windmill/issues/4687) ([2fd80f7](https://github.com/windmill-labs/windmill/commit/2fd80f7cdd21e3938311914ec733d769e13993d6))
* pdf file preview ([#4753](https://github.com/windmill-labs/windmill/issues/4753)) ([b3a7cb0](https://github.com/windmill-labs/windmill/commit/b3a7cb058384b61328e2956f8ccd782ebd7b5900))
### Bug Fixes
* prevent groups to be ill-defined with non writer owners ([f59c0c0](https://github.com/windmill-labs/windmill/commit/f59c0c007675886d41b57647dc7e93b63444e3f9))
## [1.427.0](https://github.com/windmill-labs/windmill/compare/v1.426.1...v1.427.0) (2024-11-19)
### Features
* **backend:** move some static fields out of job tables ([#4689](https://github.com/windmill-labs/windmill/issues/4689)) ([97457a5](https://github.com/windmill-labs/windmill/commit/97457a5679dd6f17b7835d4adfa66ac99c0f5404))
### Bug Fixes
* improve flow status viewer for iterations ([#4744](https://github.com/windmill-labs/windmill/issues/4744)) ([1c39848](https://github.com/windmill-labs/windmill/commit/1c398486e6d5bc5d5bc454b61b41da9acfd50f39))
## [1.426.1](https://github.com/windmill-labs/windmill/compare/v1.426.0...v1.426.1) (2024-11-18)
### Bug Fixes
* playbook files permission mode incompatible with Windows ([#4740](https://github.com/windmill-labs/windmill/issues/4740)) ([4d9ec90](https://github.com/windmill-labs/windmill/commit/4d9ec909d1af7d123fec1a64143615e6cd0bba7e))
## [1.426.0](https://github.com/windmill-labs/windmill/compare/v1.425.1...v1.426.0) (2024-11-18)
### Features
* Add mode (permissions) option to files in ansible ([#4724](https://github.com/windmill-labs/windmill/issues/4724)) ([5e10782](https://github.com/windmill-labs/windmill/commit/5e107827790292d89e51d81138eeef2b5b23a9c2))
* kafka triggers ([#4713](https://github.com/windmill-labs/windmill/issues/4713)) ([88b8ffa](https://github.com/windmill-labs/windmill/commit/88b8ffab907e662ccca612bf01e6a228566522d2))
### Bug Fixes
* do not mount critical alerts modal if user is neither superadmin nor workspace admin ([#4731](https://github.com/windmill-labs/windmill/issues/4731)) ([180809d](https://github.com/windmill-labs/windmill/commit/180809d3466fb62d6692c45cbb012f158f83528f))
## [1.425.1](https://github.com/windmill-labs/windmill/compare/v1.425.0...v1.425.1) (2024-11-16)
### Bug Fixes
* revert bool to text support in pg ([#4727](https://github.com/windmill-labs/windmill/issues/4727)) ([17d8933](https://github.com/windmill-labs/windmill/commit/17d893315bd86942c7895cdb3e9c3ab34977b258))
## [1.425.0](https://github.com/windmill-labs/windmill/compare/v1.424.0...v1.425.0) (2024-11-15)
### Features
* Handle `pip install` by `uv` ([#4517](https://github.com/windmill-labs/windmill/issues/4517)) ([f240d13](https://github.com/windmill-labs/windmill/commit/f240d1322a3c1669dfb69ebda6d05effcca26ae3))
* **monitoring:** workspace critical alerts ([#4684](https://github.com/windmill-labs/windmill/issues/4684)) ([c32038a](https://github.com/windmill-labs/windmill/commit/c32038a76d9d00703d8b865af72f083ac43414e3))
## [1.424.0](https://github.com/windmill-labs/windmill/compare/v1.423.2...v1.424.0) (2024-11-14)

View File

@@ -318,15 +318,19 @@ you to have it being synced automatically everyday.
| ------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| DATABASE_URL | | The Postgres database url. | All |
| WORKER_GROUP | default | The worker group the worker belongs to and get its configuration pulled from | Worker |
| MODE | standalone | The mode if the binary. Possible values: standalone, worker, server, agent | All |
| MODE | standalone | The mode if the binary. Possible values: standalone, worker, server | All |
| METRICS_ADDR | None | (ee only) The socket addr at which to expose Prometheus metrics at the /metrics path. Set to "true" to expose it on port 8001 | All |
| JSON_FMT | false | Output the logs in json format instead of logfmt | All |
| BASE_URL | http://localhost:8000 | The base url that is exposed publicly to access your instance. Is overriden by the instance settings if any. | Server |
| SCRIPT_TOKEN_EXPIRY | 900 | The default duration period of the ephemeral-token generated at the beginning of a script | Worker |
| ZOMBIE_JOB_TIMEOUT | 30 | The timeout after which a job is considered to be zombie if the worker did not send pings about processing the job (every server check for zombie jobs every 30s) | Server |
| RESTART_ZOMBIE_JOBS | true | If true then a zombie job is restarted (in-place with the same uuid and some logs), if false the zombie job is failed | Server |
| SLEEP_QUEUE | 50 | The number of ms to sleep in between the last check for new jobs in the DB. It is multiplied by NUM_WORKERS such that in average, for one worker instance, there is one pull every SLEEP_QUEUE ms. | Worker |
| MAX_LOG_SIZE | 500000 | The maximum number of characters a job can emit (log + result) | Worker |
| DISABLE_NUSER | false | If Nsjail is enabled, disable the nsjail's `clone_newuser` setting | Worker |
| KEEP_JOB_DIR | false | Keep the job directory after the job is done. Useful for debugging. | Worker |
| LICENSE_KEY (EE only) | None | License key checked at startup for the Enterprise Edition of Windmill | Worker |
| S3_CACHE_BUCKET (EE only) | None | The S3 bucket to sync the cache of the workers to | Worker |
| SLACK_SIGNING_SECRET | None | The signing secret of your Slack app. See [Slack documentation](https://api.slack.com/authentication/verifying-requests-from-slack) | Server |
| COOKIE_DOMAIN | None | The domain of the cookie. If not set, the cookie will be set by the browser based on the full origin | Server |
| DENO_PATH | /usr/bin/deno | The path to the deno binary. | Worker |
@@ -334,8 +338,10 @@ you to have it being synced automatically everyday.
| GO_PATH | /usr/bin/go | The path to the go binary. | Worker |
| GOPRIVATE | | The GOPRIVATE env variable to use private go modules | Worker |
| GOPROXY | | The GOPROXY env variable to use | Worker |
| NETRC | | The netrc content to use a private go registry | Worker | | Worker |
| PY_CONCURRENT_DOWNLOADS | 20 | Sets the maximum number of in-flight concurrent python downloads that windmill will perform at any given time. | Worker |
| NETRC | | The netrc content to use a private go registry | Worker |
| PIP_INDEX_URL | None | The index url to pass for pip. | Worker |
| PIP_EXTRA_INDEX_URL | None | The extra index url to pass to pip. | Worker |
| PIP_TRUSTED_HOST | None | The trusted host to pass to pip. | Worker |
| PATH | None | The path environment variable, usually inherited | Worker |
| HOME | None | The home directory to use for Go and Bash , usually inherited | Worker |
| DATABASE_CONNECTIONS | 50 (Server)/3 (Worker) | The max number of connections in the database connection pool | All |
@@ -344,7 +350,6 @@ you to have it being synced automatically everyday.
| QUEUE_LIMIT_WAIT_RESULT | None | The number of max jobs in the queue before rejecting immediately the request in 'run_wait_result' endpoint. Takes precedence on the query arg. If none is specified, there are no limit. | Worker |
| DENO_AUTH_TOKENS | None | Custom DENO_AUTH_TOKENS to pass to worker to allow the use of private modules | Worker |
| DISABLE_RESPONSE_LOGS | false | Disable response logs | Server |
| CREATE_WORKSPACE_REQUIRE_SUPERADMIN | true | If true, only superadmins can create new workspaces | Server |
## Run a local dev setup
See the [./frontend/README_DEV.md](./frontend/README_DEV.md) file for all

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value as \"value: sqlx::types::Json<Box<RawValue>>\" FROM flow_version WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false
]
},
"hash": "00a16dbe1729d530f136279471fa3d89ca7f1a88a48fcf0b1ac07144924c1707"
}

View File

@@ -5,7 +5,7 @@
"columns": [
{
"ordinal": 0,
"name": "bool",
"name": "?column?",
"type_info": "Bool"
}
],

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_flow AS \"raw_flow!: Json<Box<JsonRawValue>>\"\n FROM job WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "raw_flow!: Json<Box<JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
true
]
},
"hash": "0722f461da9edb169c3c73423440eaa3e1b9f2ca3b7033bd7ed978a3b4ddf3fc"
}

View File

@@ -42,9 +42,7 @@
"noop",
"appdependencies",
"deploymentcallback",
"singlescriptflow",
"flowscript",
"flownode"
"singlescriptflow"
]
}
}

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow as \"flow!: sqlx::types::Json<Box<RawValue>>\" FROM flow_node WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "flow!: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true
]
},
"hash": "113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7"
}

View File

@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT lock, code AS \"code!: String\" FROM flow_node WHERE id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "lock",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "code!: String",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true,
true
]
},
"hash": "15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, login_type::text, verified, super_admin, devops, name, company, username, NULL::bool as operator_only FROM password ORDER BY super_admin DESC, devops DESC, email LIMIT $1 OFFSET $2",
"query": "SELECT email, login_type::text, verified, super_admin, name, company, username, NULL::bool as operator_only FROM password ORDER BY super_admin DESC, email LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
@@ -25,26 +25,21 @@
},
{
"ordinal": 4,
"name": "devops",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"ordinal": 5,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 7,
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
},
{
"ordinal": 8,
"ordinal": 7,
"name": "operator_only",
"type_info": "Bool"
}
@@ -60,12 +55,11 @@
null,
false,
false,
false,
true,
true,
true,
null
]
},
"hash": "f07a705df1a988827e099d146f5308b763293a27adf30d02df605317791d8126"
"hash": "1a4d291c2f239f7b50c116594cebb031862e1a18ad9204e02a0194817db26d6a"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n flow_status AS \"flow_status!: Json<Box<RawValue>>\",\n coalesce(job.raw_flow, queue.raw_flow)->'modules'->(flow_status->'step')::int AS \"module: Json<Box<RawValue>>\"\n FROM queue LEFT JOIN job USING(id, workspace_id) WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"query": "SELECT\n flow_status AS \"flow_status!: Json<Box<RawValue>>\",\n raw_flow->'modules'->(flow_status->'step')::int AS \"module: Json<Box<RawValue>>\"\n FROM queue WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
@@ -25,5 +25,5 @@
null
]
},
"hash": "b3a9ab85a78edf292ddb0af33f7435bbcc84f63c9079e29d84043f258eba208e"
"hash": "1e7ce0c140410ae799f9c0c5772e4be4506bfd238c88f1b1c3ddf39b29071446"
}

View File

@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM kafka_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Bool",
"Text"
]
},
"nullable": [
null
]
},
"hash": "2139f1fb1877294bbf55d786000c5c32f582a3911efcf88e437aa90d7d5a49b5"
}

View File

@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_code, raw_lock, raw_flow AS \"raw_flow: Json<Box<JsonRawValue>>\"\n FROM queue WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "raw_code",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "raw_lock",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "raw_flow: Json<Box<JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
true,
true,
true
]
},
"hash": "217a5291438d23597b2c7f05d2c481f406364d56a129089a268f6423c548bca6"
}

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM job_logs WHERE job_id = ANY($1) RETURNING log_file_index",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "log_file_index",
"type_info": "TextArray"
}
],
"parameters": {
"Left": [
"UuidArray"
]
},
"nullable": [
true
]
},
"hash": "288e99211bbd45a337fc9b79c43c5139ee535e23c8b3362c52eef49998349f15"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only FROM password WHERE email = $1",
"query": "SELECT email, login_type::TEXT, super_admin, verified, name, company, username, NULL::bool as operator_only FROM password WHERE email = $1",
"describe": {
"columns": [
{
@@ -20,31 +20,26 @@
},
{
"ordinal": 3,
"name": "devops",
"type_info": "Bool"
},
{
"ordinal": 4,
"name": "verified",
"type_info": "Bool"
},
{
"ordinal": 5,
"ordinal": 4,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 6,
"ordinal": 5,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 7,
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
},
{
"ordinal": 8,
"ordinal": 7,
"name": "operator_only",
"type_info": "Bool"
}
@@ -59,12 +54,11 @@
null,
false,
false,
false,
true,
true,
true,
null
]
},
"hash": "df5b933f81ca7e3bbb3fb522baedf749fa3bbbf2c0e43d5d4ea148b5bc990067"
"hash": "2c14d3a88193f16ad3b8cd590749cb5537995f2499f6cb8f0f316fb62902d542"
}

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT devops FROM password WHERE email = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "devops",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
},
"hash": "2c615128e28a3fb1ecb4b7a40f45801b58221898175c5d00dbdaaa085f769ac8"
}

View File

@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO flow_version_lite (id, value) VALUES ($1, $2)\n ON CONFLICT (id) DO UPDATE SET value = EXCLUDED.value",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8",
"Jsonb"
]
},
"nullable": []
},
"hash": "2de4ac337d25cc483829818393fa3254556c0307bb6bb596613b1ce2ee7ec4cb"
}

View File

@@ -1,6 +1,6 @@
{
"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 authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC, devops DESC\n LIMIT $1 OFFSET $2",
"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 authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, name, company, username\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC\n LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
@@ -30,21 +30,16 @@
},
{
"ordinal": 5,
"name": "devops",
"type_info": "Bool"
},
{
"ordinal": 6,
"name": "name",
"type_info": "Varchar"
},
{
"ordinal": 7,
"ordinal": 6,
"name": "company",
"type_info": "Varchar"
},
{
"ordinal": 8,
"ordinal": 7,
"name": "username",
"type_info": "Varchar"
}
@@ -61,11 +56,10 @@
null,
false,
false,
false,
true,
true,
true
]
},
"hash": "3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1"
"hash": "2eec077cc9e27d7ccd160cbaac118c321c422705f79e69550bb60f377083bcef"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_flow->'failure_module' != 'null'::jsonb FROM job WHERE id = $1",
"query": "SELECT raw_flow->'failure_module' != 'null'::jsonb\n FROM completed_job\n WHERE id = $1",
"describe": {
"columns": [
{
@@ -18,5 +18,5 @@
null
]
},
"hash": "e1923bc755bd6b8cc871ae9381a97d3c63a0fce3dd57c93f48a2136f7395fa3a"
"hash": "31dd23f6768052e486668172e15eba1a3f9b6a8e5678a7ee8e5456ff4405d6f9"
}

View File

@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM kafka_trigger WHERE workspace_id = $1 AND path = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": []
},
"hash": "3997dcf2c11817e59bf50fd896381d870b847a8ba07e6197212fdf85ec901b09"
}

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow AS \"flow!: Json<Box<JsonRawValue>>\" FROM flow_node WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "flow!: Json<Box<JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true
]
},
"hash": "3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c"
}

View File

@@ -1,16 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET enabled = FALSE, error = $1, server_id = NULL, last_server_ping = NULL WHERE workspace_id = $2 AND path = $3",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "3e64c894c89ef82c4527180b82c4e82c1b7060ba0ca288dc6a7c7afcd76212e8"
}

View File

@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE password SET devops = $1 WHERE email = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Bool",
"Text"
]
},
"nullable": []
},
"hash": "411788111afccd826ce78b266153600939c65c75be8894322b90d9da18dcb824"
}

View File

@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE job SET workspace_id = $1 WHERE workspace_id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Text"
]
},
"nullable": []
},
"hash": "43fcdf5243e17bfbdcd21f09feee6e104b40f4b937914f56f01c299cddfc17e9"
}

View File

@@ -145,11 +145,6 @@
},
{
"ordinal": 28,
"name": "cron_version",
"type_info": "Text"
},
{
"ordinal": 29,
"name": "jobs",
"type_info": "JsonArray"
}
@@ -190,7 +185,6 @@
true,
true,
true,
true,
null
]
},

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM job WHERE id = ANY($1)",
"query": "DELETE FROM job_logs WHERE job_id = ANY($1)",
"describe": {
"columns": [],
"parameters": {
@@ -10,5 +10,5 @@
},
"nullable": []
},
"hash": "803b9c1373541cf52f416cde9e9e99ab79072e21dfaafb498aac25a059bd2f30"
"hash": "467c563cdc81dd57a01735a9f535d1096bdfd6c539d8c31462f8f2bd711ab0fa"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow_version.value \n FROM flow \n LEFT JOIN flow_version \n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 AND flow.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "4a764cdcb847b71183425a7a0e863708ef7fe2c88b28d0667988a47b9e995c0e"
}

View File

@@ -1,19 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO job (id, workspace_id, raw_code, raw_lock, raw_flow, tag)\n VALUES ($1, $2, $3, $4, $5, $6)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Varchar",
"Text",
"Text",
"Jsonb",
"Varchar"
]
},
"nullable": []
},
"hash": "4b923c94f6adcc7a76e8073de5e46b116dba3211487c8408ce2777aafdf94a44"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT created_by, CONCAT(coalesce(queue.logs, ''), coalesce(job_logs.logs, '')) as logs, coalesce(job_logs.log_offset, 0) as 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": [
{
@@ -33,9 +33,9 @@
"nullable": [
false,
null,
null,
false,
true
]
},
"hash": "b2c30137b3b64f8c3f6aea062e8687e119599641beee0a0d6c89c5d90e82d0db"
"hash": "57111a97ff906fd79ecd8a571212cc4fea9cb9c16fe950f082ad5469bfeefc82"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET kafka_resource_path = $1, group_id = $2, topics = $3, script_path = $4, path = $5, is_flow = $6, edited_by = $7, email = $8, edited_at = now(), server_id = NULL, last_server_ping = NULL, error = NULL\n WHERE workspace_id = $9 AND path = $10",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"VarcharArray",
"Varchar",
"Varchar",
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "5962733746c81480abe9ab3a6ccf5664130ae7500279055c08db42d67b2822f6"
}

View File

@@ -1,27 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH existing AS (\n SELECT id FROM flow_node\n WHERE hash = $1 AND path = $2 AND workspace_id = $3 AND code = $4 AND lock = $5 AND (flow IS NOT DISTINCT FROM $6)\n LIMIT 1\n ),\n inserted AS (\n INSERT INTO flow_node (hash, path, workspace_id, code, lock, flow)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT DO NOTHING\n RETURNING id\n )\n SELECT id FROM existing\n UNION ALL\n SELECT id FROM inserted\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8",
"Text",
"Text",
"Text",
"Text",
"Jsonb"
]
},
"nullable": [
null
]
},
"hash": "5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT coalesce(flow_version_lite.value, flow_version.value) as \"value!: sqlx::types::Json<Box<RawValue>>\" FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n LEFT JOIN flow_version_lite \n ON flow_version_lite.id = flow_version.id\n WHERE flow.path = $1 AND flow.workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value!: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "625c400bd81369a8142b8c7fa67b2be02f0f945e587c90d7e0f23706bf6e9a31"
}

View File

@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "WITH uuid_table as (\n select gen_random_uuid() as uuid from generate_series(1, $5)\n )\n INSERT INTO job\n (id, workspace_id, raw_code, raw_lock, raw_flow)\n (SELECT uuid, $1, $2, $3, $4 FROM uuid_table)\n RETURNING id",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text",
"Jsonb",
"Int4"
]
},
"nullable": [
false
]
},
"hash": "63e54fe57ec439b68eead00a02209f81076c5317d590e1441b557555b4d7ad96"
}

View File

@@ -5,7 +5,7 @@
"columns": [
{
"ordinal": 0,
"name": "bool",
"name": "?column?",
"type_info": "Bool"
}
],

View File

@@ -1,25 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET last_server_ping = now(), error = $1 WHERE workspace_id = $2 AND path = $3 AND server_id = $4 AND enabled IS TRUE RETURNING 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Text",
"Text",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "6e70ebf078ac04a2933d2f83791973e8fc108d9f32be8a8501391052d76e191e"
}

View File

@@ -1,26 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET enabled = $1, email = $2, edited_by = $3, edited_at = now(), server_id = NULL, last_server_ping = NULL, error = NULL\n WHERE path = $4 AND workspace_id = $5 RETURNING 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bool",
"Varchar",
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "6eb076afcf11dba0dfe35ee108c64814f95dbe5376f0539195d24a8ca96ca3e2"
}

View File

@@ -26,9 +26,7 @@
"noop",
"appdependencies",
"deploymentcallback",
"singlescriptflow",
"flowscript",
"flownode"
"singlescriptflow"
]
}
}

View File

@@ -1,15 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE flow_node SET workspace_id = $1 WHERE workspace_id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Text"
]
},
"nullable": []
},
"hash": "79992fd5650a99a4391e7c9e590d9ee7969f98975406fa13118d2b7e808958cf"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM log_file WHERE log_ts <= now() - ($1::bigint::text || ' s')::interval ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": []
},
"hash": "845120388af12c2b2f57fedf95c8cce4a406b74c9a8c8590a3bae323d59d046a"
}

View File

@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT lock, code AS \"code!: String\" FROM flow_node WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "lock",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "code!: String",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true,
true
]
},
"hash": "8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT coalesce(flow_version_lite.value, flow_version.value) as \"value!: sqlx::types::Json<Box<RawValue>>\" FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n LEFT JOIN flow_version_lite \n ON flow_version_lite.id = flow_version.id\n WHERE flow.path = $1 AND flow.workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value!: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "94a38b83d59f8c010bd96852bf57163476791448201bdd22a9e463a4116b9582"
}

View File

@@ -1,28 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM log_file WHERE log_ts <= now() - ($1::bigint::text || ' s')::interval RETURNING file_path, hostname",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "file_path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "hostname",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false,
false
]
},
"hash": "94da1e7feb4f58cc7ebe99752736f956d47810a94cb052fdcffb5cfe440f8033"
}

View File

@@ -26,9 +26,7 @@
"noop",
"appdependencies",
"deploymentcallback",
"singlescriptflow",
"flowscript",
"flownode"
"singlescriptflow"
]
}
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT owners FROM folder WHERE name = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "owners",
"type_info": "VarcharArray"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "a37e9efe197609226af13a7e4f940cadce758f4d3c54f3a6b26756a3df38bab0"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "WITH uuid_table as (\n select unnest($11::uuid[]) as uuid\n )\n INSERT INTO queue \n (id, script_hash, script_path, job_kind, language, args, tag, created_by, permissioned_as, email, scheduled_for, workspace_id, concurrent_limit, concurrency_time_window_s, timeout, flow_status)\n (SELECT uuid, $1, $2, $3, $4, ('{ \"uuid\": \"' || uuid || '\" }')::jsonb, $5, $6, $7, $8, $9, $10, $12, $13, $14, $15 FROM uuid_table) \n RETURNING id",
"query": "WITH uuid_table as (\n select gen_random_uuid() as uuid from generate_series(1, $11)\n )\n INSERT INTO queue \n (id, script_hash, script_path, job_kind, language, args, tag, created_by, permissioned_as, email, scheduled_for, workspace_id, concurrent_limit, concurrency_time_window_s, timeout, raw_code, raw_lock, raw_flow, flow_status)\n (SELECT uuid, $1, $2, $3, $4, ('{ \"uuid\": \"' || uuid || '\" }')::jsonb, $5, $6, $7, $8, $9, $10, $12, $13, $14, $15, $16, $17, $18 FROM uuid_table) \n RETURNING id",
"describe": {
"columns": [
{
@@ -32,9 +32,7 @@
"noop",
"appdependencies",
"deploymentcallback",
"singlescriptflow",
"flowscript",
"flownode"
"singlescriptflow"
]
}
}
@@ -71,10 +69,13 @@
"Varchar",
"Timestamptz",
"Varchar",
"UuidArray",
"Int4",
"Int4",
"Int4",
"Int4",
"Text",
"Text",
"Jsonb",
"Jsonb"
]
},
@@ -82,5 +83,5 @@
false
]
},
"hash": "337f31c2172194cd594042c561998a03f751b246c40daf056fced0fd91f6dd73"
"hash": "a69ba7471d1a5faa145bebbd17d43e6dbe02e9e92ebbc31a50c99c3a04719284"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_flow->'failure_module' != 'null'::jsonb FROM completed_job WHERE id = $1",
"query": "SELECT raw_flow->'failure_module' != 'null'::jsonb\n FROM queue\n WHERE id = $1",
"describe": {
"columns": [
{
@@ -18,5 +18,5 @@
null
]
},
"hash": "45950064cce9f53f73a01ddcd6911ec677297009b71041d39019c4700a571c0f"
"hash": "aa6907b7266ee437dfbd77a9bf6c047fda88f3e72a0d10323a5e4020cf857c42"
}

View File

@@ -1,27 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH existing AS (\n SELECT id FROM flow_node\n WHERE hash = $1 AND path = $2 AND workspace_id = $3 AND code = $4 AND lock = $5 AND flow = $6\n LIMIT 1\n ),\n inserted AS (\n INSERT INTO flow_node (hash, path, workspace_id, code, lock, flow)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT DO NOTHING\n RETURNING id\n )\n SELECT id FROM existing\n UNION ALL\n SELECT id FROM inserted\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8",
"Text",
"Text",
"Text",
"Text",
"Jsonb"
]
},
"nullable": [
null
]
},
"hash": "aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow_version.value AS \"value: sqlx::types::Json<Box<RawValue>>\" FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 AND flow.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "ae543dfa106fa6ad4e9bf45cda1110d4702a80f455c63af6fcbd7cf45bbc4f7a"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow_version.value AS \"value!: sqlx::types::Json<Box<sqlx::types::JsonRawValue>>\" \n FROM flow \n LEFT JOIN flow_version \n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 AND flow.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value!: sqlx::types::Json<Box<sqlx::types::JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "bbce3e1eae78c48409d4204cd6cb3b9db088f6e51bea5e74a494c4e9f4c3b78e"
}

View File

@@ -1,34 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT lock AS \"lock: String\", code AS \"code: String\", flow::text AS \"flow: Box<str>\" FROM flow_node WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "lock: String",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "code: String",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "flow: Box<str>",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true,
true,
null
]
},
"hash": "c57ed2d91de46d7de88e20b94b7afbafb622528864f2b23c8b7278bd506d967f"
}

View File

@@ -1,34 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT \n EXISTS(SELECT 1 FROM websocket_trigger WHERE workspace_id = $1) as \"websocket_used!\", \n EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1) as \"http_routes_used!\",\n EXISTS(SELECT 1 FROM kafka_trigger WHERE workspace_id = $1) as \"kafka_used!\"",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "websocket_used!",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "http_routes_used!",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "kafka_used!",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null,
null,
null
]
},
"hash": "cc8a71abdeccf0787695af32aa21fe73aba65cfdc8329c02b4d257de4d2d168a"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO completed_job AS cj\n ( workspace_id\n , id\n , parent_job\n , created_by\n , created_at\n , started_at\n , duration_ms\n , success\n , script_hash\n , script_path\n , args\n , result\n , raw_code\n , raw_lock\n , canceled\n , canceled_by\n , canceled_reason\n , job_kind\n , schedule_path\n , permissioned_as\n , flow_status\n , raw_flow\n , is_flow_step\n , is_skipped\n , language\n , email\n , visible_to_owner\n , mem_peak\n , tag\n , priority\n )\n VALUES ($1, $2, $3, $4, $5, COALESCE($6, now()), COALESCE($30::bigint, (EXTRACT('epoch' FROM (now())) - EXTRACT('epoch' FROM (COALESCE($6, now()))))*1000), $7, $8, $9,$10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29)\n ON CONFLICT (id) DO UPDATE SET success = $7, result = $11 RETURNING duration_ms",
"query": "INSERT INTO completed_job AS cj\n ( workspace_id\n , id\n , parent_job\n , created_by\n , created_at\n , started_at\n , duration_ms\n , success\n , script_hash\n , script_path\n , args\n , result\n , raw_code\n , raw_lock\n , canceled\n , canceled_by\n , canceled_reason\n , job_kind\n , schedule_path\n , permissioned_as\n , flow_status\n , raw_flow\n , is_flow_step\n , is_skipped\n , language\n , email\n , visible_to_owner\n , mem_peak\n , tag\n , priority\n )\n VALUES ($1, $2, $3, $4, $5, COALESCE($6, now()), (EXTRACT('epoch' FROM (now())) - EXTRACT('epoch' FROM (COALESCE($6, now()))))*1000, $7, $8, $9,$10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29)\n ON CONFLICT (id) DO UPDATE SET success = $7, result = $11 RETURNING duration_ms",
"describe": {
"columns": [
{
@@ -46,9 +46,7 @@
"noop",
"appdependencies",
"deploymentcallback",
"singlescriptflow",
"flowscript",
"flownode"
"singlescriptflow"
]
}
}
@@ -89,13 +87,12 @@
"Bool",
"Int4",
"Varchar",
"Int2",
"Int8"
"Int2"
]
},
"nullable": [
false
]
},
"hash": "f9fc0084fe086ef80005bb64a8bb6b493e53583017c18e2ab44f44125c52d548"
"hash": "d5a8614286c170e0d175903cd1b53ff66b37ed8110a0b67aedb9f25e6a7383e1"
}

View File

@@ -1,24 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE kafka_trigger SET server_id = $1, last_server_ping = now() WHERE enabled IS TRUE AND workspace_id = $2 AND path = $3 AND (server_id IS NULL OR last_server_ping IS NULL OR last_server_ping < now() - interval '15 seconds') RETURNING true",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "bool",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Varchar",
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "d6615719bf8db4b333ed55c9a3c160ad1962668fc3305d8e80ae91ef73614a80"
}

View File

@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_code, raw_lock, raw_flow AS \"raw_flow: Json<Box<RawValue>>\"\n FROM job WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "raw_code",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "raw_lock",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "raw_flow: Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
true,
true,
true
]
},
"hash": "da861c06f6448f68069ba3be9b677641c5c6b2c1e4960c74db27dbaffcbd4c40"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM websocket_trigger WHERE workspace_id = $1) as \"websocket_used!\", EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1) as \"http_routes_used!\"",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "websocket_used!",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "http_routes_used!",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null,
null
]
},
"hash": "db24f1f6ef1e26b7de7926bd3f32d1fa673c4970c25ff9ad98f0fdf199801b53"
}

View File

@@ -1,27 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH existing AS (\n SELECT id FROM flow_node\n WHERE hash = $1 AND path = $2 AND workspace_id = $3\n AND (code IS NOT DISTINCT FROM $4)\n AND (lock IS NOT DISTINCT FROM $5)\n AND (flow IS NOT DISTINCT FROM $6)\n LIMIT 1\n ),\n inserted AS (\n INSERT INTO flow_node (hash, path, workspace_id, code, lock, flow)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT DO NOTHING\n RETURNING id\n )\n SELECT id FROM existing\n UNION ALL\n SELECT id FROM inserted\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8",
"Text",
"Text",
"Text",
"Text",
"Jsonb"
]
},
"nullable": [
null
]
},
"hash": "dc32e9e81eab9cda88875020acc414271b96d251bcf54c153c45370d917eea9d"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT flow_version.value as \"value!: sqlx::types::Json<Box<RawValue>>\" FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 AND flow.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value!: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "dc44783a555d41c9df4cd303af686e43bbf89add915bfb09d94e25e8517d65ff"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n hostname,\n mode::text,\n worker_group,\n log_ts,\n file_path,\n ok_lines,\n err_lines,\n json_fmt\n FROM log_file\n WHERE log_ts > NOW() - make_interval(secs => $1)\n ORDER BY log_ts ASC LIMIT $2",
"query": "SELECT\n hostname,\n mode::text,\n worker_group,\n log_ts,\n file_path,\n ok_lines,\n err_lines,\n json_fmt\n FROM log_file\n ORDER BY log_ts ASC LIMIT $1",
"describe": {
"columns": [
{
@@ -46,7 +46,6 @@
],
"parameters": {
"Left": [
"Float8",
"Int8"
]
},
@@ -61,5 +60,5 @@
true
]
},
"hash": "8d207cc9ed101ff116b617d25a94633c1531170ded1fdf09114718b941f5e1db"
"hash": "dd967c5983fa0ff05e2b320ad0e0b5a152784826cb8fb4381c1ffe228cb7feb6"
}

View File

@@ -1,23 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM kafka_trigger WHERE path = $1 AND workspace_id = $2)",
"query": "SELECT raw_flow->'modules'->($1)::text->'value'->>'type' = 'flow' FROM queue WHERE id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"name": "?column?",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
"Uuid"
]
},
"nullable": [
null
]
},
"hash": "6d418b5cd7a4df54cfe3ec06e2a957c87f2307a218115ca749ea0e71eca2002e"
"hash": "de1abe57b6aa61155f747a3bcb98359f70eade6654b5a884915f07f3ef3fe15e"
}

View File

@@ -1,72 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT lock AS \"lock: String\", content AS \"code!: String\",\n language AS \"language: Option<ScriptLang>\", envs AS \"envs: Vec<String>\", codebase AS \"codebase: String\" FROM script WHERE hash = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "lock: String",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "code!: String",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "language: Option<ScriptLang>",
"type_info": {
"Custom": {
"name": "script_lang",
"kind": {
"Enum": [
"python3",
"deno",
"go",
"bash",
"postgresql",
"nativets",
"bun",
"mysql",
"bigquery",
"snowflake",
"graphql",
"powershell",
"mssql",
"php",
"bunnative",
"rust",
"ansible"
]
}
}
}
},
{
"ordinal": 3,
"name": "envs: Vec<String>",
"type_info": "VarcharArray"
},
{
"ordinal": 4,
"name": "codebase: String",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int8",
"Text"
]
},
"nullable": [
true,
false,
false,
true,
true
]
},
"hash": "df52a71d59eb84a2b08133d25f0a8bba7f2b56625fdb7a7c0e10b51377eeb1d4"
}

View File

@@ -1,20 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value FROM global_settings WHERE name = 'indexer_settings'",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": []
},
"nullable": [
false
]
},
"hash": "e2d8028163c014f4cdff0d85550371fe28ec8233fa80413324ce0194ce909e3c"
}

View File

@@ -1,16 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE flow_node SET path = REGEXP_REPLACE(path,'u/' || $2 || '/(.*)','u/' || $1 || '/\\1') WHERE path LIKE ('u/' || $2 || '/%') AND workspace_id = $3",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "ed12d54e9cdc18672bbb34d2500adc18b72323e06a1f32e7a1a7589649888927"
}

View File

@@ -1,23 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_flow AS \"raw_flow!: Json<Box<sqlx::types::JsonRawValue>>\"\n FROM job WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "raw_flow!: Json<Box<sqlx::types::JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
true
]
},
"hash": "f24303a2386575a750a48a21d1b6cdecd6e64a0415c60ad1495f100c5d85bbe1"
}

View File

@@ -1,35 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT raw_code, raw_lock, raw_flow AS \"raw_flow: Json<Box<JsonRawValue>>\"\n FROM job WHERE id = $1 AND workspace_id = $2 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "raw_code",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "raw_lock",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "raw_flow: Json<Box<JsonRawValue>>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
true,
true,
true
]
},
"hash": "fb1a32318b35ec5c8129eb3660b79eb5e6d1e01fcf01cc05d3c7ddf47295c2f5"
}

893
backend/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.433.0"
version = "1.424.0"
authors.workspace = true
edition.workspace = true
@@ -29,7 +29,7 @@ members = [
]
[workspace.package]
version = "1.433.0"
version = "1.424.0"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
@@ -62,7 +62,6 @@ jemalloc = ["windmill-common/jemalloc", "dep:tikv-jemallocator", "dep:tikv-jemal
tantivy = ["dep:windmill-indexer", "windmill-api/tantivy"]
sqlx = ["windmill-worker/sqlx"]
deno_core = ["windmill-worker/deno_core", "dep:deno_core"]
kafka = ["windmill-api/kafka"]
[dependencies]
anyhow.workspace = true
@@ -83,6 +82,7 @@ chrono.workspace = true
git-version.workspace = true
base64.workspace = true
sha2.workspace = true
rsmq_async.workspace = true
url.workspace = true
lazy_static.workspace = true
once_cell.workspace = true
@@ -139,12 +139,12 @@ headers = "^0"
hyper = { version = "^1", features = ["full"] }
tokio = { version = "^1", features = ["full", "tracing"] }
tower = "^0"
tower-http = { version = "^0.6", features = ["trace", "cors"] }
tower-http = { version = "^0.5", features = ["trace", "cors"] }
tower-cookies = "^0.10"
serde = "^1"
serde_json = { version = "^1", features = ["preserve_order", "raw_value"] }
uuid = { version = "^1", features = ["serde", "v4"] }
thiserror = "^2"
thiserror = "^1"
anyhow = "^1"
chrono = { version = "0.4.35", features = ["serde"] }
chrono-tz = "^0"
@@ -230,6 +230,7 @@ async-stripe = { version = "0.39.1", features = [
] }
async_zip = { version = "0.0.11", features = ["full"] }
once_cell = "1.17.1"
rsmq_async = { version = "5.1.5" }
gosyn = "0.2.6"
bytes = "1.4.0"
gethostname = "0.4.3"
@@ -265,7 +266,6 @@ tokio-native-tls = "^0"
openssl = "=0.10"
mail-parser = "^0"
matchit = "=0.7.3"
rdkafka = { version = "0.36.2", features = ["cmake-build", "ssl-vendored"] }
datafusion = "39.0.0"
object_store = { version = "0.10.0", features = ["aws", "azure"] }
@@ -287,8 +287,6 @@ triomphe = "^0"
tantivy = "0.22.0"
backon = "1.3.0"
# Macro-related
proc-macro2 = "1.0"
pulldown-cmark = "0.9"
@@ -297,4 +295,4 @@ syn = { version = "2.0.74", features = ["full"] }
quote = "1.0.36"
regex-lite = "0.1.6"
yaml-rust = "0.4.5"
tokio-tungstenite = { version = "0.24.0", features = ["native-tls"] }
tokio-tungstenite = { version = "0.24.0", features = ["native-tls"] }

View File

@@ -1 +1 @@
3fa1a6bc51f39e65d441afed31825347b24a521e
51dcbf93b0d127af9f33fa346cc63fcd2475d4fa

View File

@@ -1,2 +0,0 @@
-- Add down migration script here
DROP TABLE kafka_trigger;

View File

@@ -1,69 +0,0 @@
-- Add up migration script here
-- Add up migration script here
CREATE TABLE kafka_trigger (
path VARCHAR(255) NOT NULL,
kafka_resource_path VARCHAR(255) NOT NULL,
topics VARCHAR(255)[] NOT NULL,
group_id VARCHAR(255) NOT NULL,
script_path VARCHAR(255) NOT NULL,
is_flow BOOLEAN NOT NULL,
workspace_id VARCHAR(50) NOT NULL,
edited_by VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
edited_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
extra_perms JSONB NOT NULL DEFAULT '{}',
server_id VARCHAR(50) NULL,
last_server_ping TIMESTAMPTZ NULL,
error TEXT NULL,
enabled BOOLEAN NOT NULL,
PRIMARY KEY (path, workspace_id)
);
GRANT ALL ON kafka_trigger TO windmill_user;
GRANT ALL ON kafka_trigger TO windmill_admin;
ALTER TABLE kafka_trigger ENABLE ROW LEVEL SECURITY;
CREATE POLICY admin_policy ON kafka_trigger FOR ALL TO windmill_admin USING (true);
CREATE POLICY see_folder_extra_perms_user_select ON kafka_trigger FOR SELECT TO windmill_user
USING (SPLIT_PART(kafka_trigger.path, '/', 1) = 'f' AND SPLIT_PART(kafka_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_read'), ',')::text[]));
CREATE POLICY see_folder_extra_perms_user_insert ON kafka_trigger FOR INSERT TO windmill_user
WITH CHECK (SPLIT_PART(kafka_trigger.path, '/', 1) = 'f' AND SPLIT_PART(kafka_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_write'), ',')::text[]));
CREATE POLICY see_folder_extra_perms_user_update ON kafka_trigger FOR UPDATE TO windmill_user
USING (SPLIT_PART(kafka_trigger.path, '/', 1) = 'f' AND SPLIT_PART(kafka_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_write'), ',')::text[]));
CREATE POLICY see_folder_extra_perms_user_delete ON kafka_trigger FOR DELETE TO windmill_user
USING (SPLIT_PART(kafka_trigger.path, '/', 1) = 'f' AND SPLIT_PART(kafka_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_write'), ',')::text[]));
CREATE POLICY see_own ON kafka_trigger FOR ALL TO windmill_user
USING (SPLIT_PART(kafka_trigger.path, '/', 1) = 'u' AND SPLIT_PART(kafka_trigger.path, '/', 2) = current_setting('session.user'));
CREATE POLICY see_member ON kafka_trigger FOR ALL TO windmill_user
USING (SPLIT_PART(kafka_trigger.path, '/', 1) = 'g' AND SPLIT_PART(kafka_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.groups'), ',')::text[]));
CREATE POLICY see_extra_perms_user_select ON kafka_trigger FOR SELECT TO windmill_user
USING (extra_perms ? CONCAT('u/', current_setting('session.user')));
CREATE POLICY see_extra_perms_user_insert ON kafka_trigger FOR INSERT TO windmill_user
WITH CHECK ((extra_perms ->> CONCAT('u/', current_setting('session.user')))::boolean);
CREATE POLICY see_extra_perms_user_update ON kafka_trigger FOR UPDATE TO windmill_user
USING ((extra_perms ->> CONCAT('u/', current_setting('session.user')))::boolean);
CREATE POLICY see_extra_perms_user_delete ON kafka_trigger FOR DELETE TO windmill_user
USING ((extra_perms ->> CONCAT('u/', current_setting('session.user')))::boolean);
CREATE POLICY see_extra_perms_groups_select ON kafka_trigger FOR SELECT TO windmill_user
USING (extra_perms ?| regexp_split_to_array(current_setting('session.pgroups'), ',')::text[]);
CREATE POLICY see_extra_perms_groups_insert ON kafka_trigger FOR INSERT TO windmill_user
WITH CHECK (exists(
SELECT key, value FROM jsonb_each_text(extra_perms)
WHERE SPLIT_PART(key, '/', 1) = 'g' AND key = ANY(regexp_split_to_array(current_setting('session.pgroups'), ',')::text[])
AND value::boolean));
CREATE POLICY see_extra_perms_groups_update ON kafka_trigger FOR UPDATE TO windmill_user
USING (exists(
SELECT key, value FROM jsonb_each_text(extra_perms)
WHERE SPLIT_PART(key, '/', 1) = 'g' AND key = ANY(regexp_split_to_array(current_setting('session.pgroups'), ',')::text[])
AND value::boolean));
CREATE POLICY see_extra_perms_groups_delete ON kafka_trigger FOR DELETE TO windmill_user
USING (exists(
SELECT key, value FROM jsonb_each_text(extra_perms)
WHERE SPLIT_PART(key, '/', 1) = 'g' AND key = ANY(regexp_split_to_array(current_setting('session.pgroups'), ',')::text[])
AND value::boolean));

View File

@@ -1 +0,0 @@
ALTER TABLE schedule DROP COLUMN cron_version;

View File

@@ -1,2 +0,0 @@
-- Add existing rows to have 'v1' as the cron_version
ALTER TABLE schedule ADD COLUMN cron_version TEXT DEFAULT 'v1';

View File

@@ -1,4 +0,0 @@
-- Add down migration script here
DROP TABLE job CASCADE;
DROP VIEW queue_view CASCADE;
DROP VIEW completed_job_view CASCADE;

View File

@@ -1,38 +0,0 @@
-- Add up migration script here
CREATE TABLE job (
id UUID PRIMARY KEY,
raw_code TEXT,
raw_lock TEXT,
raw_flow jsonb NULL,
tag VARCHAR(50),
workspace_id VARCHAR(50)
);
-- Create `queue_view` and `completed_job_view` views.
DO $$
DECLARE
t TEXT;
BEGIN
FOR t IN VALUES ('queue'), ('completed_job') LOOP
EXECUTE format(
'CREATE OR REPLACE VIEW '||t||'_view AS
SELECT %s, job_logs.log_offset, job_logs.log_file_index FROM '||t||'
LEFT JOIN job ON '||t||'.id = job.id AND '||t||'.workspace_id = job.workspace_id
LEFT JOIN job_logs ON '||t||'.id = job_logs.job_id', (
SELECT string_agg(
CASE
WHEN column_name = 'logs' THEN -- Concatenate logs from base and job_logs.
'concat(coalesce('||t||'.logs, ''''), coalesce(job_logs.logs, '''')) as logs'
WHEN column_name IN ('raw_code', 'raw_lock', 'raw_flow') THEN -- Coalesce column from base and job.
format('coalesce('||t||'.%s, job.%s) as %s', column_name, column_name, column_name)
ELSE
format('%s.%s', t, column_name)
END,
', '
)
FROM information_schema.columns
WHERE table_name = t
)
);
END LOOP;
END $$;

View File

@@ -1 +0,0 @@
-- Add down migration script here

View File

@@ -1,3 +0,0 @@
-- Add up migration script here
GRANT ALL ON job TO windmill_user;
GRANT ALL ON job TO windmill_admin;

View File

@@ -1,2 +0,0 @@
-- Add down migration script here
-- Nothing to do here

View File

@@ -1,4 +0,0 @@
-- Add up migration script here
DELETE FROM job
WHERE NOT EXISTS (SELECT 1 FROM completed_job WHERE completed_job.id = job.id)
AND NOT EXISTS (SELECT 1 FROM queue WHERE queue.id = job.id);

View File

@@ -1,2 +0,0 @@
-- Add down migration script here
ALTER TABLE password DROP COLUMN devops;

View File

@@ -1,2 +0,0 @@
-- Add up migration script here
ALTER TABLE password ADD COLUMN devops BOOLEAN NOT NULL DEFAULT false;

View File

@@ -1,4 +0,0 @@
-- Add down migration script here
DROP TABLE IF EXISTS flow_version_lite;
DROP TABLE IF EXISTS flow_node;
DROP INDEX IF EXISTS flow_node_hash;

View File

@@ -1,29 +0,0 @@
-- Add up migration script here
ALTER TYPE JOB_KIND ADD VALUE IF NOT EXISTS 'flowscript';
-- Same as `flow_version` but with a "lite" value (e.g. `RawScript` replaced by `FlowScript`).
CREATE TABLE flow_version_lite (
id BIGSERIAL PRIMARY KEY,
value JSONB,
FOREIGN KEY (id) REFERENCES flow_version (id) ON DELETE CASCADE
);
GRANT ALL ON flow_version_lite TO windmill_user;
GRANT ALL ON flow_version_lite TO windmill_admin;
-- Either a script or a flow value.
CREATE TABLE flow_node (
id BIGSERIAL PRIMARY KEY,
workspace_id VARCHAR(50) NOT NULL REFERENCES workspace(id),
hash BIGINT NOT NULL,
path VARCHAR(255) NOT NULL, -- flow path.
lock TEXT,
code TEXT,
flow JSONB,
FOREIGN KEY (path, workspace_id) REFERENCES flow (path, workspace_id) ON DELETE CASCADE
);
GRANT ALL ON flow_node TO windmill_user;
GRANT ALL ON flow_node TO windmill_admin;
CREATE INDEX flow_node_hash ON flow_node (hash);

View File

@@ -1 +0,0 @@
-- Add down migration script here

View File

@@ -1,2 +0,0 @@
-- Add up migration script here
ALTER TYPE JOB_KIND ADD VALUE IF NOT EXISTS 'flownode';

View File

@@ -1,12 +0,0 @@
-- for some managed dbs (e.g Azure Postgres) the role is not
-- automatically applied to the user when created
DO
$do$
BEGIN
GRANT windmill_user to CURRENT_USER;
GRANT windmill_admin to CURRENT_USER;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'error granting windmill_user and windmill_admin to current_user: %', SQLERRM;
END
$do$;

View File

@@ -63,7 +63,6 @@ static PYTHON_IMPORTS_REPLACEMENT: phf::Map<&'static str, &'static str> = phf_ma
"msgraph" => "msgraph-sdk",
"pythonjsonlogger" => "python-json-logger",
"socks" => "PySocks",
"taiga" => "python-taiga",
};
fn replace_import(x: String) -> String {

View File

@@ -93,12 +93,6 @@ pub fn parse_python_signature(
.iter()
.enumerate()
.map(|(i, x)| {
let mut typ = x
.as_arg()
.annotation
.as_ref()
.map_or(Typ::Unknown, |e| parse_expr(e));
let default = if i >= def_arg_start {
params
.defaults()
@@ -109,28 +103,19 @@ pub fn parse_python_signature(
None
};
let should_get_type_from_default = match &typ {
Typ::Unknown => true,
// if the type is a list of unknowns, we should get the type from the default
Typ::List(inner) => matches!(inner.as_ref(), Typ::Unknown),
_ => false,
};
let mut typ = x
.as_arg()
.annotation
.as_ref()
.map_or(Typ::Unknown, |e| parse_expr(e));
if should_get_type_from_default
if typ == Typ::Unknown
&& default.is_some()
&& default != Some(json!(FUNCTION_CALL))
{
typ = json_to_typ(default.as_ref().unwrap());
}
// if the type is still a list of unknowns after checking the default, we set it to a list of strings to not break past behavior
match typ {
Typ::List(inner) if matches!(inner.as_ref(), Typ::Unknown) => {
typ = Typ::List(Box::new(Typ::Str(None)));
}
_ => {}
}
Arg {
otyp: None,
name: x.as_arg().arg.to_string(),
@@ -208,7 +193,7 @@ fn parse_typ(id: &str) -> Typ {
"int" => Typ::Int,
"bool" => Typ::Bool,
"dict" => Typ::Object(vec![]),
"list" => Typ::List(Box::new(Typ::Unknown)),
"list" => Typ::List(Box::new(Typ::Str(None))),
"bytes" => Typ::Bytes,
"datetime" => Typ::Datetime,
"datetime.datetime" => Typ::Datetime,
@@ -608,69 +593,4 @@ def main(): return
Ok(())
}
#[test]
fn test_parse_python_sig_8() -> anyhow::Result<()> {
let code = r#"
from typing import List
def main(a: list, e: List[int], b: list = [1,2,3,4], c = [1,2,3,4], d = ["a", "b"]): return
"#;
println!(
"{}",
serde_json::to_string(&parse_python_signature(code, None)?)?
);
assert_eq!(
parse_python_signature(code, None)?,
MainArgSignature {
star_args: false,
star_kwargs: false,
args: vec![
Arg {
otyp: None,
name: "a".to_string(),
typ: Typ::List(Box::new(Typ::Str(None))),
default: None,
has_default: false,
oidx: None
},
Arg {
otyp: None,
name: "e".to_string(),
typ: Typ::List(Box::new(Typ::Int)),
default: None,
has_default: false,
oidx: None
},
Arg {
otyp: None,
name: "b".to_string(),
typ: Typ::List(Box::new(Typ::Int)),
default: Some(json!([1, 2, 3, 4])),
has_default: true,
oidx: None
},
Arg {
otyp: None,
name: "c".to_string(),
typ: Typ::List(Box::new(Typ::Int)),
default: Some(json!([1, 2, 3, 4])),
has_default: true,
oidx: None
},
Arg {
otyp: None,
name: "d".to_string(),
typ: Typ::List(Box::new(Typ::Str(None))),
default: Some(json!(["a", "b"])),
has_default: true,
oidx: None
}
],
no_main_func: Some(false),
has_preprocessor: Some(false)
}
);
Ok(())
}
}

View File

@@ -198,7 +198,6 @@ pub enum ResourceOrVariablePath {
pub struct FileResource {
pub resource_path: ResourceOrVariablePath,
pub target_path: String,
pub mode: Option<u32>,
}
#[derive(Debug, Clone)]
@@ -438,65 +437,36 @@ fn count_consecutive_vs(s: &str) -> usize {
fn parse_file_resource(yaml: &Yaml) -> anyhow::Result<FileResource> {
if let Yaml::Hash(f) = yaml {
let target_path = f
.get(&Yaml::String("target".to_string()))
.and_then(|x| x.as_str())
.map(|x| x.to_string())
.ok_or(anyhow!(
"No `target` provided for the file. Please input a target path (only relative paths are allowed) where the ansible playbook can read this file.",
))?;
let mut mode = None;
if let Some(u) = f.get(&Yaml::String("mode".to_string())) {
let mode_val: u32 = match u {
Yaml::Integer(u) => {
u.clone().try_into().map_err(|e| {
anyhow!(
"Invalid value for `mode` permissions property on targeted file to: {}, err: {e}",
target_path
)
})?
}
Yaml::String(s) => {
let val = if s.starts_with("0b") {
u32::from_str_radix(&s[2..], 2)
} else if s.starts_with("0o") {
u32::from_str_radix(&s[2..], 8)
} else if s.starts_with("0") {
u32::from_str_radix(&s[1..], 8)
} else {
u32::from_str_radix(s, 8)
};
val.map_err(|e| anyhow!("Error parsing permission mode value {s}: {e}"))?
}
_ => {
return Err(anyhow!("Invalid field in `mode`, expected integer like 0o644"));
}
};
if mode_val <= 0o777 {
mode = Some(mode_val);
} else {
return Err(anyhow!("The provided value for `mode` is too big. Make sure that you are using the octal prefix (0o), e.g. `mode: 0o644`"));
}
}
if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String("resource".to_string())) {
let target_path = f
.get(&Yaml::String("target".to_string()))
.and_then(|x| x.as_str())
.map(|x| x.to_string())
.ok_or(anyhow!(
"No `target` provided for file resource {}. Please input a target relative path for the ansible playbook to see this file.",
resource_path
))?;
return Ok(FileResource {
resource_path: ResourceOrVariablePath::Resource(resource_path.clone()),
target_path,
mode,
});
}
if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String("variable".to_string())) {
let target_path = f
.get(&Yaml::String("target".to_string()))
.and_then(|x| x.as_str())
.map(|x| x.to_string())
.ok_or(anyhow!(
"No `target` provided for file resource {}. Please input a target relative path for the ansible playbook to see this file.",
resource_path
))?;
return Ok(FileResource {
resource_path: ResourceOrVariablePath::Variable(resource_path.clone()),
target_path,
mode,
});
}
return Err(anyhow!(
"Files should have a `resource` or `variable` field that will be the contents of the local text file"
"File resource should have a `resource` field, linking to a text file resource"
));
}
return Err(anyhow!("Invalid file resource: Should be a dictionary."));

View File

@@ -8,7 +8,8 @@
use anyhow::Context;
use monitor::{
reload_delete_logs_periodically_setting, reload_indexer_config, reload_timeout_wait_result_setting, send_current_log_file_to_object_store, send_logs_to_object_store
reload_timeout_wait_result_setting, send_current_log_file_to_object_store,
send_logs_to_object_store,
};
use rand::Rng;
use sqlx::{postgres::PgListener, Pool, Postgres};
@@ -29,7 +30,15 @@ use windmill_common::ee::{maybe_renew_license_key_on_start, LICENSE_KEY_ID, LICE
use windmill_common::{
global_settings::{
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING, CRITICAL_ERROR_CHANNELS_SETTING, CUSTOM_TAGS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, ENV_SETTINGS, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING, HUB_BASE_URL_SETTING, INDEXER_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, NPM_CONFIG_REGISTRY_SETTING, OAUTH_SETTING, PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING, TIMEOUT_WAIT_RESULT_SETTING
BASE_URL_SETTING, BUNFIG_INSTALL_SCOPES_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING,
CRITICAL_ERROR_CHANNELS_SETTING, CUSTOM_TAGS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING,
DEFAULT_TAGS_WORKSPACES_SETTING, ENV_SETTINGS, EXPOSE_DEBUG_METRICS_SETTING,
EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING, HUB_BASE_URL_SETTING,
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING,
LICENSE_KEY_SETTING, NPM_CONFIG_REGISTRY_SETTING, OAUTH_SETTING, PIP_INDEX_URL_SETTING,
REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING,
RETENTION_PERIOD_SECS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING,
TIMEOUT_WAIT_RESULT_SETTING,
},
scripts::ScriptLang,
stats_ee::schedule_stats,
@@ -58,8 +67,7 @@ use windmill_worker::{
get_hub_script_content_and_requirements, BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR,
BUN_DEPSTAR_CACHE_DIR, DENO_CACHE_DIR, DENO_CACHE_DIR_DEPS, DENO_CACHE_DIR_NPM,
GO_BIN_CACHE_DIR, GO_CACHE_DIR, LOCK_CACHE_DIR, PIP_CACHE_DIR, POWERSHELL_CACHE_DIR,
PY311_CACHE_DIR, RUST_CACHE_DIR, TAR_PIP_CACHE_DIR, TAR_PY311_CACHE_DIR, TMP_LOGS_DIR,
UV_CACHE_DIR,
PY311_CACHE_DIR, RUST_CACHE_DIR, TAR_PIP_CACHE_DIR, TMP_LOGS_DIR, UV_CACHE_DIR,
};
use crate::monitor::{
@@ -256,10 +264,6 @@ async fn windmill_main() -> anyhow::Result<()> {
Mode::Server
} else if &x == "worker" {
tracing::info!("Binary is in 'worker' mode");
#[cfg(windows)]
{
tracing::warn!("It is highly recommended to use the agent mode instead on windows (MODE=agent) and to pass a BASE_INTERNAL_URL");
}
Mode::Worker
} else if &x == "agent" {
tracing::info!("Binary is in 'agent' mode");
@@ -337,6 +341,27 @@ async fn windmill_main() -> anyhow::Result<()> {
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))
};
let rsmq_config = std::env::var("REDIS_URL").ok().map(|x| {
let url = x.parse::<url::Url>().unwrap();
let mut config = rsmq_async::RsmqOptions { ..Default::default() };
config.host = url.host_str().expect("redis host required").to_owned();
config.password = url.password().map(|s| s.to_owned());
config.db = url
.path_segments()
.and_then(|mut segments| segments.next())
.and_then(|segment| segment.parse().ok())
.unwrap_or(0);
config.ns = url
.query_pairs()
.find(|s| s.0 == "rsmq_namespace")
.map(|s| s.1)
.unwrap_or(std::borrow::Cow::Borrowed("rsmq"))
.into_owned();
config.port = url.port().unwrap_or(6379).to_string();
config
});
tracing::info!("Connecting to database...");
let db = windmill_common::connect_db(server_mode, indexer_mode).await?;
tracing::info!("Database connected");
@@ -351,6 +376,13 @@ async fn windmill_main() -> anyhow::Result<()> {
.unwrap_or_else(|| "UNKNOWN".to_string())
);
let rsmq = if let Some(config) = rsmq_config {
tracing::info!("Redis config set: {:?}", config);
Some(rsmq_async::MultiplexedRsmq::new(config).await.unwrap())
} else {
None
};
let is_agent = mode == Mode::Agent;
if !is_agent {
@@ -411,7 +443,7 @@ Windmill Community Edition {GIT_VERSION}
}
let valid_key = *LICENSE_KEY_VALID.read().await;
if !valid_key && !server_mode {
tracing::error!("Invalid license key, workers require a valid license key");
panic!("Invalid license key, workers require a valid license key");
}
if server_mode {
// only force renewal if invalid but not empty (= expired)
@@ -426,6 +458,13 @@ Windmill Community Edition {GIT_VERSION}
tracing::error!("Failed to reload license key: {err:#}");
}
}
if num_workers > 0 {
let valid_key = *LICENSE_KEY_VALID.read().await;
if !valid_key {
tracing::warn!("License key invalid, setting num_workers to 0");
num_workers = 0;
}
}
}
}
@@ -458,6 +497,7 @@ Windmill Community Edition {GIT_VERSION}
monitor_db(
&db,
&base_internal_url,
rsmq.clone(),
server_mode,
worker_mode,
true,
@@ -476,6 +516,7 @@ Windmill Community Edition {GIT_VERSION}
let addr = SocketAddr::from((server_bind_address, port));
let rsmq2 = rsmq.clone();
let (base_internal_tx, base_internal_rx) = tokio::sync::oneshot::channel::<String>();
DirBuilder::new()
@@ -488,25 +529,10 @@ Windmill Community Edition {GIT_VERSION}
let should_index_jobs =
mode == Mode::Indexer || (enable_standalone_indexer && mode == Mode::Standalone);
reload_indexer_config(&db).await;
#[cfg(feature = "tantivy")]
let (index_reader, index_writer) = if should_index_jobs {
let mut indexer_rx = killpill_rx.resubscribe();
let (mut reader, mut writer) = (None, None);
tokio::select! {
_ = indexer_rx.recv() => {
tracing::info!("Received killpill, aborting index initialization");
},
res = windmill_indexer::completed_runs_ee::init_index(&db) => {
let res = res?;
reader = Some(res.0);
writer = Some(res.1);
}
}
(reader, writer)
let (r, w) = windmill_indexer::completed_runs_ee::init_index(&db).await?;
(Some(r), Some(w))
} else {
(None, None)
};
@@ -522,7 +548,7 @@ Windmill Community Edition {GIT_VERSION}
index_writer,
indexer_rx,
)
.await?;
.await;
}
Ok(())
}
@@ -530,21 +556,8 @@ Windmill Community Edition {GIT_VERSION}
#[cfg(all(feature = "tantivy", feature = "parquet"))]
let (log_index_reader, log_index_writer) = if should_index_jobs {
let mut indexer_rx = killpill_rx.resubscribe();
let (mut reader, mut writer) = (None, None);
tokio::select! {
_ = indexer_rx.recv() => {
tracing::info!("Received killpill, aborting index initialization");
},
res = windmill_indexer::service_logs_ee::init_index(&db) => {
let res = res?;
reader = Some(res.0);
writer = Some(res.1);
}
}
(reader, writer)
let (r, w) = windmill_indexer::service_logs_ee::init_index(&db).await?;
(Some(r), Some(w))
} else {
(None, None)
};
@@ -560,7 +573,7 @@ Windmill Community Edition {GIT_VERSION}
log_index_writer,
log_indexer_rx,
)
.await?;
.await;
}
Ok(())
}
@@ -582,6 +595,7 @@ Windmill Community Edition {GIT_VERSION}
if !is_agent {
windmill_api::run_server(
db.clone(),
rsmq2,
index_reader,
log_index_reader,
addr,
@@ -613,6 +627,7 @@ Windmill Community Edition {GIT_VERSION}
killpill_tx.clone(),
num_workers,
base_internal_url.clone(),
rsmq.clone(),
mode.clone() == Mode::Agent,
hostname.clone(),
)
@@ -628,12 +643,13 @@ Windmill Community Edition {GIT_VERSION}
killpill_phase2_tx.send(())?;
tracing::info!("Phase 2 of shutdown completed");
}
Ok(())
Ok(()) as anyhow::Result<()>
};
let monitor_f = async {
let db = db.clone();
let tx = killpill_tx.clone();
let rsmq = rsmq.clone();
let base_internal_url = base_internal_url.to_string();
let h = tokio::spawn(async move {
@@ -650,6 +666,7 @@ Windmill Community Edition {GIT_VERSION}
monitor_db(
&db,
&base_internal_url,
rsmq.clone(),
server_mode,
worker_mode,
false,
@@ -698,6 +715,14 @@ Windmill Community Edition {GIT_VERSION}
if let Err(e) = reload_license_key(&db).await {
tracing::error!("Failed to reload license key: {e:#}");
}
#[cfg(feature = "enterprise")]
if worker_mode {
let valid_key = *LICENSE_KEY_VALID.read().await;
if !valid_key {
tracing::error!("Invalid license key, exiting...");
tx.send(()).expect("send");
}
}
},
DEFAULT_TAGS_PER_WORKSPACE_SETTING => {
if let Err(e) = load_tag_per_workspace_enabled(&db).await {
@@ -712,18 +737,12 @@ Windmill Community Edition {GIT_VERSION}
SMTP_SETTING => {
reload_smtp_config(&db).await;
},
INDEXER_SETTING => {
reload_indexer_config(&db).await;
},
TIMEOUT_WAIT_RESULT_SETTING => {
reload_timeout_wait_result_setting(&db).await
},
RETENTION_PERIOD_SECS_SETTING => {
reload_retention_period_setting(&db).await
},
MONITOR_LOGS_ON_OBJECT_STORE_SETTING => {
reload_delete_logs_periodically_setting(&db).await
},
JOB_DEFAULT_TIMEOUT_SECS_SETTING => {
reload_job_default_timeout_setting(&db).await
},
@@ -935,12 +954,13 @@ fn display_config(envs: &[&str]) {
)
}
pub async fn run_workers(
pub async fn run_workers<R: rsmq_async::RsmqConnection + Send + Sync + Clone + 'static>(
db: Pool<Postgres>,
mut rx: tokio::sync::broadcast::Receiver<()>,
tx: tokio::sync::broadcast::Sender<()>,
num_workers: i32,
base_internal_url: String,
rsmq: Option<R>,
agent_mode: bool,
hostname: String,
) -> anyhow::Result<()> {
@@ -979,7 +999,6 @@ pub async fn run_workers(
TMP_LOGS_DIR,
UV_CACHE_DIR,
TAR_PIP_CACHE_DIR,
TAR_PY311_CACHE_DIR,
DENO_CACHE_DIR,
DENO_CACHE_DIR_DEPS,
DENO_CACHE_DIR_NPM,
@@ -1013,6 +1032,7 @@ pub async fn run_workers(
let rx = killpill_rxs.pop().unwrap();
let tx = tx.clone();
let base_internal_url = base_internal_url.clone();
let rsmq2 = rsmq.clone();
let hostname = hostname.clone();
handles.push(tokio::spawn(async move {
@@ -1030,6 +1050,7 @@ pub async fn run_workers(
rx,
tx,
&base_internal_url,
rsmq2,
agent_mode,
);

View File

@@ -11,7 +11,7 @@ use std::{
};
use chrono::{NaiveDateTime, Utc};
use futures::{stream::FuturesUnordered, StreamExt};
use rsmq_async::MultiplexedRsmq;
use serde::de::DeserializeOwned;
use sqlx::{Pool, Postgres};
use tokio::{
@@ -27,7 +27,7 @@ use windmill_api::{
DEFAULT_BODY_LIMIT, IS_SECURE, OAUTH_CLIENTS, REQUEST_SIZE_LIMIT, SAML_METADATA, SCIM_TOKEN,
};
#[cfg(feature = "enterprise")]
use windmill_common::ee::{jobs_waiting_alerts, worker_groups_alerts};
use windmill_common::ee::{jobs_waiting_alerts, worker_groups_alerts, LICENSE_KEY_VALID};
use windmill_common::{
auth::JWT_SECRET,
ee::CriticalErrorChannel,
@@ -38,13 +38,11 @@ use windmill_common::{
CRITICAL_ERROR_CHANNELS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING,
DEFAULT_TAGS_WORKSPACES_SETTING, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
EXTRA_PIP_INDEX_URL_SETTING, HUB_BASE_URL_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING,
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPM_CONFIG_REGISTRY_SETTING, OAUTH_SETTING,
PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, NPM_CONFIG_REGISTRY_SETTING,
OAUTH_SETTING, PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
},
indexer::load_indexer_config,
jobs::QueuedJob,
oauth2::REQUIRE_PREEXISTING_USER_FOR_OAUTH,
server::load_smtp_config,
@@ -53,12 +51,11 @@ use windmill_common::{
utils::{now_from_db, rd_string, report_critical_error, Mode},
worker::{
load_worker_config, make_pull_query, make_suspended_pull_query, reload_custom_tags_setting,
update_min_version, DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, INDEXER_CONFIG,
SMTP_CONFIG, TMP_DIR, WORKER_CONFIG, WORKER_GROUP,
update_min_version, DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, SMTP_CONFIG,
WORKER_CONFIG, WORKER_GROUP,
},
BASE_URL, CRITICAL_ALERT_MUTE_UI_ENABLED, CRITICAL_ERROR_CHANNELS, DB, DEFAULT_HUB_BASE_URL,
HUB_BASE_URL, JOB_RETENTION_SECS, METRICS_DEBUG_ENABLED, METRICS_ENABLED,
MONITOR_LOGS_ON_OBJECT_STORE, SERVICE_LOG_RETENTION_SECS,
};
use windmill_queue::cancel_job;
use windmill_worker::{
@@ -182,7 +179,6 @@ pub async fn initial_load(
}
if worker_mode {
reload_job_default_timeout_setting(&db).await;
reload_extra_pip_index_url_setting(&db).await;
reload_pip_index_url_setting(&db).await;
reload_npm_config_registry_setting(&db).await;
@@ -571,11 +567,6 @@ pub async fn load_require_preexisting_user(db: &DB) {
};
}
struct LogFile {
file_path: String,
hostname: String,
}
pub async fn delete_expired_items(db: &DB) -> () {
let tokens_deleted_r: std::result::Result<Vec<String>, _> = sqlx::query_scalar(
"DELETE FROM token WHERE expiration <= now()
@@ -638,25 +629,6 @@ pub async fn delete_expired_items(db: &DB) -> () {
Err(e) => tracing::error!("Error deleting cache resource {}", e.to_string()),
}
match sqlx::query_as!(
LogFile,
"DELETE FROM log_file WHERE log_ts <= now() - ($1::bigint::text || ' s')::interval RETURNING file_path, hostname",
SERVICE_LOG_RETENTION_SECS,
)
.fetch_all(db)
.await
{
Ok(log_files_to_delete) => {
let paths = log_files_to_delete
.iter()
.map(|f| format!("{}/{}", f.hostname, f.file_path))
.collect();
delete_log_files_from_disk_and_store(paths, TMP_WINDMILL_LOGS_SERVICE, windmill_common::tracing_init::LOGS_SERVICE).await;
}
Err(e) => tracing::error!("Error deleting log file: {:?}", e),
}
let job_retention_secs = *JOB_RETENTION_SECS.read().await;
if job_retention_secs > 0 {
match db.begin().await {
@@ -686,22 +658,14 @@ pub async fn delete_expired_items(db: &DB) -> () {
{
tracing::error!("Error deleting job stats: {:?}", e);
}
match sqlx::query_scalar!(
"DELETE FROM job_logs WHERE job_id = ANY($1) RETURNING log_file_index",
if let Err(e) = sqlx::query!(
"DELETE FROM job_logs WHERE job_id = ANY($1)",
&deleted_jobs
)
.fetch_all(&mut *tx)
.execute(&mut *tx)
.await
{
Ok(log_file_index) => {
let paths = log_file_index
.into_iter()
.filter_map(|opt| opt)
.flat_map(|inner_vec| inner_vec.into_iter())
.collect();
delete_log_files_from_disk_and_store(paths, TMP_DIR, "").await;
}
Err(e) => tracing::error!("Error deleting job stats: {:?}", e),
tracing::error!("Error deleting job stats: {:?}", e);
}
if let Err(e) = sqlx::query!(
"DELETE FROM concurrency_key WHERE ended_at <= now() - ($1::bigint::text || ' s')::interval ",
@@ -712,13 +676,14 @@ pub async fn delete_expired_items(db: &DB) -> () {
{
tracing::error!("Error deleting custom concurrency key: {:?}", e);
}
if let Err(e) =
sqlx::query!("DELETE FROM job WHERE id = ANY($1)", &deleted_jobs)
.execute(&mut *tx)
.await
if let Err(e) = sqlx::query!(
"DELETE FROM log_file WHERE log_ts <= now() - ($1::bigint::text || ' s')::interval ",
job_retention_secs
)
.execute(&mut *tx)
.await
{
tracing::error!("Error deleting job: {:?}", e);
tracing::error!("Error deleting log file: {:?}", e);
}
}
}
@@ -739,59 +704,6 @@ pub async fn delete_expired_items(db: &DB) -> () {
}
}
async fn delete_log_files_from_disk_and_store(
paths_to_delete: Vec<String>,
tmp_dir: &str,
_s3_prefix: &str,
) {
#[cfg(feature = "parquet")]
let os = windmill_common::s3_helpers::OBJECT_STORE_CACHE_SETTINGS
.read()
.await
.clone();
#[cfg(not(feature = "parquet"))]
let os: Option<()> = None;
let _should_del_from_store = MONITOR_LOGS_ON_OBJECT_STORE.read().await.clone();
let delete_futures = FuturesUnordered::new();
for path in paths_to_delete {
let _os2 = &os;
delete_futures.push(async move {
let disk_path = std::path::Path::new(tmp_dir).join(&path);
if tokio::fs::metadata(&disk_path).await.is_ok() {
if let Err(e) = tokio::fs::remove_file(&disk_path).await {
tracing::error!(
"Failed to delete from disk {}: {e}",
disk_path.to_string_lossy()
);
} else {
tracing::debug!(
"Succesfully deleted {} from disk",
disk_path.to_string_lossy()
);
}
}
#[cfg(feature = "parquet")]
if _should_del_from_store {
if let Some(os) = _os2 {
let p = object_store::path::Path::from(format!("{}{}", _s3_prefix, path));
if let Err(e) = os.delete(&p).await {
tracing::error!("Failed to delete from object store {}: {e}", p.to_string())
} else {
tracing::debug!("Succesfully deleted {} from object store", p.to_string());
}
}
}
});
}
let _: Vec<_> = delete_futures.collect().await;
}
pub async fn reload_scim_token_setting(db: &DB) {
reload_option_setting_with_tracing(db, SCIM_TOKEN_SETTING, "SCIM_TOKEN", SCIM_TOKEN.clone())
.await;
@@ -870,20 +782,6 @@ pub async fn reload_retention_period_setting(db: &DB) {
tracing::error!("Error reloading retention period: {:?}", e)
}
}
pub async fn reload_delete_logs_periodically_setting(db: &DB) {
if let Err(e) = reload_setting(
db,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING,
"MONITOR_LOGS_ON_OBJECT_STORE",
false,
MONITOR_LOGS_ON_OBJECT_STORE.clone(),
|x| x,
)
.await
{
tracing::error!("Error reloading retention period: {:?}", e)
}
}
#[cfg(feature = "parquet")]
pub async fn reload_s3_cache_setting(db: &DB) {
@@ -1123,6 +1021,7 @@ pub async fn monitor_pool(db: &DB) {
pub async fn monitor_db(
db: &Pool<Postgres>,
base_internal_url: &str,
rsmq: Option<MultiplexedRsmq>,
server_mode: bool,
_worker_mode: bool,
initial_load: bool,
@@ -1130,8 +1029,8 @@ pub async fn monitor_db(
) {
let zombie_jobs_f = async {
if server_mode && !initial_load {
handle_zombie_jobs(db, base_internal_url, "server").await;
match handle_zombie_flows(db).await {
handle_zombie_jobs(db, base_internal_url, rsmq.clone(), "server").await;
match handle_zombie_flows(db, rsmq.clone()).await {
Err(err) => {
tracing::error!("Error handling zombie flows: {:?}", err);
}
@@ -1149,6 +1048,13 @@ pub async fn monitor_db(
#[cfg(feature = "enterprise")]
if !initial_load {
verify_license_key().await;
if _worker_mode {
let valid_key = *LICENSE_KEY_VALID.read().await;
if !valid_key {
tracing::error!("Invalid license key, exiting...");
_killpill_tx.send(()).expect("send");
}
}
}
};
@@ -1280,17 +1186,6 @@ pub async fn reload_smtp_config(db: &Pool<Postgres>) {
}
}
pub async fn reload_indexer_config(db: &Pool<Postgres>) {
let indexer_config = load_indexer_config(&db).await;
if let Err(e) = indexer_config {
tracing::error!("Error reloading indexer config: {:?}", e)
} else {
let mut wc = INDEXER_CONFIG.write().await;
tracing::info!("Reloading smtp config...");
*wc = indexer_config.unwrap()
}
}
pub async fn reload_worker_config(
db: &DB,
tx: tokio::sync::broadcast::Sender<()>,
@@ -1396,7 +1291,12 @@ pub async fn reload_base_url_setting(db: &DB) -> error::Result<()> {
Ok(())
}
async fn handle_zombie_jobs(db: &Pool<Postgres>, base_internal_url: &str, worker_name: &str) {
async fn handle_zombie_jobs<R: rsmq_async::RsmqConnection + Send + Sync + Clone>(
db: &Pool<Postgres>,
base_internal_url: &str,
rsmq: Option<R>,
worker_name: &str,
) {
if *RESTART_ZOMBIE_JOBS {
let restarted = sqlx::query!(
"UPDATE queue SET running = false, started_at = null
@@ -1505,6 +1405,7 @@ async fn handle_zombie_jobs(db: &Pool<Postgres>, base_internal_url: &str, worker
true,
same_worker_tx_never_used,
"",
rsmq.clone(),
worker_name,
send_result_never_used,
#[cfg(feature = "benchmark")]
@@ -1514,7 +1415,10 @@ async fn handle_zombie_jobs(db: &Pool<Postgres>, base_internal_url: &str, worker
}
}
async fn handle_zombie_flows(db: &DB) -> error::Result<()> {
async fn handle_zombie_flows(
db: &DB,
rsmq: Option<rsmq_async::MultiplexedRsmq>,
) -> error::Result<()> {
let flows = sqlx::query_as::<_, QueuedJob>(
r#"
SELECT *
@@ -1561,7 +1465,7 @@ async fn handle_zombie_flows(db: &DB) -> error::Result<()> {
}
);
report_critical_error(reason.clone(), db.clone(), Some(&flow.workspace_id), None).await;
cancel_zombie_flow_job(db, flow, reason).await?;
cancel_zombie_flow_job(db, flow, &rsmq, reason).await?;
}
}
@@ -1591,7 +1495,7 @@ async fn handle_zombie_flows(db: &DB) -> error::Result<()> {
job.workspace_id,
flow.last_ping
);
cancel_zombie_flow_job(db, job,
cancel_zombie_flow_job(db, job, &rsmq,
format!("Flow {} cancelled as one of the parallel branch {} was unable to make the last transition ", flow.parent_flow_id, flow.job_id))
.await?;
} else {
@@ -1604,6 +1508,7 @@ async fn handle_zombie_flows(db: &DB) -> error::Result<()> {
async fn cancel_zombie_flow_job(
db: &Pool<Postgres>,
flow: QueuedJob,
rsmq: &Option<MultiplexedRsmq>,
message: String,
) -> Result<(), error::Error> {
let tx = db.begin().await.unwrap();
@@ -1619,6 +1524,7 @@ async fn cancel_zombie_flow_job(
flow.workspace_id.as_str(),
tx,
db,
rsmq.clone(),
true,
false,
)

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