Compare commits
28 Commits
rf/orderBy
...
v1.490.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a470e38177 | ||
|
|
b51568c166 | ||
|
|
54b4815df2 | ||
|
|
9e2cdade92 | ||
|
|
a23a4c0faf | ||
|
|
a3c76fb10c | ||
|
|
7c69959853 | ||
|
|
66798df384 | ||
|
|
011434b072 | ||
|
|
254c3cf8ef | ||
|
|
bb0ed2b112 | ||
|
|
7b48c10f12 | ||
|
|
e0d36a60e0 | ||
|
|
0cd92932f0 | ||
|
|
233bc1bfc5 | ||
|
|
c80c9c70ce | ||
|
|
da4df4c99a | ||
|
|
5589135cb0 | ||
|
|
242a565428 | ||
|
|
45224fec3d | ||
|
|
0ac8e477d6 | ||
|
|
40f4071702 | ||
|
|
06287d8a11 | ||
|
|
df9f827d10 | ||
|
|
e6f965c119 | ||
|
|
8a47414ca8 | ||
|
|
75d992449c | ||
|
|
386ed62a4e |
109
.cursor/rules/rust-best-practices.mdc
Normal file
109
.cursor/rules/rust-best-practices.mdc
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
description:
|
||||
globs: backend/**/*.rs
|
||||
alwaysApply: false
|
||||
---
|
||||
# Windmill Backend - Rust Best Practices
|
||||
|
||||
## Project Structure
|
||||
|
||||
Windmill uses a workspace-based architecture with multiple crates:
|
||||
|
||||
- **windmill-api**: API server functionality
|
||||
- **windmill-worker**: Job execution
|
||||
- **windmill-common**: Shared code used by all crates
|
||||
- **windmill-queue**: Job & flow queuing
|
||||
- **windmill-audit**: Audit logging
|
||||
- Other specialized crates (git-sync, autoscaling, etc.)
|
||||
|
||||
## Adding New Code
|
||||
|
||||
### Module Organization
|
||||
|
||||
- Place new code in the appropriate crate based on functionality
|
||||
- For API endpoints, create or modify files in `windmill-api/src/` organized by domain
|
||||
- For shared functionality, use `windmill-common/src/`
|
||||
- Use the `_ee.rs` suffix for enterprise-only modules
|
||||
- Follow existing patterns for file structure and organization
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use the custom `Error` enum from `windmill-common::error`
|
||||
- Return `Result<T, Error>` or `JsonResult<T>` for functions that can fail
|
||||
- Use the `?` operator for error propagation
|
||||
- Add location tracking to errors using `#[track_caller]`
|
||||
|
||||
### Database Operations
|
||||
|
||||
- Use `sqlx` for database operations with prepared statements
|
||||
- Leverage existing database helper functions in `db.rs` modules
|
||||
- Use transactions for multi-step operations
|
||||
- Handle database errors properly
|
||||
|
||||
### API Endpoints
|
||||
|
||||
- Follow existing patterns in the `windmill-api` crate
|
||||
- Use axum's routing system and extractors
|
||||
- Group related routes together
|
||||
- Use consistent response formats (JSON)
|
||||
- Follow proper authentication and authorization patterns
|
||||
|
||||
## Performance Optimizations
|
||||
|
||||
When generating code, especially involving `serde`, `sqlx`, and `tokio`, prioritize performance by applying the following principles:
|
||||
|
||||
### Serde Optimizations (Serialization & Deserialization)
|
||||
|
||||
- **Specify Structure Explicitly:** When defining structs for Serde (`#[derive(Serialize, Deserialize)]`), use `#[serde(...` attributes extensively. This includes:
|
||||
* `#[serde(rename = "...")]` or `#[serde(alias = "...")]` to map external names precisely, avoiding dynamic lookups.
|
||||
* `#[serde(default)]` for optional fields with default values, reducing parsing complexity.
|
||||
* `#[serde(skip_serializing_if = "...")]` to avoid writing fields that meet a certain condition (e.g., `Option::is_none()`, `Vec::is_empty()`, or a custom function), reducing output size and serialization work.
|
||||
* `#[serde(skip_serializing)]` or `#[serde(skip_deserializing)]` for fields that should *not* be included.
|
||||
- **Prefer Borrowing:** Where possible and safe (data lifetime allows), use `Cow<'a, str>` or `&'a str` (with `#[serde(borrow)]`) instead of `String` for string fields during deserialization. This avoids allocating new strings, enabling zero-copy reading from the input buffer. Apply this principle to byte slices (`&'a [u8]` / `Cow<'a, [u8]>`) and potentially borrowed vectors as well.
|
||||
- **Avoid Intermediate `Value`:** Unless the data structure is truly dynamic or unknown at compile time, deserialize directly into a well-defined struct or enum rather than into `serde_json::Value` (or equivalent for other formats). This avoids unnecessary heap allocations and type switching.
|
||||
|
||||
### SQLx Optimizations (Database Interaction)
|
||||
|
||||
- **Select Only Necessary Columns:** In `SELECT` queries, list specific column names rather than using `SELECT *`. This reduces data transferred from the database and the work needed for hydration/deserialization.
|
||||
- **Batch Operations:** For multiple `INSERT`, `UPDATE`, or `DELETE` statements, prefer executing them in a single query if the database and driver support it efficiently (e.g., `INSERT INTO ... VALUES (...), (...), ...`). This minimizes round trips to the database.
|
||||
- **Avoid N+1 Queries:** Do not loop through results of one query and execute a separate query for each item (e.g., fetching users, then querying for each user's profile in a loop). Instead, use JOINs or a single query with an `IN` clause to fetch related data efficiently.
|
||||
- **Deserialize Directly:** Use `#[derive(FromRow)]` on structs and ensure the struct fields match the selected columns in the query. This allows SQLx to hydrate objects directly, avoiding intermediate data structures.
|
||||
- **Parameterize Queries:** Always use SQLx's query methods (`.bind(...)`) to pass values as parameters rather than string formatting. This prevents SQL injection and allows the database to cache query plans, improving performance on repeated executions.
|
||||
|
||||
### Tokio Optimizations (Asynchronous Runtime)
|
||||
|
||||
- **Avoid Blocking Operations:** **Crucially**, never perform blocking operations (synchronous file I/O, `std::thread::sleep`, CPU-bound loops, `std::sync::Mutex::lock`, blocking network calls without `tokio::net`) directly within an `async fn` or a standard `tokio::spawn` task. Blocking pauses the entire worker thread, potentially starving other tasks. Use `tokio::task::spawn_blocking` for CPU-intensive work or blocking I/O.
|
||||
- **Use Tokio's Async Primitives:** Prefer `tokio::sync` (channels, mutexes, semaphores), `tokio::io`, `tokio::net`, and `tokio::time` over their `std` counterparts in asynchronous contexts. These are designed to yield control back to the scheduler.
|
||||
- **Manage Concurrency:** Be mindful of how many tasks are spawned. Creating a new task for every tiny piece of work can introduce overhead. Group related asynchronous operations where appropriate.
|
||||
- **Handle Shared State Efficiently:** Use `Arc` for shared ownership in concurrent tasks. When shared state needs mutation, prefer `tokio::sync::Mutex` over `std::sync::Mutex` in `async` code. Consider `tokio::sync::RwLock` if reads significantly outnumber writes. Minimize the duration for which locks are held.
|
||||
- **Understand `.await`:** Place `.await` strategically to allow the runtime to switch to other ready tasks. Ensure that `.await` points to genuinely asynchronous operations.
|
||||
- **Backpressure:** If dealing with data streams or queues between tasks, implement backpressure mechanisms (e.g., bounded channels like `tokio::sync::mpsc::channel`) to prevent one component from overwhelming another or critical resources like the database.
|
||||
|
||||
## Enterprise Features
|
||||
|
||||
- Use feature flags for enterprise functionality
|
||||
- Conditionally compile with `#[cfg(feature = "enterprise")]`
|
||||
- Isolate enterprise code in separate modules
|
||||
|
||||
## Code Style
|
||||
|
||||
- Group imports by external and internal crates
|
||||
- Place struct/enum definitions before implementations
|
||||
- Group similar functionality together
|
||||
- Use descriptive naming consistent with the codebase
|
||||
- Follow existing patterns for async code using tokio
|
||||
|
||||
## Testing
|
||||
|
||||
- Write unit tests for core functionality
|
||||
- Use the `#[cfg(test)]` module for test code
|
||||
- For database tests, use the existing test utilities
|
||||
|
||||
## Common Crates Used
|
||||
|
||||
- **tokio**: For async runtime
|
||||
- **axum**: For web server and routing
|
||||
- **sqlx**: For database operations
|
||||
- **serde**: For serialization/deserialization
|
||||
- **tracing**: For logging and diagnostics
|
||||
- **reqwest**: For HTTP client functionality
|
||||
229
.cursor/rules/svelte5-best-practices.mdc
Normal file
229
.cursor/rules/svelte5-best-practices.mdc
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
description:
|
||||
globs: frontend/src/**/*.svelte
|
||||
alwaysApply: false
|
||||
---
|
||||
# Svelte 5 Best Practices
|
||||
|
||||
This guide outlines best practices for developing with Svelte 5, incorporating the new Runes API and other modern Svelte features. They should be applied on every new files created, but not on existing svelte 4 files unless specifically asked to.
|
||||
|
||||
## Reactivity with Runes
|
||||
|
||||
Svelte 5 introduces Runes for more explicit and flexible reactivity.
|
||||
|
||||
1. **Embrace Runes for State Management**:
|
||||
* Use `$state` for reactive local component state.
|
||||
```svelte
|
||||
<script>
|
||||
let count = $state(0);
|
||||
|
||||
function increment() {
|
||||
count += 1;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={increment}>
|
||||
Clicked {count} {count === 1 ? 'time' : 'times'}
|
||||
</button>
|
||||
```
|
||||
* Use `$derived` for computed values based on other reactive state.
|
||||
```svelte
|
||||
<script>
|
||||
let count = $state(0);
|
||||
const doubled = $derived(count * 2);
|
||||
</script>
|
||||
|
||||
<p>{count} * 2 = {doubled}</p>
|
||||
```
|
||||
* Use `$effect` for side effects that need to run when reactive values change (e.g., logging, manual DOM manipulation, data fetching). Remember `$effect` does not run on the server.
|
||||
```svelte
|
||||
<script>
|
||||
let count = $state(0);
|
||||
|
||||
$effect(() => {
|
||||
console.log('The count is now', count);
|
||||
if (count > 5) {
|
||||
alert('Count is too high!');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
2. **Props with `$props`**:
|
||||
* Declare component props using `$props()`. This offers better clarity and flexibility compared to `export let`.
|
||||
```svelte
|
||||
<script>
|
||||
// ChildComponent.svelte
|
||||
let { name, age = $state(30) } = $props();
|
||||
</script>
|
||||
|
||||
<p>Name: {name}</p>
|
||||
<p>Age: {age}</p>
|
||||
```
|
||||
* For bindable props, use `$bindable`.
|
||||
```svelte
|
||||
<script>
|
||||
// MyInput.svelte
|
||||
let { value = $bindable() } = $props();
|
||||
</script>
|
||||
|
||||
<input bind:value />
|
||||
```
|
||||
|
||||
## Event Handling
|
||||
|
||||
* **Use direct event attributes**: Svelte 5 moves away from `on:` directives for DOM events.
|
||||
* **Do**: `<button onclick={handleClick}>...</button>`
|
||||
* **Don't**: `<button on:click={handleClick}>...</button>`
|
||||
* **For component events, prefer callback props**: Instead of `createEventDispatcher`, pass functions as props.
|
||||
```svelte
|
||||
<!-- Parent.svelte -->
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
let message = $state('');
|
||||
function handleChildEvent(detail) {
|
||||
message = detail;
|
||||
}
|
||||
</script>
|
||||
<Child onCustomEvent={handleChildEvent} />
|
||||
<p>Message from child: {message}</p>
|
||||
|
||||
<!-- Child.svelte -->
|
||||
<script>
|
||||
let { onCustomEvent } = $props();
|
||||
function emitEvent() {
|
||||
onCustomEvent('Hello from child!');
|
||||
}
|
||||
</script>
|
||||
<button onclick={emitEvent}>Send Event</button>
|
||||
```
|
||||
|
||||
## Snippets for Content Projection
|
||||
|
||||
* **Use `{#snippet ...}` and `{@render ...}` instead of slots**: Snippets are more powerful and flexible.
|
||||
```svelte
|
||||
<!-- Parent.svelte -->
|
||||
<script>
|
||||
import Card from './Card.svelte';
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
{#snippet title()}
|
||||
My Awesome Title
|
||||
{/snippet}
|
||||
{#snippet content()}
|
||||
<p>Some interesting content here.</p>
|
||||
{/snippet}
|
||||
</Card>
|
||||
|
||||
<!-- Card.svelte -->
|
||||
<script>
|
||||
let { title, content } = $props();
|
||||
</script>
|
||||
|
||||
<article>
|
||||
<header>{@render title()}</header>
|
||||
<div>{@render content()}</div>
|
||||
</article>
|
||||
```
|
||||
* Default content is passed via the `children` prop (which is a snippet).
|
||||
```svelte
|
||||
<!-- Wrapper.svelte -->
|
||||
<script>
|
||||
let { children } = $props();
|
||||
</script>
|
||||
<div>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Component Design
|
||||
|
||||
1. **Create Small, Reusable Components**: Break down complex UIs into smaller, focused components. Each component should have a single responsibility. This also aids performance by limiting the scope of reactivity updates.
|
||||
2. **Descriptive Naming**: Use clear and descriptive names for variables, functions, and components.
|
||||
3. **Minimize Logic in Components**: Move complex business logic to utility functions or services. Keep components focused on presentation and interaction.
|
||||
|
||||
## State Management (Stores)
|
||||
|
||||
1. **Segment Stores**: Avoid a single global store. Create multiple stores, each responsible for a specific piece of global state (e.g., `userStore.js`, `themeStore.js`). This can help limit reactivity updates to only the parts of the UI that depend on specific state segments.
|
||||
2. **Use Custom Stores for Complex Logic**: For stores with related methods, create custom stores.
|
||||
```javascript
|
||||
// counterStore.js
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
function createCounter() {
|
||||
const { subscribe, set, update } = writable(0);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
increment: () => update(n => n + 1),
|
||||
decrement: () => update(n => n - 1),
|
||||
reset: () => set(0)
|
||||
};
|
||||
}
|
||||
export const counter = createCounter();
|
||||
```
|
||||
3. **Use Context API for Localized State**: For state shared within a component subtree, consider Svelte's context API (`setContext`, `getContext`) instead of global stores when the state doesn't need to be truly global.
|
||||
|
||||
## Performance Optimizations (Svelte 5)
|
||||
|
||||
When generating Svelte 5 code, prioritize frontend performance by applying the following principles:
|
||||
|
||||
### General Svelte 5 Principles
|
||||
|
||||
- **Leverage the Compiler:** Trust Svelte's compiler to generate optimized JavaScript. Avoid manual DOM manipulation (`document.querySelector`, etc.) unless absolutely necessary for integrating third-party libraries that lack Svelte adapters.
|
||||
- **Keep Components Small and Focused:** Reinforcing from Component Design, smaller components lead to less complex reactivity graphs and more targeted, efficient updates.
|
||||
|
||||
### Reactivity & State Management
|
||||
|
||||
- **Optimize Computations with `$derived`:** Always use `$derived` for computed values that depend on other state. This ensures the computation only runs when its specific dependencies change, avoiding unnecessary work compared to recomputing derived values in `$effect` or less efficient methods.
|
||||
- **Minimize `$effect` Usage:** Use `$effect` sparingly and only for true side effects that interact with the outside world or non-Svelte state. Avoid putting complex logic or state updates *within* an `$effect` unless those updates are explicitly intended as a reaction to external changes or non-Svelte state. Excessive or complex effects can impact rendering performance.
|
||||
- **Structure State for Fine-Grained Updates:** Design your `$state` objects or variables such that updates affect only the necessary parts of the UI. Avoid putting too much unrelated state into a single large object that gets frequently updated, as this can potentially trigger broader updates than necessary. Consider normalizing complex, nested state.
|
||||
|
||||
### List Rendering (`{#each}`)
|
||||
|
||||
- **Mandate `key` Attribute:** Always use a `key` attribute (`{#each items as item (item.id)}`) that refers to a unique, stable identifier for each item in a list. This is critical for allowing Svelte to efficiently update, reorder, add, or remove list items without destroying and re-creating unnecessary DOM elements and component instances.
|
||||
|
||||
### Component Loading & Bundling
|
||||
|
||||
- **Implement Lazy Loading/Code Splitting:** For routes, components, or modules that are not immediately needed on page load, use dynamic imports (`import(...)`) to split the code bundle. SvelteKit handles this automatically for routes, but it can be applied manually to components using helper patterns if needed.
|
||||
- **Be Mindful of Third-Party Libraries:** When incorporating external libraries, import only the necessary functions or components to minimize the final bundle size. Prefer libraries designed to be tree-shakeable.
|
||||
|
||||
### Rendering & DOM
|
||||
|
||||
- **Use CSS for Animations/Transitions:** Prefer CSS animations or transitions where possible for performance. Svelte's built-in `transition:` directive is also highly optimized and should be used for complex state-driven transitions, but simple cases can often use plain CSS.
|
||||
- **Optimize Image Loading:** Implement best practices for images: use optimized formats (WebP, AVIF), lazy loading (`loading="lazy"`), and responsive images (`<picture>`, `srcset`) to avoid loading unnecessarily large images.
|
||||
|
||||
### Server-Side Rendering (SSR) & Hydration
|
||||
|
||||
- **Ensure SSR Compatibility:** Write components that can be rendered on the server for faster initial page loads. Avoid relying on browser-specific APIs (like `window` or `document`) in the main `<script>` context. If necessary, use `$effect` or check `if (browser)` inside effects to run browser-specific code only on the client.
|
||||
- **Minimize Work During Hydration:** Structure components and data fetching such that minimal complex setup or computation is required when the client-side Svelte code takes over from the server-rendered HTML. Heavy synchronous work during hydration can block the main thread.
|
||||
|
||||
## General Clean Code Practices
|
||||
|
||||
1. **Organized File Structure**: Group related files together. A common structure:
|
||||
```
|
||||
/src
|
||||
|-- /routes // Page components (if using a router like SvelteKit)
|
||||
|-- /lib // Utility functions, services, constants (SvelteKit often uses this)
|
||||
| |-- /stores
|
||||
| |-- /utils
|
||||
| |-- /services
|
||||
| |-- /components // Reusable UI components
|
||||
|-- App.svelte
|
||||
|-- main.js (or main.ts)
|
||||
```
|
||||
2. **Scoped Styles**: Keep CSS scoped to components to avoid unintended side effects and improve maintainability. Avoid `:global` where possible.
|
||||
3. **Immutability**: With Svelte 5 and `$state`, direct assignments to properties of `$state` objects (`obj.prop = value;`) are generally fine as Svelte's reactivity system handles updates. However, for non-rune state or when interacting with other systems, understanding and sometimes preferring immutable updates (creating new objects/arrays) can still be relevant.
|
||||
4. **Use `class:` and `style:` directives**: For dynamic classes and styles, use Svelte's built-in directives for cleaner templates and potentially optimized updates.
|
||||
```svelte
|
||||
<script>
|
||||
let isActive = $state(true);
|
||||
let color = $state('blue');
|
||||
</script>
|
||||
|
||||
<div class:active={isActive} style:color={color}>
|
||||
Hello
|
||||
</div>
|
||||
```
|
||||
5. **Stay Updated**: Keep Svelte and its related packages up to date to benefit from the latest features, performance improvements, and security fixes.
|
||||
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,5 +1,53 @@
|
||||
# Changelog
|
||||
|
||||
## [1.490.0](https://github.com/windmill-labs/windmill/compare/v1.489.0...v1.490.0) (2025-05-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* preprocessor refactor ([#5629](https://github.com/windmill-labs/windmill/issues/5629)) ([254c3cf](https://github.com/windmill-labs/windmill/commit/254c3cf8eff32071d5290429aafd26992527fbca))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add back missing query args from http trigger object + correct wm_trigger shape ([#5722](https://github.com/windmill-labs/windmill/issues/5722)) ([66798df](https://github.com/windmill-labs/windmill/commit/66798df38464d732864627ae27a0e51e9518c609))
|
||||
* fix date input issue with initializer ([0cd9293](https://github.com/windmill-labs/windmill/commit/0cd92932f0e0998fc30ac02065d292ec35db5cae))
|
||||
* improve agents workers handling of WHITELIST_ENVS ([7c69959](https://github.com/windmill-labs/windmill/commit/7c699598533dade9713d976d8dd90fc657ebb503))
|
||||
* improve error display of nativets exceptions ([a3c76fb](https://github.com/windmill-labs/windmill/commit/a3c76fb10cba4d18547e66e47edec84833172b64))
|
||||
* make ansible more resilient to invalid lockfiles ([b51568c](https://github.com/windmill-labs/windmill/commit/b51568c166e29ec5ee4053fb14abda2fe6d46488))
|
||||
|
||||
## [1.489.0](https://github.com/windmill-labs/windmill/compare/v1.488.0...v1.489.0) (2025-05-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* raise error if end early in flow ([#5653](https://github.com/windmill-labs/windmill/issues/5653)) ([242a565](https://github.com/windmill-labs/windmill/commit/242a5654285b0a3bf222c80e82f6861ffafed838))
|
||||
|
||||
## [1.488.0](https://github.com/windmill-labs/windmill/compare/v1.487.0...v1.488.0) (2025-05-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* handle . in interpolated args ([0ac8e47](https://github.com/windmill-labs/windmill/commit/0ac8e477d6fb7c5a7699a198fce9d18a08aff68c))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix azure object storage regression due to object_store regression ([df9f827](https://github.com/windmill-labs/windmill/commit/df9f827d103def27166a767044373bd0754285e2))
|
||||
* performance and stability improvement to fetch last deployed script ([75d9924](https://github.com/windmill-labs/windmill/commit/75d992449c845fd11c9a317d401c405e7d78e1ec))
|
||||
|
||||
## [1.487.0](https://github.com/windmill-labs/windmill/compare/v1.486.1...v1.487.0) (2025-05-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* critical alert if disk near full ([#5549](https://github.com/windmill-labs/windmill/issues/5549)) ([4fd0561](https://github.com/windmill-labs/windmill/commit/4fd056123907337efb5f5669975b337973a124cc))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ansible in agent mode can use inventory.ini ([9bdd301](https://github.com/windmill-labs/windmill/commit/9bdd301f5296fbfb631df9ff9100e92e0984ff64))
|
||||
|
||||
## [1.486.1](https://github.com/windmill-labs/windmill/compare/v1.486.0...v1.486.1) (2025-05-04)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ARG DEBIAN_IMAGE=debian:bookworm-slim
|
||||
ARG RUST_IMAGE=rust:1.85-slim-bookworm
|
||||
ARG RUST_IMAGE=rust:1.86-slim-bookworm
|
||||
|
||||
FROM ${RUST_IMAGE} AS rust_base
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['retry'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "06731936fb073169b3a1a8a9817f1e669b60edccd260625a95094b7244f5fb83"
|
||||
}
|
||||
14
backend/.sqlx/query-06db0e720dd59a7c52c0a98ea7b316237eb1a547678858c1a1e45985035b3468.json
generated
Normal file
14
backend/.sqlx/query-06db0e720dd59a7c52c0a98ea7b316237eb1a547678858c1a1e45985035b3468.json
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = flow_status - 'retry'\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "06db0e720dd59a7c52c0a98ea7b316237eb1a547678858c1a1e45985035b3468"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select path, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor, on_behalf_of_email, created_by from script where hash = $1 AND workspace_id = $2",
|
||||
"query": "select hash, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor, on_behalf_of_email, created_by, path from script where hash = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
@@ -101,6 +101,11 @@
|
||||
"ordinal": 13,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -123,8 +128,9 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "75451b6d48e4c26812ae64981d0d968b8fb0bf4374a2fccc167fa879bad7078f"
|
||||
"hash": "0937e25e89959447e7cb1816c112bbc4718cbb8ad6e2f13eae6b14f129d12936"
|
||||
}
|
||||
16
backend/.sqlx/query-0aaec91ab06753e46c595d82469924a98f28b0dead245df7248a9ccb8a5f20c3.json
generated
Normal file
16
backend/.sqlx/query-0aaec91ab06753e46c595d82469924a98f28b0dead245df7248a9ccb8a5f20c3.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0aaec91ab06753e46c595d82469924a98f28b0dead245df7248a9ccb8a5f20c3"
|
||||
}
|
||||
35
backend/.sqlx/query-0e296134f05593edc989c628c00cbb60a5446993217baffa83f843bc12a5ac73.json
generated
Normal file
35
backend/.sqlx/query-0e296134f05593edc989c628c00cbb60a5446993217baffa83f843bc12a5ac73.json
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n value->'preprocessor_module' IS NOT NULL as has_preprocessor,\n value->'preprocessor_module'->'value'->'input_transforms'->'wm_trigger' IS NOT NULL as is_v1_preprocessor,\n schema as \"schema: _\"\n FROM flow \n WHERE workspace_id = $1 \n AND path = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "is_v1_preprocessor",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "schema: _",
|
||||
"type_info": "Json"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null,
|
||||
null,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "0e296134f05593edc989c628c00cbb60a5446993217baffa83f843bc12a5ac73"
|
||||
}
|
||||
17
backend/.sqlx/query-1060c503cf8d4bb5cef9720c162b8192924b4a938d249fae92624cd55e44f488.json
generated
Normal file
17
backend/.sqlx/query-1060c503cf8d4bb5cef9720c162b8192924b4a938d249fae92624cd55e44f488.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT],\n $4\n )\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "1060c503cf8d4bb5cef9720c162b8192924b4a938d249fae92624cd55e44f488"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'iterator', 'index'],\n ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "1252ef3a652ffb99529c2ce84928197fa15efb9c78d68e3a191c01a04efe153f"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['failure_module'], $1),\n ARRAY['step'],\n $2\n )\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "173fbfd3ca2344fd08f73af75524c917d27fdb6273a35a563292b1f0701dc6ed"
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'iterator', 'index'],\n ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "17851a0710b80ffd6bebe42012a354665dff01554549ea7bbbb9953c68231296"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "1850552883e67da181d68ff5c4e1babaa2fe072900b57e78e461590a6dafb682"
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "28b42ab9c3ce0c2f05cf385e81f3b72fa7c4b3c458d52a5891a61f9c53a49c6d"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH job_result AS (\n SELECT result \n FROM v2_job_completed \n WHERE id = $1\n )\n UPDATE v2_job \n SET args = COALESCE(\n CASE \n WHEN job_result.result IS NULL THEN NULL\n WHEN jsonb_typeof(job_result.result) = 'object' \n THEN job_result.result\n WHEN jsonb_typeof(job_result.result) = 'null'\n THEN NULL\n ELSE jsonb_build_object('value', job_result.result)\n END, \n '{}'::jsonb\n ),\n preprocessed = TRUE\n FROM job_result\n WHERE v2_job.id = $2;\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "303c7e92ce23dc367d97d813415cd9aef958c15df1c0a7b02318a756cd3589e9"
|
||||
}
|
||||
15
backend/.sqlx/query-3325f8ed245b1bce27c3d9f5e62ffc14b5c8aabf5ab53384f5f2b20eafd66cb3.json
generated
Normal file
15
backend/.sqlx/query-3325f8ed245b1bce27c3d9f5e62ffc14b5c8aabf5ab53384f5f2b20eafd66cb3.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['retry'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3325f8ed245b1bce27c3d9f5e62ffc14b5c8aabf5ab53384f5f2b20eafd66cb3"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_runtime SET ping = NULL\n WHERE id = $1",
|
||||
"query": "UPDATE v2_job_runtime SET ping = NULL\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -10,5 +10,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ec1f31fd7628ea2e30995a0de1d8665831ee3e4ec3815e9ad90e886ffecba0f1"
|
||||
"hash": "38b3945c04ae58aace881ed4d6aa4da72e61eeb8e081d2e3d1ab99a4fe450350"
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker from flow WHERE path = $1 and workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "3a534b4fc36171efaa7c647f48320b59bbc414cfb92e960c174dd63fc180e187"
|
||||
}
|
||||
14
backend/.sqlx/query-3af32856235690827a8700bb2396f3ab44afe0d1a7c261a626d93fb44c00bdb7.json
generated
Normal file
14
backend/.sqlx/query-3af32856235690827a8700bb2396f3ab44afe0d1a7c261a626d93fb44c00bdb7.json
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = flow_status - 'approval_conditions'\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3af32856235690827a8700bb2396f3ab44afe0d1a7c261a626d93fb44c00bdb7"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['approval_conditions'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3d58b5861c62f0b092b6b95c17ba1dac2cbcf00db116624bd2fe27a4d0dfb436"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['cleanup_module', 'flow_jobs_to_clean'], COALESCE(flow_status->'cleanup_module'->'flow_jobs_to_clean', '[]'::jsonb) || $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3e0cdd500dffc3bd1d8374ca3cc8fd60ce778c2fece27637d9985d4650778653"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "429aef2c320a152b16fe20c1ab84aab41142897db108dc8cbc2c51abb2e30c7c"
|
||||
}
|
||||
23
backend/.sqlx/query-4455c7e8aa7616f3d547c5eb7d93c840d8aff3df4a6926f569792f69b2e9601f.json
generated
Normal file
23
backend/.sqlx/query-4455c7e8aa7616f3d547c5eb7d93c840d8aff3df4a6926f569792f69b2e9601f.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select hash from script where path = $1 AND workspace_id = $2 AND deleted = false AND lock IS not NULL AND lock_error_logs IS NULL ORDER BY created_at DESC LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "4455c7e8aa7616f3d547c5eb7d93c840d8aff3df4a6926f569792f69b2e9601f"
|
||||
}
|
||||
15
backend/.sqlx/query-4622d28e2fa09bc60b9d0c79397efe0ca030638ded82c2ffd2155cacdf36ec11.json
generated
Normal file
15
backend/.sqlx/query-4622d28e2fa09bc60b9d0c79397efe0ca030638ded82c2ffd2155cacdf36ec11.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['step'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4622d28e2fa09bc60b9d0c79397efe0ca030638ded82c2ffd2155cacdf36ec11"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2),\n ARRAY['step'],\n $3\n )\n WHERE id = $4",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4c9cf8c3176abc2b8b9a1c3f671949e16830671a458d5a73762cd8545d26172d"
|
||||
}
|
||||
23
backend/.sqlx/query-4e07dcc1ba4396ada2f1080a400ad9fad00b1d77ea44c8639b7598c5953635ff.json
generated
Normal file
23
backend/.sqlx/query-4e07dcc1ba4396ada2f1080a400ad9fad00b1d77ea44c8639b7598c5953635ff.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM script WHERE path = $1 AND workspace_id = $2 AND archived = false ORDER BY created_at DESC LIMIT 1)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "4e07dcc1ba4396ada2f1080a400ad9fad00b1d77ea44c8639b7598c5953635ff"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT \n id, \n created_at, \n trigger_kind AS \"trigger_kind: _\",\n CASE \n WHEN pg_column_size(payload) < 40000 THEN payload \n ELSE '\"WINDMILL_TOO_BIG\"'::jsonb \n END AS \"payload!: _\",\n trigger_extra AS \"trigger_extra: _\"\n FROM \n capture\n WHERE \n workspace_id = $1 \n AND path = $2 \n AND is_flow = $3 \n AND ($4::trigger_kind IS NULL OR trigger_kind = $4)\n ORDER BY \n created_at DESC\n OFFSET $5\n LIMIT $6\n ",
|
||||
"query": "\n SELECT \n id, \n created_at, \n trigger_kind AS \"trigger_kind: _\",\n CASE \n WHEN pg_column_size(main_args) < 40000 THEN main_args \n ELSE '\"WINDMILL_TOO_BIG\"'::jsonb \n END AS \"main_args!: _\",\n CASE\n WHEN pg_column_size(preprocessor_args) < 40000 THEN preprocessor_args\n ELSE '\"WINDMILL_TOO_BIG\"'::jsonb\n END AS \"preprocessor_args: _\"\n FROM \n capture\n WHERE \n workspace_id = $1 \n AND path = $2 \n AND is_flow = $3 \n AND ($4::trigger_kind IS NULL OR trigger_kind = $4)\n ORDER BY \n created_at DESC\n OFFSET $5\n LIMIT $6\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -38,12 +38,12 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "payload!: _",
|
||||
"name": "main_args!: _",
|
||||
"type_info": "Jsonb"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "trigger_extra: _",
|
||||
"name": "preprocessor_args: _",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
@@ -80,8 +80,8 @@
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
true
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "7cba31d597215a343cb0bca5b204a15fbba193262f7895c2bba90feb4215d6f3"
|
||||
"hash": "4f547c0fd54f3bc57212ce87810e35adf640d44d607e62a1fb296e38ac3fdd36"
|
||||
}
|
||||
15
backend/.sqlx/query-525a9ef57c7d9fac86cb1bf47868fa6fb782e9d589852e51530cdd1a38322a9d.json
generated
Normal file
15
backend/.sqlx/query-525a9ef57c7d9fac86cb1bf47868fa6fb782e9d589852e51530cdd1a38322a9d.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "525a9ef57c7d9fac86cb1bf47868fa6fb782e9d589852e51530cdd1a38322a9d"
|
||||
}
|
||||
15
backend/.sqlx/query-52ad0c838d19cbd9e90b8368abe71dd12655179f41f43896e7d30fdfb3ae5939.json
generated
Normal file
15
backend/.sqlx/query-52ad0c838d19cbd9e90b8368abe71dd12655179f41f43896e7d30fdfb3ae5939.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH job_result AS (\n SELECT result \n FROM v2_job_completed \n WHERE id = $1\n )\n UPDATE v2_job \n SET args = COALESCE(\n CASE \n WHEN job_result.result IS NULL THEN NULL\n WHEN jsonb_typeof(job_result.result) = 'object' \n THEN job_result.result\n WHEN jsonb_typeof(job_result.result) = 'null'\n THEN NULL\n ELSE jsonb_build_object('value', job_result.result)\n END, \n '{}'::jsonb\n ),\n preprocessed = TRUE\n FROM job_result\n WHERE v2_job.id = $2;\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "52ad0c838d19cbd9e90b8368abe71dd12655179f41f43896e7d30fdfb3ae5939"
|
||||
}
|
||||
15
backend/.sqlx/query-553108ba3c0b8d579800bc8b5a4f887d79fb4c13b60b19c4913a8db18521958c.json
generated
Normal file
15
backend/.sqlx/query-553108ba3c0b8d579800bc8b5a4f887d79fb4c13b60b19c4913a8db18521958c.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_queue q SET suspend = 0\n FROM v2_job j, v2_job_status f\n WHERE parent_job = $1\n AND f.id = j.id AND q.id = j.id\n AND suspend = $2 AND (f.flow_status->'step')::int = 0",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "553108ba3c0b8d579800bc8b5a4f887d79fb4c13b60b19c4913a8db18521958c"
|
||||
}
|
||||
16
backend/.sqlx/query-5a4fa8ff2148d92946e6ac95f70585d082435e0e79a09821a2045e3b550c3276.json
generated
Normal file
16
backend/.sqlx/query-5a4fa8ff2148d92946e6ac95f70585d082435e0e79a09821a2045e3b550c3276.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1),\n ARRAY['step'],\n $2\n )\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "5a4fa8ff2148d92946e6ac95f70585d082435e0e79a09821a2045e3b550c3276"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT id\n FROM v2_job j JOIN v2_job_queue USING (id)\n WHERE j.workspace_id = $2 AND trigger_kind = 'schedule' AND trigger = $1 AND runnable_path = $4\n AND parent_job IS NULL\n AND j.id != $3\n AND running = true",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "6513c1433dbfe03f7c778963a05d964fda13a1091a8206ee174ed3a161248126"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_leaf_jobs = JSONB_SET(coalesce(flow_leaf_jobs, '{}'::jsonb), ARRAY[$1::TEXT], $2)\n WHERE COALESCE((SELECT flow_innermost_root_job FROM v2_job WHERE id = $3), $3) = id",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6664be80f0d72ea7b8b184c5348063db3bbfea67f4a056d6e3be1fc4255cfc06"
|
||||
}
|
||||
23
backend/.sqlx/query-69db5305aadd911b06ecdc4eeb9610c0e233bca35edebe2ad1772a4a1a1d5bbe.json
generated
Normal file
23
backend/.sqlx/query-69db5305aadd911b06ecdc4eeb9610c0e233bca35edebe2ad1772a4a1a1d5bbe.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "69db5305aadd911b06ecdc4eeb9610c0e233bca35edebe2ad1772a4a1a1d5bbe"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['step'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "69ff806066a24c60188d7547a7776c160ee65eaa01b259c996f3f96ed44fcaaf"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job WHERE id = $1 AND workspace_id = $2",
|
||||
"query": "SELECT args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job WHERE id = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -19,5 +19,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "1b58b90c184ca21d777ea4e264c79aecc2361134a4817c2b9580f2680425352d"
|
||||
"hash": "6b0347da54d1b8646ece08a5ce78ed7e7c98780fef56f6ea6e1e1fd0458ae32f"
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT on_behalf_of_email, edited_by FROM flow WHERE path = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "6d36da815795d5cac2e76b4d34a7f1f9f836bd5b6866d3db26b25428d39c0b23"
|
||||
}
|
||||
25
backend/.sqlx/query-7470e7067b948509d14828c24a8725da747e6b967554eb7e088ee3a018ec1f8b.json
generated
Normal file
25
backend/.sqlx/query-7470e7067b948509d14828c24a8725da747e6b967554eb7e088ee3a018ec1f8b.json
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT id\n FROM v2_job j JOIN v2_job_queue USING (id)\n WHERE j.workspace_id = $2 AND trigger_kind = 'schedule' AND trigger = $1 AND runnable_path = $4\n AND parent_job IS NULL\n AND j.id != $3\n AND running = true",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "7470e7067b948509d14828c24a8725da747e6b967554eb7e088ee3a018ec1f8b"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['failure_module'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7b084617bf2de5ed9a657d2bd2cbc9de1246427bf0302c032f8bd26ff93313f7"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = flow_status - 'approval_conditions'\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7bd7505b008954aae6152554c1f9bb0611d0ec451b48aa1a4de309dadeb53315"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT result AS \"result!: Json<Box<RawValue>>\"\n FROM v2_job_completed WHERE id = $1 AND workspace_id = $2",
|
||||
"query": "SELECT result AS \"result!: Json<Box<RawValue>>\"\n FROM v2_job_completed WHERE id = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -19,5 +19,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "d988e91087695742d75946100cf2b7593cb8eed2a97411697819849958c022b3"
|
||||
"hash": "8780a8cd6781f86041ae8df58477913c01b5d8d27dd4251f0cabbe3e974c0b0a"
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select hash, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor, on_behalf_of_email, created_by from script where path = $1 AND workspace_id = $2 AND\n created_at = (SELECT max(created_at) FROM script WHERE path = $1 AND workspace_id = $2 AND\n deleted = false AND lock IS not NULL AND lock_error_logs IS NULL)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "concurrency_key",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "concurrent_limit",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "concurrency_time_window_s",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "cache_ttl",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "language: 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",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "priority",
|
||||
"type_info": "Int2"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "delete_after_use",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "timeout",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "89de3ff8ab32e545efcbcda05f994cb1a32c4991cbd25046282d34272587d2de"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = flow_status - 'retry'\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8be1ddb20ffd8c375b7d1ecb14bdb3a7c2f0c8f9308946b9262e14b8c584dd99"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT],\n $4\n )\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8cb755510f2cfb23bdd0d1cf66b69949549a44855529f77a530f681a6e714646"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "8f3ed45a0290cd9989f40f34775de5e8c3762597e6f55f8b9575a54ccc31e085"
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT edited_by, on_behalf_of_email FROM flow WHERE path = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "8fb2581a439c26391e66ae7fac32c6cd2932f28ab6490ace027ed3a790b2a0f7"
|
||||
}
|
||||
15
backend/.sqlx/query-8fcf755b4a57ed4ebf10a57c0c82589075c240b16d872576a048349b56f468e5.json
generated
Normal file
15
backend/.sqlx/query-8fcf755b4a57ed4ebf10a57c0c82589075c240b16d872576a048349b56f468e5.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_queue SET\n suspend = $1,\n suspend_until = now() + interval '14 day',\n running = true\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8fcf755b4a57ed4ebf10a57c0c82589075c240b16d872576a048349b56f468e5"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job WHERE id = $1",
|
||||
"query": "SELECT args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -18,5 +18,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "fdedd3909a97db5d43d9c46ff77b800b8efd647121b538deb023f96dbaac3715"
|
||||
"hash": "903cf23d6b620388c645d5b8ac7d106bb6eea8af03e350d4ba19a4aba2cb9625"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_queue q SET suspend = 0\n FROM v2_job j, v2_job_status f\n WHERE parent_job = $1\n AND f.id = j.id AND q.id = j.id\n AND suspend = $2 AND (f.flow_status->'step')::int = 0",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "90635149190c59396ca557bf1670554a1e40d0ce9cc686ad09adca0904324cd8"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n kind AS \"job_kind!: JobKind\",\n runnable_id AS \"script_hash: ScriptHash\",\n flow_status AS \"flow_status!: Json<Box<RawValue>>\",\n raw_flow AS \"raw_flow: Json<Box<RawValue>>\"\n FROM v2_job INNER JOIN v2_job_status ON v2_job.id = v2_job_status.id WHERE v2_job.id = $1 AND v2_job.workspace_id = $2 LIMIT 1",
|
||||
"query": "SELECT\n kind AS \"job_kind!: JobKind\",\n runnable_id AS \"script_hash: ScriptHash\",\n flow_status AS \"flow_status!: Json<Box<RawValue>>\",\n raw_flow AS \"raw_flow: Json<Box<RawValue>>\"\n FROM v2_job INNER JOIN v2_job_status ON v2_job.id = v2_job_status.id WHERE v2_job.id = $1 AND v2_job.workspace_id = $2 LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -63,5 +63,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "c50b6a4a6739d6df087a3b37c209e5f4b72fc27578d988155b74b05ec5df30b9"
|
||||
"hash": "92c7c961198e506426bf3f97a8ddbb34af450041c675b30b708fed3ef9e01d2d"
|
||||
}
|
||||
15
backend/.sqlx/query-94f11d70062eebce384fe0fde527f3d6cebca1aa84a6f792c2a962b798f8da22.json
generated
Normal file
15
backend/.sqlx/query-94f11d70062eebce384fe0fde527f3d6cebca1aa84a6f792c2a962b798f8da22.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['failure_module'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "94f11d70062eebce384fe0fde527f3d6cebca1aa84a6f792c2a962b798f8da22"
|
||||
}
|
||||
25
backend/.sqlx/query-96c0e34708bbba29db162e7289a942addd4581dddc88663b6c2cbae87ec205fc.json
generated
Normal file
25
backend/.sqlx/query-96c0e34708bbba29db162e7289a942addd4581dddc88663b6c2cbae87ec205fc.json
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "96c0e34708bbba29db162e7289a942addd4581dddc88663b6c2cbae87ec205fc"
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT flow.versions[array_upper(flow.versions, 1)] AS \"version!: i64\"\n FROM flow WHERE path = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "version!: i64",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "97048ce0bcabb9baecb80cde5ab3c989e1575fbd20ef22766d2887a86dce15e1"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor, on_behalf_of_email, edited_by\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",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor, on_behalf_of_email, edited_by, flow_version.id AS version\n FROM flow\n INNER JOIN flow_version\n ON flow_version.id = $3\n WHERE flow.path = $1 and flow.workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -32,12 +32,18 @@
|
||||
"ordinal": 5,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "version",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
"Text",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
@@ -46,8 +52,9 @@
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "a0833b9899833166891c5de926f78632fae1123e736d728bf92cb2de004b6826"
|
||||
"hash": "9b60fa8a1003015bc5a7cdbee9a4486b313d45347dfd9d4793d60e2760763ca3"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT \n id, \n created_at, \n trigger_kind AS \"trigger_kind: _\", \n payload AS \"payload!: _\", \n trigger_extra AS \"trigger_extra: _\"\n FROM \n capture\n WHERE \n id = $1 \n AND workspace_id = $2\n ",
|
||||
"query": "\n SELECT \n id, \n created_at, \n trigger_kind AS \"trigger_kind: _\", \n main_args AS \"main_args!: _\", \n preprocessor_args AS \"preprocessor_args: _\"\n FROM \n capture\n WHERE \n id = $1 \n AND workspace_id = $2\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -38,12 +38,12 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "payload!: _",
|
||||
"name": "main_args!: _",
|
||||
"type_info": "Jsonb"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "trigger_extra: _",
|
||||
"name": "preprocessor_args: _",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
@@ -61,5 +61,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "6781ba76dfce321dca4634566496ea5d698ac09d8264e35dfaa4cd8edc9e8414"
|
||||
"hash": "9c50e3a136a8ee3ec56e083f26d3a960b89e02ec40b292f3b5198baf2a1d3dbf"
|
||||
}
|
||||
23
backend/.sqlx/query-9dec888d4b0666d1843fbbc4fb2475fd947f047a9965bc110d7338208b77783d.json
generated
Normal file
23
backend/.sqlx/query-9dec888d4b0666d1843fbbc4fb2475fd947f047a9965bc110d7338208b77783d.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT flow_version.id from flow\n INNER 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": "id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9dec888d4b0666d1843fbbc4fb2475fd947f047a9965bc110d7338208b77783d"
|
||||
}
|
||||
23
backend/.sqlx/query-a10ec229d7ed89f563b6b33e70e8ede5135a849e7b9108c37bfd90990a4be780.json
generated
Normal file
23
backend/.sqlx/query-a10ec229d7ed89f563b6b33e70e8ede5135a849e7b9108c37bfd90990a4be780.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'iterator', 'index'],\n ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "a10ec229d7ed89f563b6b33e70e8ede5135a849e7b9108c37bfd90990a4be780"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2)\n WHERE id = $3\n RETURNING flow_status AS \"flow_status: Json<Box<RawValue>>\"",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2)\n WHERE id = $3\n RETURNING flow_status AS \"flow_status: Json<Box<RawValue>>\"",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -20,5 +20,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "30216cf02e972f961b7cc6054050fdc984be118df1ad68f7263c84e058bb1266"
|
||||
"hash": "a3debece1a4171881431640f6af264d402d32e2b6ce925d1ebf1f60f3b688207"
|
||||
}
|
||||
16
backend/.sqlx/query-a3f315fdae54e51b56b0681fab2bbff779a4a62d129916dd4c3054b45e0b654e.json
generated
Normal file
16
backend/.sqlx/query-a3f315fdae54e51b56b0681fab2bbff779a4a62d129916dd4c3054b45e0b654e.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'approvers'], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a3f315fdae54e51b56b0681fab2bbff779a4a62d129916dd4c3054b45e0b654e"
|
||||
}
|
||||
70
backend/.sqlx/query-a8bcae108af1eda6efe3a4b8c6f8807bc464a81c0883e68f5a69b89b94b0b34b.json
generated
Normal file
70
backend/.sqlx/query-a8bcae108af1eda6efe3a4b8c6f8807bc464a81c0883e68f5a69b89b94b0b34b.json
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT has_preprocessor, language as \"language: _\", content, schema as \"schema: _\" FROM script WHERE workspace_id = $1 AND hash = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "language: _",
|
||||
"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",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "content",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "schema: _",
|
||||
"type_info": "Json"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "a8bcae108af1eda6efe3a4b8c6f8807bc464a81c0883e68f5a69b89b94b0b34b"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO parallel_monitor_lock (parent_flow_id, job_id)\n VALUES ($1, $2)",
|
||||
"query": "INSERT INTO parallel_monitor_lock (parent_flow_id, job_id)\n VALUES ($1, $2)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -11,5 +11,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4507c3907bf49f93f6c17956d9cf9495f4538b20ce0299acde7578386db4278c"
|
||||
"hash": "aa4ecf6b7ab078544c280957ad6614c4ccd1bc9b4695ca56f56ba0899b23562f"
|
||||
}
|
||||
16
backend/.sqlx/query-aed8bd751c3e988f422216e74acfb77dc03469355d2a0da0b2d6b4aeeea37d3e.json
generated
Normal file
16
backend/.sqlx/query-aed8bd751c3e988f422216e74acfb77dc03469355d2a0da0b2d6b4aeeea37d3e.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_leaf_jobs = JSONB_SET(coalesce(flow_leaf_jobs, '{}'::jsonb), ARRAY[$1::TEXT], $2)\n WHERE COALESCE((SELECT flow_innermost_root_job FROM v2_job WHERE id = $3), $3) = id",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "aed8bd751c3e988f422216e74acfb77dc03469355d2a0da0b2d6b4aeeea37d3e"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1),\n ARRAY['step'],\n $2\n )\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "af925931f3217bbd32313678989ad1a66bbd8dacd12dea36608cc20197df358f"
|
||||
}
|
||||
15
backend/.sqlx/query-b01160fe44d69834ac08bbf60feacb3e3caa02a04b084da44cdcb9103794b39e.json
generated
Normal file
15
backend/.sqlx/query-b01160fe44d69834ac08bbf60feacb3e3caa02a04b084da44cdcb9103794b39e.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['cleanup_module', 'flow_jobs_to_clean'], COALESCE(flow_status->'cleanup_module'->'flow_jobs_to_clean', '[]'::jsonb) || $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b01160fe44d69834ac08bbf60feacb3e3caa02a04b084da44cdcb9103794b39e"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT result, id\n FROM v2_job_completed\n WHERE id = ANY($1) AND workspace_id = $2",
|
||||
"query": "SELECT result, id\n FROM v2_job_completed\n WHERE id = ANY($1) AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -25,5 +25,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "47e6b25cc092ec8718a6581c76aca10b275653e10ea4aa17a8ef5091ca09294a"
|
||||
"hash": "b1c96c527c4b263b5155d689eb88894ea93f0eaba37874f828a733062af17640"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job\n WHERE id = $1",
|
||||
"query": "SELECT\n args AS \"args: Json<HashMap<String, Box<RawValue>>>\"\n FROM v2_job\n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -18,5 +18,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "597b148ff09a1e0f369bb04781ee4e429ebce64a4d5c16b0f136142ad213cdb1"
|
||||
"hash": "b41fa341e65ee348f468ed04ac1160770b19c0a00cd333abc48b29c54f863149"
|
||||
}
|
||||
17
backend/.sqlx/query-bbc2c0769bf833f4e95bfc7908897ecbfe662efb13ffdd8ee3f1930bff4cd9c4.json
generated
Normal file
17
backend/.sqlx/query-bbc2c0769bf833f4e95bfc7908897ecbfe662efb13ffdd8ee3f1930bff4cd9c4.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2),\n ARRAY['step'],\n $3\n )\n WHERE id = $4",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "bbc2c0769bf833f4e95bfc7908897ecbfe662efb13ffdd8ee3f1930bff4cd9c4"
|
||||
}
|
||||
15
backend/.sqlx/query-bcfe877749ff7b944fef302ea37481b170c221349a793c9608c4ccd52ba8a5af.json
generated
Normal file
15
backend/.sqlx/query-bcfe877749ff7b944fef302ea37481b170c221349a793c9608c4ccd52ba8a5af.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['approval_conditions'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "bcfe877749ff7b944fef302ea37481b170c221349a793c9608c4ccd52ba8a5af"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH suspend AS (\n UPDATE v2_job_queue SET suspend = $2, suspend_until = now() + $3\n WHERE id = $4\n RETURNING id\n ) UPDATE v2_job_status SET flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', flow_status->>'step'::TEXT],\n $1\n ) WHERE id = (SELECT id FROM suspend)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Int4",
|
||||
"Interval",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c202f6fbae6a727f88f3ac692985c70e6ebc68e4a16d02e4e36b79f3cfb1c661"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(JSONB_SET(flow_status, ARRAY['retry'], $1), ARRAY['modules', $3::TEXT, 'failed_retries'], $4)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c71e12ec9d0054dd5605a4ea2ef77fa54ce686da9c93790420a91a0735589ac7"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor, on_behalf_of_email, edited_by\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": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "c794ff5e14429a1bc56f5e70cfd10e2160d1b7e123c7ab226dc77d1789f164f9"
|
||||
}
|
||||
16
backend/.sqlx/query-cd79f4dc6a426f1c4c19c2a86dc877a6d5bc5771b27d9e208a219a63add200f3.json
generated
Normal file
16
backend/.sqlx/query-cd79f4dc6a426f1c4c19c2a86dc877a6d5bc5771b27d9e208a219a63add200f3.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['failure_module'], $1),\n ARRAY['step'],\n $2\n )\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "cd79f4dc6a426f1c4c19c2a86dc877a6d5bc5771b27d9e208a219a63add200f3"
|
||||
}
|
||||
25
backend/.sqlx/query-d6db1103fee4bad6831656d77a28254c9a832b4f660ec755f4fa14f6f7bb3353.json
generated
Normal file
25
backend/.sqlx/query-d6db1103fee4bad6831656d77a28254c9a832b4f660ec755f4fa14f6f7bb3353.json
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET\n flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'iterator', 'index'],\n ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n )\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "d6db1103fee4bad6831656d77a28254c9a832b4f660ec755f4fa14f6f7bb3353"
|
||||
}
|
||||
17
backend/.sqlx/query-de2a213bc5a08d08bcd52ad630559cc0f16d7286c3f07c27d962258022f0e04d.json
generated
Normal file
17
backend/.sqlx/query-de2a213bc5a08d08bcd52ad630559cc0f16d7286c3f07c27d962258022f0e04d.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(JSONB_SET(flow_status, ARRAY['retry'], $1), ARRAY['modules', $3::TEXT, 'failed_retries'], $4)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "de2a213bc5a08d08bcd52ad630559cc0f16d7286c3f07c27d962258022f0e04d"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_queue SET\n suspend = $1,\n suspend_until = now() + interval '14 day',\n running = true\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "defd99dd2427cdc54bb662d1ba3a1aea7f410ef204ec3465f4fb6c9acd256c95"
|
||||
}
|
||||
17
backend/.sqlx/query-e3f545460bf317c3e2f34f4cbd12740141eb8b5ed07c090ae9356a970caeadd0.json
generated
Normal file
17
backend/.sqlx/query-e3f545460bf317c3e2f34f4cbd12740141eb8b5ed07c090ae9356a970caeadd0.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH suspend AS (\n UPDATE v2_job_queue SET suspend = $2, suspend_until = now() + $3\n WHERE id = $4\n RETURNING id\n ) UPDATE v2_job_status SET flow_status = JSONB_SET(\n flow_status,\n ARRAY['modules', flow_status->>'step'::TEXT],\n $1\n ) WHERE id = (SELECT id FROM suspend)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Int4",
|
||||
"Interval",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e3f545460bf317c3e2f34f4cbd12740141eb8b5ed07c090ae9356a970caeadd0"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO \n capture (\n workspace_id, path, is_flow, trigger_kind, payload, trigger_extra, created_by\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7\n )\n ",
|
||||
"query": "\n INSERT INTO \n capture (\n workspace_id, path, is_flow, trigger_kind, main_args, preprocessor_args, created_by\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7\n )\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -34,5 +34,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f9f7f31390f8ea1f4facd8e6a888886ea136f2327169bf93f126e2ef130d0946"
|
||||
"hash": "eac595e19e5c8e70f1514ef29dec35c7342ac9a814c73f6290e1d6ebd3a55423"
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, on_behalf_of_email, created_by from script where hash = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "concurrency_key",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "concurrent_limit",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "concurrency_time_window_s",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "cache_ttl",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "language: 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",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "priority",
|
||||
"type_info": "Int2"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "delete_after_use",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "timeout",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ec7836df5f9056ec70015800b7f4feaeb1b671120f5f8c98fca8c89c6587fc35"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'approvers'], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f3c78cb67379f9407f1f32ce3387184d7f4fcb04c07a8e2f07c5effc10f8fd5c"
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker, on_behalf_of_email, edited_by from flow WHERE path = $1 and workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "on_behalf_of_email",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "f44f1a794ab217be05a9feb21e57b3409d9166a028701981cfc280aaab3c4436"
|
||||
}
|
||||
531
backend/Cargo.lock
generated
531
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.486.1"
|
||||
version = "1.490.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -32,7 +32,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.486.1"
|
||||
version = "1.490.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -96,6 +96,9 @@ java = ["windmill-worker/java"]
|
||||
all_languages = [ "python", "deno_core", "rust", "mysql", "oracledb", "mssql", "bigquery", "csharp", "nu", "php", "java"]
|
||||
|
||||
|
||||
[patch.crates-io]
|
||||
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7" }
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
tokio.workspace = true
|
||||
@@ -334,7 +337,7 @@ nkeys = "0.4.4"
|
||||
nu-parser = { version = "0.101.0", default-features = false }
|
||||
|
||||
datafusion = "47.0.0"
|
||||
object_store = { version = "0.12.0", features = ["aws", "azure"] }
|
||||
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7", features = ["aws", "azure"] }
|
||||
openidconnect = { version = "4.0.0-rc.1" }
|
||||
aws-config = "^1"
|
||||
aws-sdk-sqs = "1.57.0"
|
||||
|
||||
@@ -1 +1 @@
|
||||
868ccad87afb804fe22818ecd3d5a091199bcdbf
|
||||
4dc1f25f4fcc013334d4cc1d07cbe60a22b56d1f
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE capture RENAME COLUMN preprocessor_args to trigger_extra;
|
||||
ALTER TABLE capture RENAME COLUMN main_args to payload;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE capture RENAME COLUMN trigger_extra to preprocessor_args;
|
||||
ALTER TABLE capture RENAME COLUMN payload to main_args;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add down migration script here
|
||||
DROP TRIGGER script_update_trigger ON script;
|
||||
DROP TRIGGER flow_update_trigger ON flow_version;
|
||||
DROP FUNCTION notify_runnable_version_change();
|
||||
@@ -0,0 +1,22 @@
|
||||
-- Add up migration script here
|
||||
CREATE OR REPLACE FUNCTION notify_runnable_version_change()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
source_type TEXT;
|
||||
BEGIN
|
||||
source_type := TG_ARGV[0];
|
||||
|
||||
PERFORM pg_notify('notify_runnable_version_change', NEW.workspace_id || ':' || source_type || ':' || NEW.path);
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER script_update_trigger
|
||||
AFTER UPDATE OF lock ON script
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION notify_runnable_version_change('script');
|
||||
|
||||
CREATE TRIGGER flow_update_trigger
|
||||
AFTER INSERT ON flow_version
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION notify_runnable_version_change('flow');
|
||||
@@ -506,7 +506,7 @@ fn one_of_label(members: &Vec<TsTypeElement>) -> Option<String> {
|
||||
let Expr::Ident(Ident { sym, .. }) = &**key else {
|
||||
return None;
|
||||
};
|
||||
if sym != "label" {
|
||||
if sym != "label" && sym != "kind" {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ fn wrap_sig(r: anyhow::Result<MainArgSignature>) -> String {
|
||||
|
||||
#[cfg(feature = "ts-parser")]
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_deno(code: &str, main_override: Option<String>, skip_params: Option<bool>) -> String {
|
||||
pub fn parse_deno(code: &str, main_override: Option<String>) -> String {
|
||||
wrap_sig(windmill_parser_ts::parse_deno_signature(
|
||||
code,
|
||||
false,
|
||||
|
||||
@@ -787,6 +787,29 @@ Windmill Community Edition {GIT_VERSION}
|
||||
tracing::info!("Workspace premium change detected, invalidating workspace premium cache: {}", workspace_id);
|
||||
windmill_common::workspaces::IS_PREMIUM_CACHE.remove(workspace_id);
|
||||
},
|
||||
"notify_runnable_version_change" => {
|
||||
let payload = n.payload();
|
||||
tracing::info!("Runnable version change detected: {}", payload);
|
||||
match payload.split(':').collect::<Vec<&str>>().as_slice() {
|
||||
[workspace_id, source_type, path] => {
|
||||
let key = (workspace_id.to_string(), path.to_string());
|
||||
match source_type {
|
||||
&"script" => {
|
||||
windmill_common::DEPLOYED_SCRIPT_HASH_CACHE.remove(&key);
|
||||
}
|
||||
&"flow" => {
|
||||
windmill_common::FLOW_VERSION_CACHE.remove(&key);
|
||||
},
|
||||
_ => {
|
||||
tracing::warn!("Unknown runnable version change payload: {}", payload);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
tracing::warn!("Unknown runnable version change payload: {}", payload);
|
||||
}
|
||||
}
|
||||
},
|
||||
"notify_global_setting_change" => {
|
||||
tracing::info!("Global setting change detected: {}", n.payload());
|
||||
match n.payload() {
|
||||
@@ -1108,6 +1131,7 @@ async fn listen_pg(url: &str) -> Option<PgListener> {
|
||||
"notify_global_setting_change",
|
||||
"notify_webhook_change",
|
||||
"notify_workspace_envs_change",
|
||||
"notify_runnable_version_change",
|
||||
];
|
||||
#[cfg(feature = "cloud")]
|
||||
channels.push("notify_workspace_premium_change");
|
||||
|
||||
@@ -28,10 +28,10 @@ use windmill_api::{
|
||||
SCIM_TOKEN,
|
||||
};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
use windmill_common::ee::{jobs_waiting_alerts, worker_groups_alerts};
|
||||
#[cfg(feature = "enterprise")]
|
||||
use windmill_common::ee::low_disk_alerts;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use windmill_common::ee::{jobs_waiting_alerts, worker_groups_alerts};
|
||||
|
||||
#[cfg(feature = "oauth2")]
|
||||
use windmill_common::global_settings::OAUTH_SETTING;
|
||||
@@ -60,13 +60,9 @@ use windmill_common::{
|
||||
server::load_smtp_config,
|
||||
tracing_init::JSON_FMT,
|
||||
users::truncate_token,
|
||||
utils::empty_string_as_none,
|
||||
utils::{now_from_db, rd_string, report_critical_error, Mode},
|
||||
utils::{empty_as_none, now_from_db, rd_string, report_critical_error, Mode},
|
||||
worker::{
|
||||
load_worker_config, reload_custom_tags_setting, store_pull_query,
|
||||
store_suspended_pull_query, update_min_version, Connection, DEFAULT_TAGS_PER_WORKSPACE,
|
||||
DEFAULT_TAGS_WORKSPACES, INDEXER_CONFIG, SCRIPT_TOKEN_EXPIRY, SMTP_CONFIG, TMP_DIR,
|
||||
WORKER_CONFIG, WORKER_GROUP,
|
||||
load_env_vars, load_init_bash_from_env, load_whitelist_env_vars_from_env, load_worker_config, reload_custom_tags_setting, store_pull_query, store_suspended_pull_query, update_min_version, Connection, WorkerConfig, DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, INDEXER_CONFIG, SCRIPT_TOKEN_EXPIRY, SMTP_CONFIG, TMP_DIR, WORKER_CONFIG, WORKER_GROUP
|
||||
},
|
||||
KillpillSender, BASE_URL, CRITICAL_ALERTS_ON_DB_OVERSIZE, CRITICAL_ALERT_MUTE_UI_ENABLED,
|
||||
CRITICAL_ERROR_CHANNELS, DB, DEFAULT_HUB_BASE_URL, HUB_BASE_URL, JOB_RETENTION_SECS,
|
||||
@@ -203,10 +199,23 @@ pub async fn initial_load(
|
||||
}
|
||||
Connection::Http(_) => {
|
||||
// TODO: reload worker config from http
|
||||
WORKER_CONFIG.write().await.worker_tags = DECODED_AGENT_TOKEN
|
||||
.as_ref()
|
||||
.map(|x| x.tags.clone())
|
||||
.unwrap_or_default();
|
||||
let mut config = WORKER_CONFIG.write().await;
|
||||
*config = WorkerConfig {
|
||||
worker_tags: DECODED_AGENT_TOKEN
|
||||
.as_ref()
|
||||
.map(|x| x.tags.clone())
|
||||
.unwrap_or_default(),
|
||||
env_vars: load_env_vars(
|
||||
load_whitelist_env_vars_from_env(),
|
||||
&std::collections::HashMap::new(),
|
||||
),
|
||||
priority_tags_sorted: vec![],
|
||||
dedicated_worker: None,
|
||||
init_bash: load_init_bash_from_env(),
|
||||
cache_clear: None,
|
||||
additional_python_paths: None,
|
||||
pip_local_dependencies: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,13 +280,13 @@ struct OtelSetting {
|
||||
metrics_enabled: Option<bool>,
|
||||
logs_enabled: Option<bool>,
|
||||
tracing_enabled: Option<bool>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_exporter_otlp_endpoint: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_exporter_otlp_headers: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_exporter_otlp_protocol: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_exporter_otlp_compression: Option<String>,
|
||||
}
|
||||
|
||||
@@ -2213,7 +2222,9 @@ pub async fn reload_critical_error_channels_setting(conn: &DB) -> error::Result<
|
||||
pub async fn reload_critical_alerts_on_db_oversize(conn: &DB) -> error::Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct DBOversize {
|
||||
#[serde(default)]
|
||||
enabled: bool,
|
||||
#[serde(default)]
|
||||
value: f32,
|
||||
}
|
||||
let db_oversize_value =
|
||||
|
||||
@@ -4687,6 +4687,7 @@ mod job_payload {
|
||||
path: "f/system/hello_with_nodes_flow".to_string(),
|
||||
dedicated_worker: None,
|
||||
apply_preprocessor: false,
|
||||
version: 1443253234253454,
|
||||
})
|
||||
.run_until_complete(&db, port)
|
||||
.await
|
||||
@@ -4731,6 +4732,7 @@ mod job_payload {
|
||||
path: "f/system/hello_with_preprocessor".to_string(),
|
||||
dedicated_worker: None,
|
||||
apply_preprocessor: true,
|
||||
version: 1443253234253456,
|
||||
})
|
||||
.run_until_complete_with(db, port, |id| async move {
|
||||
let job = sqlx::query!("SELECT preprocessed FROM v2_job WHERE id = $1", id)
|
||||
@@ -4798,6 +4800,7 @@ mod job_payload {
|
||||
path: "f/system/hello_with_nodes_flow".to_string(),
|
||||
dedicated_worker: None,
|
||||
apply_preprocessor: true,
|
||||
version: 1443253234253454,
|
||||
})
|
||||
.run_until_complete(&db, port)
|
||||
.await
|
||||
|
||||
@@ -2750,6 +2750,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
|
||||
pub expr: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub skip_if_stopped: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub error_message: Option<String>
|
||||
}
|
||||
impl From<&FlowModuleStopAfterAllItersIf> for FlowModuleStopAfterAllItersIf {
|
||||
fn from(value: &FlowModuleStopAfterAllItersIf) -> Self {
|
||||
@@ -2761,6 +2763,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
|
||||
pub expr: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub skip_if_stopped: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub error_message: Option<String>
|
||||
}
|
||||
impl From<&FlowModuleStopAfterIf> for FlowModuleStopAfterIf {
|
||||
fn from(value: &FlowModuleStopAfterIf) -> Self {
|
||||
|
||||
@@ -1824,6 +1824,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
|
||||
pub expr: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub skip_if_stopped: Option<bool>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub error_message: Option<String>
|
||||
}
|
||||
impl From<&FlowModuleStopAfterIf> for FlowModuleStopAfterIf {
|
||||
fn from(value: &FlowModuleStopAfterIf) -> Self {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.486.1
|
||||
version: 1.490.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
@@ -16539,8 +16539,8 @@ components:
|
||||
properties:
|
||||
trigger_kind:
|
||||
$ref: "#/components/schemas/CaptureTriggerKind"
|
||||
payload: {}
|
||||
trigger_extra: {}
|
||||
main_args: {}
|
||||
preprocessor_args: {}
|
||||
id:
|
||||
type: integer
|
||||
created_at:
|
||||
@@ -16548,7 +16548,8 @@ components:
|
||||
format: date-time
|
||||
required:
|
||||
- trigger_kind
|
||||
- payload
|
||||
- main_args
|
||||
- preprocessor_args
|
||||
- id
|
||||
- created_at
|
||||
CaptureConfig:
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(feature = "parquet")]
|
||||
use crate::job_helpers_ee::get_workspace_s3_resource;
|
||||
use axum::{
|
||||
extract::{FromRequest, FromRequestParts, Multipart, Query, Request},
|
||||
http::{HeaderMap, Uri},
|
||||
@@ -9,139 +7,318 @@ use axum::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use http::{header::CONTENT_TYPE, request::Parts, StatusCode};
|
||||
#[cfg(feature = "parquet")]
|
||||
use object_store::{Attribute, Attributes};
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::value::RawValue;
|
||||
use sqlx::types::JsonRawValue;
|
||||
#[cfg(feature = "parquet")]
|
||||
use windmill_common::s3_helpers::build_object_store_client;
|
||||
use windmill_common::{error::Error, worker::to_raw_value, DB};
|
||||
use windmill_queue::PushArgsOwned;
|
||||
use windmill_queue::{PushArgsOwned, TriggerKind};
|
||||
|
||||
use crate::db::ApiAuthed;
|
||||
#[cfg(feature = "parquet")]
|
||||
use crate::job_helpers_ee::{get_random_file_name, upload_file_internal};
|
||||
use crate::{
|
||||
db::ApiAuthed,
|
||||
trigger_helpers::{get_runnable_format, RunnableFormat, RunnableFormatVersion, RunnableId},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WebhookArgs {
|
||||
pub args: PushArgsOwned,
|
||||
pub multipart: Option<Multipart>,
|
||||
pub wrap_body: Option<bool>,
|
||||
#[derive(Debug)]
|
||||
pub enum RawBody {
|
||||
Json(String),
|
||||
CEJson(String),
|
||||
Text(String),
|
||||
Xml(String),
|
||||
UrlEncoded(Bytes),
|
||||
Multipart(Multipart),
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl WebhookArgs {
|
||||
#[derive(Clone, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Body {
|
||||
HashMap(HashMap<String, Box<RawValue>>),
|
||||
NoHashMap(Box<RawValue>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct WebhookArgsMetadata {
|
||||
pub raw_string: Option<String>,
|
||||
pub headers: HashMap<String, Box<RawValue>>,
|
||||
pub method: http::Method,
|
||||
pub query: HashMap<String, Box<RawValue>>,
|
||||
pub query_wrap_body: bool,
|
||||
pub query_use_raw: bool,
|
||||
}
|
||||
|
||||
pub struct RawWebhookArgs {
|
||||
pub body: RawBody,
|
||||
pub metadata: WebhookArgsMetadata,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WebhookArgs {
|
||||
pub body: Body,
|
||||
pub metadata: WebhookArgsMetadata,
|
||||
}
|
||||
|
||||
// capture
|
||||
//
|
||||
|
||||
impl RawWebhookArgs {
|
||||
#[cfg(not(feature = "parquet"))]
|
||||
pub async fn to_push_args_owned(
|
||||
self,
|
||||
pub async fn process_multipart(
|
||||
_multipart: Multipart,
|
||||
_authed: &ApiAuthed,
|
||||
_db: &DB,
|
||||
_w_id: &str,
|
||||
) -> Result<PushArgsOwned, Error> {
|
||||
if self.multipart.is_some() {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"multipart/form-data requires the parquet feature"
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(self.args)
|
||||
) -> Result<HashMap<String, Box<RawValue>>, Error> {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"multipart/form-data requires the parquet feature"
|
||||
)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "parquet")]
|
||||
pub async fn to_push_args_owned(
|
||||
mut self,
|
||||
async fn process_multipart(
|
||||
mut multipart: Multipart,
|
||||
authed: &ApiAuthed,
|
||||
db: &DB,
|
||||
w_id: &str,
|
||||
) -> Result<HashMap<String, Box<RawValue>>, Error> {
|
||||
use crate::job_helpers_ee::{
|
||||
get_random_file_name, get_workspace_s3_resource, upload_file_internal,
|
||||
};
|
||||
use futures::TryStreamExt;
|
||||
use object_store::{Attribute, Attributes};
|
||||
use windmill_common::s3_helpers::build_object_store_client;
|
||||
|
||||
let (_, s3_resource) = get_workspace_s3_resource(authed, db, None, "", w_id, None).await?;
|
||||
|
||||
if let Some(s3_resource) = s3_resource {
|
||||
let s3_client = build_object_store_client(&s3_resource).await?;
|
||||
|
||||
let mut body = HashMap::new();
|
||||
let mut files = HashMap::new();
|
||||
|
||||
while let Some(field) = multipart.next_field().await.map_err(|e| {
|
||||
Error::BadRequest(format!("Error reading multipart field: {}", e.body_text()))
|
||||
})? {
|
||||
if let Some(name) = field.name().map(|x| x.to_string()) {
|
||||
if let Some(content_type) = field.content_type() {
|
||||
let ext = field
|
||||
.file_name()
|
||||
.map(|x| x.split('.').last())
|
||||
.flatten()
|
||||
.map(|x| x.to_string());
|
||||
|
||||
let file_key = get_random_file_name(ext);
|
||||
|
||||
let options = Attributes::from_iter(vec![
|
||||
(Attribute::ContentType, content_type.to_string()),
|
||||
(
|
||||
Attribute::ContentDisposition,
|
||||
if let Some(filename) = field.file_name() {
|
||||
format!("inline; filename=\"{}\"", filename)
|
||||
} else {
|
||||
"inline".to_string()
|
||||
},
|
||||
),
|
||||
])
|
||||
.into();
|
||||
|
||||
let bytes_stream = field
|
||||
.into_stream()
|
||||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err));
|
||||
|
||||
upload_file_internal(s3_client.clone(), &file_key, bytes_stream, options)
|
||||
.await?;
|
||||
|
||||
files.entry(name).or_insert(vec![]).push(serde_json::json!({
|
||||
"s3": &file_key
|
||||
}));
|
||||
} else {
|
||||
body.insert(name, to_raw_value(&field.text().await.unwrap_or_default()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (k, v) in files {
|
||||
body.insert(k, to_raw_value(&v));
|
||||
}
|
||||
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::BadRequest(format!(
|
||||
"You need to connect your workspace to an S3 bucket to use multipart/form-data"
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn process_args(
|
||||
self,
|
||||
authed: &ApiAuthed,
|
||||
db: &DB,
|
||||
w_id: &str,
|
||||
force_use_raw: Option<bool>,
|
||||
) -> Result<WebhookArgs, Error> {
|
||||
let use_raw = force_use_raw.unwrap_or(self.metadata.query_use_raw);
|
||||
|
||||
match self.body {
|
||||
RawBody::Multipart(multipart) => {
|
||||
let body = Self::process_multipart(multipart, authed, db, w_id).await?;
|
||||
Ok(WebhookArgs { body: Body::HashMap(body), metadata: self.metadata })
|
||||
}
|
||||
RawBody::Empty => {
|
||||
let mut metadata = self.metadata;
|
||||
if use_raw {
|
||||
metadata.raw_string = Some("".to_string());
|
||||
}
|
||||
Ok(WebhookArgs { body: Body::HashMap(HashMap::new()), metadata })
|
||||
}
|
||||
RawBody::Text(s) | RawBody::Xml(s) => Ok(WebhookArgs {
|
||||
body: Body::HashMap(HashMap::new()),
|
||||
metadata: WebhookArgsMetadata { raw_string: Some(s), ..self.metadata },
|
||||
}),
|
||||
RawBody::UrlEncoded(bytes) => {
|
||||
let mut metadata = self.metadata;
|
||||
if use_raw {
|
||||
let raw_string = String::from_utf8(bytes.to_vec())
|
||||
.map_err(|e| Error::BadRequest(format!("invalid utf8: {}", e)))?;
|
||||
metadata.raw_string = Some(raw_string);
|
||||
}
|
||||
let payload: HashMap<String, Option<String>> = serde_urlencoded::from_bytes(&bytes)
|
||||
.map_err(|e| Error::BadRequest(format!("invalid urlencoded data: {}", e)))?;
|
||||
let payload = payload
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, to_raw_value(&v)))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
Ok(WebhookArgs { body: Body::HashMap(payload), metadata })
|
||||
}
|
||||
RawBody::Json(s) => WebhookArgs::from_json(self.metadata, use_raw, s).await,
|
||||
RawBody::CEJson(s) => WebhookArgs::from_ce_json(self.metadata, use_raw, s).await,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn to_main_args(
|
||||
self,
|
||||
authed: &ApiAuthed,
|
||||
db: &DB,
|
||||
w_id: &str,
|
||||
) -> Result<PushArgsOwned, Error> {
|
||||
use futures::TryStreamExt;
|
||||
let args = self.process_args(authed, db, w_id, None).await?;
|
||||
args.to_main_args()
|
||||
}
|
||||
|
||||
if let Some(mut multipart) = self.multipart {
|
||||
{
|
||||
let (_, s3_resource) =
|
||||
get_workspace_s3_resource(authed, db, None, "", w_id, None).await?;
|
||||
pub async fn to_args_from_runnable(
|
||||
self,
|
||||
authed: &ApiAuthed,
|
||||
db: &DB,
|
||||
w_id: &str,
|
||||
runnable_id: RunnableId,
|
||||
skip_preprocessor: Option<bool>,
|
||||
) -> Result<PushArgsOwned, Error> {
|
||||
let args = self.process_args(authed, db, w_id, None).await?;
|
||||
args.to_args_from_runnable(db, w_id, runnable_id, skip_preprocessor)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s3_resource) = s3_resource {
|
||||
let s3_client = build_object_store_client(&s3_resource).await?;
|
||||
#[derive(Serialize)]
|
||||
struct WebhookPreprocessorEvent {
|
||||
kind: String,
|
||||
body: Box<RawValue>,
|
||||
raw_string: Option<String>,
|
||||
headers: HashMap<String, Box<RawValue>>,
|
||||
query: HashMap<String, Box<RawValue>>,
|
||||
}
|
||||
|
||||
let mut body = HashMap::new();
|
||||
let mut files = HashMap::new();
|
||||
impl WebhookArgs {
|
||||
pub fn to_main_args(self) -> Result<PushArgsOwned, Error> {
|
||||
self.to_args_from_format(RunnableFormat {
|
||||
has_preprocessor: false,
|
||||
version: RunnableFormatVersion::V2,
|
||||
})
|
||||
}
|
||||
|
||||
while let Some(field) = multipart.next_field().await.map_err(|e| {
|
||||
Error::BadRequest(format!(
|
||||
"Error reading multipart field: {}",
|
||||
e.body_text()
|
||||
))
|
||||
})? {
|
||||
if let Some(name) = field.name().map(|x| x.to_string()) {
|
||||
if let Some(content_type) = field.content_type() {
|
||||
let ext = field
|
||||
.file_name()
|
||||
.map(|x| x.split('.').last())
|
||||
.flatten()
|
||||
.map(|x| x.to_string());
|
||||
pub async fn to_args_from_runnable(
|
||||
self,
|
||||
db: &DB,
|
||||
w_id: &str,
|
||||
runnable_id: RunnableId,
|
||||
skip_preprocessor: Option<bool>,
|
||||
) -> Result<PushArgsOwned, Error> {
|
||||
if skip_preprocessor.unwrap_or(false) {
|
||||
self.to_main_args()
|
||||
} else {
|
||||
let runnable_format =
|
||||
get_runnable_format(runnable_id, w_id, db, &TriggerKind::Webhook).await?;
|
||||
|
||||
let file_key = get_random_file_name(ext);
|
||||
self.to_args_from_format(runnable_format)
|
||||
}
|
||||
}
|
||||
|
||||
let options = Attributes::from_iter(vec![
|
||||
(Attribute::ContentType, content_type.to_string()),
|
||||
(
|
||||
Attribute::ContentDisposition,
|
||||
if let Some(filename) = field.file_name() {
|
||||
format!("inline; filename=\"{}\"", filename)
|
||||
} else {
|
||||
"inline".to_string()
|
||||
},
|
||||
),
|
||||
])
|
||||
.into();
|
||||
pub fn to_args_from_format(
|
||||
self,
|
||||
runnable_format: RunnableFormat,
|
||||
) -> Result<PushArgsOwned, Error> {
|
||||
match runnable_format {
|
||||
RunnableFormat { has_preprocessor: true, version: RunnableFormatVersion::V2 } => {
|
||||
let mut args = HashMap::new();
|
||||
|
||||
let bytes_stream = field.into_stream().map_err(|err| {
|
||||
std::io::Error::new(std::io::ErrorKind::Other, err)
|
||||
});
|
||||
args.insert(
|
||||
"event".to_string(),
|
||||
to_raw_value(&WebhookPreprocessorEvent {
|
||||
kind: "webhook".to_string(),
|
||||
body: to_raw_value(&self.body),
|
||||
raw_string: self.metadata.raw_string,
|
||||
headers: self.metadata.headers,
|
||||
query: self.metadata.query,
|
||||
}),
|
||||
);
|
||||
|
||||
upload_file_internal(
|
||||
s3_client.clone(),
|
||||
&file_key,
|
||||
bytes_stream,
|
||||
options,
|
||||
)
|
||||
.await?;
|
||||
Ok(PushArgsOwned { args, extra: None })
|
||||
}
|
||||
RunnableFormat { has_preprocessor, .. } => {
|
||||
let mut extra = HashMap::new();
|
||||
|
||||
files.entry(name).or_insert(vec![]).push(serde_json::json!({
|
||||
"s3": &file_key
|
||||
}));
|
||||
} else {
|
||||
body.insert(
|
||||
name,
|
||||
to_raw_value(&field.text().await.unwrap_or_default()),
|
||||
);
|
||||
}
|
||||
let WebhookArgsMetadata { query, query_wrap_body, headers, raw_string, .. } =
|
||||
self.metadata;
|
||||
|
||||
for (k, v) in headers {
|
||||
extra.insert(k, v);
|
||||
}
|
||||
|
||||
for (k, v) in query {
|
||||
extra.insert(k, v);
|
||||
}
|
||||
|
||||
if let Some(raw_string) = raw_string {
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&raw_string));
|
||||
}
|
||||
|
||||
if has_preprocessor {
|
||||
// if has preprocessor, it has to be v1
|
||||
extra.insert(
|
||||
"wm_trigger".to_string(),
|
||||
to_raw_value(&serde_json::json!({
|
||||
"kind": "webhook",
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
let extra = if extra.is_empty() { None } else { Some(extra) };
|
||||
|
||||
match self.body {
|
||||
Body::HashMap(mut body) => {
|
||||
if query_wrap_body {
|
||||
body = HashMap::from([("body".to_string(), to_raw_value(&body))]);
|
||||
}
|
||||
Ok(PushArgsOwned { args: body, extra })
|
||||
}
|
||||
|
||||
for (k, v) in files {
|
||||
body.insert(k, to_raw_value(&v));
|
||||
Body::NoHashMap(args) => {
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert("body".to_string(), args);
|
||||
Ok(PushArgsOwned { args: hm, extra })
|
||||
}
|
||||
|
||||
if self.wrap_body.unwrap_or(false) {
|
||||
self.args
|
||||
.args
|
||||
.insert("body".to_string(), to_raw_value(&body));
|
||||
} else {
|
||||
self.args.args.extend(body);
|
||||
}
|
||||
|
||||
return Ok(self.args);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(Error::BadRequest(format!(
|
||||
"You need to connect your workspace to an S3 bucket to use multipart/form-data"
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(self.args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,26 +343,36 @@ async fn req_to_string<S: Send + Sync>(
|
||||
pub async fn try_from_request_body<S>(
|
||||
request: Request,
|
||||
_state: &S,
|
||||
use_raw: Option<bool>,
|
||||
wrap_body: Option<bool>,
|
||||
) -> Result<WebhookArgs, Response>
|
||||
is_http_trigger: bool,
|
||||
) -> Result<RawWebhookArgs, Response>
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
let (content_type, mut extra, use_raw, wrap_body) = {
|
||||
let (content_type, metadata) = {
|
||||
let headers_map = request.headers();
|
||||
let content_type_header = headers_map.get(CONTENT_TYPE);
|
||||
let content_type = content_type_header.and_then(|value| value.to_str().ok());
|
||||
let uri = request.uri();
|
||||
let query = Query::<RequestQuery>::try_from_uri(uri).unwrap().0;
|
||||
let mut extra = build_extra(&headers_map, query.include_header);
|
||||
let query_decode = DecodeQueries::from_uri(uri);
|
||||
let request_query = Query::<RequestQuery>::try_from_uri(uri).unwrap().0;
|
||||
let headers = build_headers(&headers_map, request_query.include_header, is_http_trigger);
|
||||
let query_decode = DecodeQueries::from_uri(uri, is_http_trigger);
|
||||
let mut query = HashMap::new();
|
||||
if let Some(DecodeQueries(queries)) = query_decode {
|
||||
extra.extend(queries);
|
||||
query.extend(queries);
|
||||
}
|
||||
let raw = query.raw.unwrap_or(use_raw.unwrap_or(false));
|
||||
let wrap_body = query.wrap_body.unwrap_or(wrap_body.unwrap_or(false));
|
||||
(content_type, extra, raw, wrap_body)
|
||||
let raw = !is_http_trigger && request_query.raw.unwrap_or(false);
|
||||
let wrap_body = !is_http_trigger && request_query.wrap_body.unwrap_or(false);
|
||||
(
|
||||
content_type,
|
||||
WebhookArgsMetadata {
|
||||
headers,
|
||||
query,
|
||||
method: request.method().clone(),
|
||||
raw_string: None,
|
||||
query_wrap_body: wrap_body,
|
||||
query_use_raw: raw,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
let no_content_type = content_type.is_none();
|
||||
@@ -194,33 +381,19 @@ where
|
||||
.await
|
||||
.map_err(IntoResponse::into_response)?;
|
||||
if no_content_type && bytes.is_empty() {
|
||||
if use_raw {
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&"".to_string()));
|
||||
}
|
||||
let mut args = HashMap::new();
|
||||
if wrap_body {
|
||||
args.insert("body".to_string(), to_raw_value(&serde_json::json!({})));
|
||||
}
|
||||
return Ok(WebhookArgs {
|
||||
args: PushArgsOwned { extra: Some(extra), args: args },
|
||||
..Default::default()
|
||||
});
|
||||
Ok(RawWebhookArgs { body: RawBody::Empty, metadata })
|
||||
} else {
|
||||
let str = String::from_utf8(bytes.to_vec())
|
||||
.map_err(|e| Error::BadRequest(format!("invalid utf8: {}", e)).into_response())?;
|
||||
Ok(RawWebhookArgs { body: RawBody::Json(str), metadata })
|
||||
}
|
||||
let str = String::from_utf8(bytes.to_vec())
|
||||
.map_err(|e| Error::BadRequest(format!("invalid utf8: {}", e)).into_response())?;
|
||||
|
||||
PushArgsOwned::from_json(extra, use_raw, wrap_body, str)
|
||||
.await
|
||||
.map(|args| WebhookArgs { args, ..Default::default() })
|
||||
} else if content_type
|
||||
.unwrap()
|
||||
.starts_with("application/cloudevents+json")
|
||||
{
|
||||
let str = req_to_string(request, _state).await?;
|
||||
|
||||
PushArgsOwned::from_ce_json(extra, use_raw, str)
|
||||
.await
|
||||
.map(|args| WebhookArgs { args, ..Default::default() })
|
||||
Ok(RawWebhookArgs { body: RawBody::CEJson(str), metadata })
|
||||
} else if content_type
|
||||
.unwrap()
|
||||
.starts_with("application/cloudevents-batch+json")
|
||||
@@ -231,11 +404,7 @@ where
|
||||
)
|
||||
} else if content_type.unwrap().starts_with("text/plain") {
|
||||
let str = req_to_string(request, _state).await?;
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&str));
|
||||
Ok(WebhookArgs {
|
||||
args: PushArgsOwned { extra: Some(extra), args: HashMap::new() },
|
||||
..Default::default()
|
||||
})
|
||||
Ok(RawWebhookArgs { body: RawBody::Text(str), metadata })
|
||||
} else if content_type
|
||||
.unwrap()
|
||||
.starts_with("application/x-www-form-urlencoded")
|
||||
@@ -244,58 +413,32 @@ where
|
||||
.await
|
||||
.map_err(IntoResponse::into_response)?;
|
||||
|
||||
if use_raw {
|
||||
let raw_string = String::from_utf8(bytes.to_vec())
|
||||
.map_err(|e| Error::BadRequest(format!("invalid utf8: {}", e)).into_response())?;
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&raw_string));
|
||||
}
|
||||
|
||||
let payload: HashMap<String, Option<String>> = serde_urlencoded::from_bytes(&bytes)
|
||||
.map_err(|e| {
|
||||
Error::BadRequest(format!("invalid urlencoded data: {}", e)).into_response()
|
||||
})?;
|
||||
let payload = payload
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, to_raw_value(&v)))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
return Ok(WebhookArgs {
|
||||
args: PushArgsOwned { extra: Some(extra), args: payload },
|
||||
..Default::default()
|
||||
});
|
||||
Ok(RawWebhookArgs { body: RawBody::UrlEncoded(bytes), metadata })
|
||||
} else if content_type.unwrap().starts_with("application/xml")
|
||||
|| content_type.unwrap().starts_with("text/xml")
|
||||
{
|
||||
let str = req_to_string(request, _state).await?;
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&str));
|
||||
Ok(WebhookArgs {
|
||||
args: PushArgsOwned { extra: Some(extra), args: HashMap::new() },
|
||||
..Default::default()
|
||||
})
|
||||
Ok(RawWebhookArgs { body: RawBody::Xml(str), metadata })
|
||||
} else if content_type.unwrap().starts_with("multipart/form-data") {
|
||||
let multipart = Multipart::from_request(request, _state)
|
||||
.await
|
||||
.map_err(IntoResponse::into_response)?;
|
||||
|
||||
Ok(WebhookArgs {
|
||||
args: PushArgsOwned { extra: Some(extra), args: HashMap::new() },
|
||||
multipart: Some(multipart),
|
||||
wrap_body: Some(wrap_body),
|
||||
})
|
||||
Ok(RawWebhookArgs { body: RawBody::Multipart(multipart), metadata })
|
||||
} else {
|
||||
Err(StatusCode::UNSUPPORTED_MEDIA_TYPE.into_response())
|
||||
}
|
||||
}
|
||||
|
||||
#[axum::async_trait]
|
||||
impl<S> FromRequest<S, axum::body::Body> for WebhookArgs
|
||||
impl<S> FromRequest<S, axum::body::Body> for RawWebhookArgs
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = Response;
|
||||
|
||||
async fn from_request(request: Request, _state: &S) -> Result<Self, Self::Rejection> {
|
||||
let args = try_from_request_body(request, _state, None, None).await?;
|
||||
let args = try_from_request_body(request, _state, false).await?;
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
@@ -309,27 +452,37 @@ lazy_static::lazy_static! {
|
||||
.collect()).unwrap_or_default();
|
||||
}
|
||||
|
||||
pub fn build_extra(
|
||||
pub fn build_headers(
|
||||
headers: &HeaderMap,
|
||||
include_header: Option<String>,
|
||||
is_http_trigger: bool,
|
||||
) -> HashMap<String, Box<RawValue>> {
|
||||
let mut args = HashMap::new();
|
||||
let whitelist = include_header
|
||||
.map(|s| s.split(",").map(|s| s.to_string()).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
let mut selected_headers = HashMap::new();
|
||||
|
||||
whitelist
|
||||
.iter()
|
||||
.chain(INCLUDE_HEADERS.iter())
|
||||
.for_each(|h| {
|
||||
if let Some(v) = headers.get(h) {
|
||||
args.insert(
|
||||
h.to_string().to_lowercase().replace('-', "_"),
|
||||
to_raw_value(&v.to_str().unwrap().to_string()),
|
||||
);
|
||||
}
|
||||
});
|
||||
args
|
||||
if is_http_trigger {
|
||||
for (k, v) in headers.iter() {
|
||||
selected_headers.insert(
|
||||
k.to_string(),
|
||||
to_raw_value(&v.to_str().unwrap_or("").to_string()),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let whitelist = include_header
|
||||
.map(|s| s.split(",").map(|s| s.to_string()).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
whitelist
|
||||
.iter()
|
||||
.chain(INCLUDE_HEADERS.iter())
|
||||
.for_each(|h| {
|
||||
if let Some(v) = headers.get(h) {
|
||||
selected_headers.insert(
|
||||
h.to_string().to_lowercase().replace('-', "_"),
|
||||
to_raw_value(&v.to_str().unwrap_or("").to_string()),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
selected_headers
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -347,37 +500,49 @@ where
|
||||
type Rejection = Response;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||||
Ok(DecodeQueries::from_uri(&parts.uri).unwrap_or_else(|| DecodeQueries(HashMap::new())))
|
||||
Ok(DecodeQueries::from_uri(&parts.uri, false)
|
||||
.unwrap_or_else(|| DecodeQueries(HashMap::new())))
|
||||
}
|
||||
}
|
||||
|
||||
impl DecodeQueries {
|
||||
pub fn from_uri(uri: &Uri) -> Option<Self> {
|
||||
pub fn from_uri(uri: &Uri, is_http_trigger: bool) -> Option<Self> {
|
||||
let query = uri.query();
|
||||
if query.is_none() {
|
||||
return None;
|
||||
}
|
||||
let query = query.unwrap();
|
||||
let include_query = serde_urlencoded::from_str::<IncludeQuery>(query)
|
||||
.map(|x| x.include_query)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_default();
|
||||
let parse_query_args = include_query
|
||||
.split(",")
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
let mut args = HashMap::new();
|
||||
if !parse_query_args.is_empty() {
|
||||
if is_http_trigger {
|
||||
let queries =
|
||||
serde_urlencoded::from_str::<HashMap<String, String>>(query).unwrap_or_default();
|
||||
parse_query_args.iter().for_each(|h| {
|
||||
if let Some(v) = queries.get(h) {
|
||||
args.insert(h.to_string(), to_raw_value(v));
|
||||
}
|
||||
});
|
||||
Some(DecodeQueries(
|
||||
queries
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, to_raw_value(&v)))
|
||||
.collect(),
|
||||
))
|
||||
} else {
|
||||
let include_query = serde_urlencoded::from_str::<IncludeQuery>(query)
|
||||
.map(|x| x.include_query)
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_default();
|
||||
let parse_query_args = include_query
|
||||
.split(",")
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
let mut args = HashMap::new();
|
||||
if !parse_query_args.is_empty() {
|
||||
let queries = serde_urlencoded::from_str::<HashMap<String, String>>(query)
|
||||
.unwrap_or_default();
|
||||
parse_query_args.iter().for_each(|h| {
|
||||
if let Some(v) = queries.get(h) {
|
||||
args.insert(h.to_string(), to_raw_value(v));
|
||||
}
|
||||
});
|
||||
}
|
||||
Some(DecodeQueries(args))
|
||||
}
|
||||
Some(DecodeQueries(args))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,69 +579,50 @@ fn restructure_cloudevents_metadata(
|
||||
}
|
||||
}
|
||||
|
||||
trait PushArgsOwnedExt: Sized {
|
||||
impl WebhookArgs {
|
||||
async fn from_json(
|
||||
extra: HashMap<String, Box<RawValue>>,
|
||||
use_raw: bool,
|
||||
force_wrap_body: bool,
|
||||
str: String,
|
||||
) -> Result<Self, Response>;
|
||||
|
||||
async fn from_ce_json(
|
||||
extra: HashMap<String, Box<RawValue>>,
|
||||
mut metadata: WebhookArgsMetadata,
|
||||
use_raw: bool,
|
||||
str: String,
|
||||
) -> Result<Self, Response>;
|
||||
}
|
||||
|
||||
impl PushArgsOwnedExt for PushArgsOwned {
|
||||
async fn from_json(
|
||||
mut extra: HashMap<String, Box<RawValue>>,
|
||||
use_raw: bool,
|
||||
force_wrap_body: bool,
|
||||
str: String,
|
||||
) -> Result<Self, Response> {
|
||||
) -> Result<Self, Error> {
|
||||
if use_raw {
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&str));
|
||||
metadata.raw_string = Some(str.clone());
|
||||
}
|
||||
|
||||
let wrap_body = force_wrap_body || str.len() > 0 && str.chars().next().unwrap() != '{';
|
||||
let no_hashmap = str.len() > 0 && str.chars().next().unwrap() != '{';
|
||||
|
||||
if wrap_body {
|
||||
if no_hashmap {
|
||||
let args = serde_json::from_str::<Option<Box<RawValue>>>(&str)
|
||||
.map_err(|e| Error::BadRequest(format!("invalid json: {}", e)).into_response())?
|
||||
.map_err(|e| Error::BadRequest(format!("invalid json: {}", e)))?
|
||||
.unwrap_or_else(|| to_raw_value(&serde_json::Value::Null));
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert("body".to_string(), args);
|
||||
Ok(PushArgsOwned { extra: Some(extra), args: hm })
|
||||
|
||||
Ok(Self { body: Body::NoHashMap(args), metadata })
|
||||
} else {
|
||||
let hm = serde_json::from_str::<Option<HashMap<String, Box<JsonRawValue>>>>(&str)
|
||||
.map_err(|e| Error::BadRequest(format!("invalid json: {}", e)).into_response())?
|
||||
.map_err(|e| Error::BadRequest(format!("invalid json: {}", e)))?
|
||||
.unwrap_or_else(HashMap::new);
|
||||
Ok(PushArgsOwned { extra: Some(extra), args: hm })
|
||||
Ok(Self { body: Body::HashMap(hm), metadata })
|
||||
}
|
||||
}
|
||||
|
||||
async fn from_ce_json(
|
||||
mut extra: HashMap<String, Box<RawValue>>,
|
||||
mut metadata: WebhookArgsMetadata,
|
||||
use_raw: bool,
|
||||
str: String,
|
||||
) -> Result<Self, Response> {
|
||||
) -> Result<Self, Error> {
|
||||
if use_raw {
|
||||
extra.insert("raw_string".to_string(), to_raw_value(&str));
|
||||
metadata.raw_string = Some(str.clone());
|
||||
}
|
||||
|
||||
let hm = serde_json::from_str::<HashMap<String, Box<RawValue>>>(&str).map_err(|e| {
|
||||
Error::BadRequest(format!("invalid cloudevents+json: {}", e)).into_response()
|
||||
})?;
|
||||
let hm = restructure_cloudevents_metadata(hm).map_err(|e| e.into_response())?;
|
||||
Ok(PushArgsOwned { extra: Some(extra), args: hm })
|
||||
let hm = serde_json::from_str::<HashMap<String, Box<RawValue>>>(&str)
|
||||
.map_err(|e| Error::BadRequest(format!("invalid cloudevents+json: {}", e)))?;
|
||||
let hm = restructure_cloudevents_metadata(hm)?;
|
||||
Ok(Self { body: Body::HashMap(hm), metadata })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -514,24 +660,35 @@ mod tests {
|
||||
"data" : 1.5
|
||||
}
|
||||
"#;
|
||||
let extra = HashMap::new();
|
||||
let metadata = WebhookArgsMetadata::default();
|
||||
|
||||
let a1 = PushArgsOwned::from_ce_json(extra.clone(), false, r1.to_string())
|
||||
let a1 = WebhookArgs::from_ce_json(metadata.clone(), false, r1.to_string())
|
||||
.await
|
||||
.expect("Failed to parse the cloudevent");
|
||||
let a2 = PushArgsOwned::from_ce_json(extra.clone(), false, r2.to_string())
|
||||
let a2 = WebhookArgs::from_ce_json(metadata.clone(), false, r2.to_string())
|
||||
.await
|
||||
.expect("Failed to parse the cloudevent");
|
||||
|
||||
a1.args.get("WEBHOOK__METADATA__").expect(
|
||||
"CloudEvents should generate a neighboring `webhook-metadata` field in PushArgs",
|
||||
);
|
||||
assert_eq!(
|
||||
a2.args
|
||||
.get("body")
|
||||
.expect("Cloud events with a data field with no wrapping curly brackets should be inside of a `body` field in PushArgs")
|
||||
.to_string(),
|
||||
"1.5"
|
||||
);
|
||||
match a1.body {
|
||||
Body::HashMap(body) => {
|
||||
body.get("WEBHOOK__METADATA__").expect(
|
||||
"CloudEvents should generate a neighboring `webhook-metadata` field in PushArgs",
|
||||
);
|
||||
}
|
||||
_ => panic!("Expected a HashMap"),
|
||||
}
|
||||
|
||||
match a2.body {
|
||||
Body::HashMap(body) => {
|
||||
assert_eq!(
|
||||
body
|
||||
.get("body")
|
||||
.expect("Cloud events with a data field with no wrapping curly brackets should be inside of a `body` field in PushArgs")
|
||||
.to_string(),
|
||||
"1.5"
|
||||
);
|
||||
}
|
||||
_ => panic!("Expected a HashMap"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
#[cfg(feature = "http_trigger")]
|
||||
use {
|
||||
crate::{
|
||||
args::try_from_request_body,
|
||||
http_triggers::{build_http_trigger_extra, HttpMethod},
|
||||
},
|
||||
crate::http_trigger_args::{HttpMethod, RawHttpTriggerArgs},
|
||||
axum::response::{IntoResponse, Response},
|
||||
std::collections::HashMap,
|
||||
};
|
||||
@@ -33,7 +30,7 @@ use {
|
||||
axum::extract::Request,
|
||||
http::HeaderMap,
|
||||
serde::de::DeserializeOwned,
|
||||
windmill_common::{error::Error, utils::empty_string_as_none},
|
||||
windmill_common::{error::Error, utils::empty_as_none},
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "enterprise", feature = "kafka"))]
|
||||
@@ -56,8 +53,9 @@ use {
|
||||
};
|
||||
|
||||
use crate::{
|
||||
args::WebhookArgs,
|
||||
args::RawWebhookArgs,
|
||||
db::{ApiAuthed, DB},
|
||||
trigger_helpers::{RunnableFormat, RunnableFormatVersion},
|
||||
users::fetch_api_authed,
|
||||
utils::RunnableKind,
|
||||
};
|
||||
@@ -164,9 +162,9 @@ pub struct SqsTriggerConfig {
|
||||
pub struct GcpTriggerConfig {
|
||||
pub gcp_resource_path: String,
|
||||
pub subscription_mode: SubscriptionMode,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
pub subscription_id: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_string_as_none")]
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
pub base_endpoint: Option<String>,
|
||||
#[serde(flatten)]
|
||||
pub create_update: Option<CreateUpdateConfig>,
|
||||
@@ -496,8 +494,8 @@ struct Capture {
|
||||
id: i64,
|
||||
created_at: chrono::DateTime<chrono::Utc>,
|
||||
trigger_kind: TriggerKind,
|
||||
payload: SqlxJson<Box<serde_json::value::RawValue>>,
|
||||
trigger_extra: Option<SqlxJson<Box<serde_json::value::RawValue>>>,
|
||||
main_args: SqlxJson<Box<serde_json::value::RawValue>>,
|
||||
preprocessor_args: Option<SqlxJson<Box<serde_json::value::RawValue>>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -525,10 +523,13 @@ async fn list_captures(
|
||||
created_at,
|
||||
trigger_kind AS "trigger_kind: _",
|
||||
CASE
|
||||
WHEN pg_column_size(payload) < 40000 THEN payload
|
||||
WHEN pg_column_size(main_args) < 40000 THEN main_args
|
||||
ELSE '"WINDMILL_TOO_BIG"'::jsonb
|
||||
END AS "payload!: _",
|
||||
trigger_extra AS "trigger_extra: _"
|
||||
END AS "main_args!: _",
|
||||
CASE
|
||||
WHEN pg_column_size(preprocessor_args) < 40000 THEN preprocessor_args
|
||||
ELSE '"WINDMILL_TOO_BIG"'::jsonb
|
||||
END AS "preprocessor_args: _"
|
||||
FROM
|
||||
capture
|
||||
WHERE
|
||||
@@ -570,8 +571,8 @@ async fn get_capture(
|
||||
id,
|
||||
created_at,
|
||||
trigger_kind AS "trigger_kind: _",
|
||||
payload AS "payload!: _",
|
||||
trigger_extra AS "trigger_extra: _"
|
||||
main_args AS "main_args!: _",
|
||||
preprocessor_args AS "preprocessor_args: _"
|
||||
FROM
|
||||
capture
|
||||
WHERE
|
||||
@@ -820,15 +821,15 @@ pub async fn insert_capture_payload(
|
||||
path: &str,
|
||||
is_flow: bool,
|
||||
trigger_kind: &TriggerKind,
|
||||
payload: PushArgsOwned,
|
||||
trigger_extra: Option<Box<RawValue>>,
|
||||
main_args: PushArgsOwned,
|
||||
preprocessor_args: PushArgsOwned,
|
||||
owner: &str,
|
||||
) -> Result<()> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO
|
||||
capture (
|
||||
workspace_id, path, is_flow, trigger_kind, payload, trigger_extra, created_by
|
||||
workspace_id, path, is_flow, trigger_kind, main_args, preprocessor_args, created_by
|
||||
)
|
||||
VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
@@ -838,11 +839,9 @@ pub async fn insert_capture_payload(
|
||||
path,
|
||||
is_flow,
|
||||
trigger_kind as &TriggerKind,
|
||||
SqlxJson(to_raw_value(&PushArgs {
|
||||
args: &payload.args,
|
||||
extra: payload.extra
|
||||
})) as SqlxJson<Box<RawValue>>,
|
||||
trigger_extra.map(SqlxJson) as Option<SqlxJson<Box<RawValue>>>,
|
||||
SqlxJson(PushArgs { args: &main_args.args, extra: main_args.extra }) as SqlxJson<PushArgs>,
|
||||
SqlxJson(PushArgs { args: &preprocessor_args.args, extra: preprocessor_args.extra })
|
||||
as SqlxJson<PushArgs>,
|
||||
owner,
|
||||
)
|
||||
.execute(db)
|
||||
@@ -856,7 +855,7 @@ pub async fn insert_capture_payload(
|
||||
async fn webhook_payload(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, runnable_kind, path)): Path<(String, RunnableKind, StripPath)>,
|
||||
args: WebhookArgs,
|
||||
args: RawWebhookArgs,
|
||||
) -> Result<StatusCode> {
|
||||
let (owner, email) = get_active_capture_owner_and_email(
|
||||
&db,
|
||||
@@ -868,7 +867,15 @@ async fn webhook_payload(
|
||||
.await?;
|
||||
|
||||
let authed = fetch_api_authed(owner.clone(), email, &w_id, &db, None).await?;
|
||||
let args = args.to_push_args_owned(&authed, &db, &w_id).await?;
|
||||
|
||||
let args = args.process_args(&authed, &db, &w_id, None).await?;
|
||||
|
||||
let preprocessor_args = args.clone().to_args_from_format(RunnableFormat {
|
||||
has_preprocessor: true,
|
||||
version: RunnableFormatVersion::V2,
|
||||
})?;
|
||||
|
||||
let main_args = args.to_main_args()?;
|
||||
|
||||
insert_capture_payload(
|
||||
&db,
|
||||
@@ -876,12 +883,8 @@ async fn webhook_payload(
|
||||
&path.to_path(),
|
||||
matches!(runnable_kind, RunnableKind::Flow),
|
||||
&TriggerKind::Webhook,
|
||||
args,
|
||||
Some(to_raw_value(&serde_json::json!({
|
||||
"wm_trigger": {
|
||||
"kind": "webhook",
|
||||
}
|
||||
}))),
|
||||
main_args,
|
||||
preprocessor_args,
|
||||
&owner,
|
||||
)
|
||||
.await?;
|
||||
@@ -897,6 +900,8 @@ async fn gcp_payload(
|
||||
headers: HeaderMap,
|
||||
request: Request,
|
||||
) -> Result<StatusCode> {
|
||||
use crate::{gcp_triggers_ee::GcpTrigger, trigger_helpers::TriggerJobArgs};
|
||||
|
||||
let is_flow = matches!(runnable_kind, RunnableKind::Flow);
|
||||
let (gcp_trigger_config, owner, email): (GcpTriggerConfig, _, _) =
|
||||
get_capture_trigger_config_and_owner(&db, &w_id, &path, is_flow, &TriggerKind::Gcp).await?;
|
||||
@@ -918,9 +923,9 @@ async fn gcp_payload(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (args, extra) = process_google_push_request(headers, request).await?;
|
||||
let (payload, gcp) = process_google_push_request(headers, request).await?;
|
||||
|
||||
let payload = PushArgsOwned { args, extra: None };
|
||||
let (main_args, preprocessor_args) = GcpTrigger::build_capture_payloads(payload, gcp);
|
||||
|
||||
let _ = insert_capture_payload(
|
||||
&db,
|
||||
@@ -928,8 +933,8 @@ async fn gcp_payload(
|
||||
&path,
|
||||
is_flow,
|
||||
&TriggerKind::Gcp,
|
||||
payload,
|
||||
Some(to_raw_value(&extra)),
|
||||
main_args,
|
||||
preprocessor_args,
|
||||
&owner,
|
||||
)
|
||||
.await?;
|
||||
@@ -941,10 +946,7 @@ async fn gcp_payload(
|
||||
async fn http_payload(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, runnable_kind, path, route_path)): Path<(String, RunnableKind, String, StripPath)>,
|
||||
Query(query): Query<HashMap<String, String>>,
|
||||
method: http::Method,
|
||||
headers: HeaderMap,
|
||||
request: Request,
|
||||
args: RawHttpTriggerArgs,
|
||||
) -> std::result::Result<StatusCode, Response> {
|
||||
let path = path.replace(".", "/");
|
||||
let is_flow = matches!(runnable_kind, RunnableKind::Flow);
|
||||
@@ -954,20 +956,17 @@ async fn http_payload(
|
||||
.await
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
let args = try_from_request_body(
|
||||
request,
|
||||
&(),
|
||||
http_trigger_config.raw_string,
|
||||
http_trigger_config.wrap_body,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
let authed = fetch_api_authed(owner.clone(), email, &w_id, &db, None)
|
||||
.await
|
||||
.map_err(|e| e.into_response())?;
|
||||
let mut args = args
|
||||
.to_push_args_owned(&authed, &db, &w_id)
|
||||
|
||||
let args = args
|
||||
.process_args(
|
||||
&authed,
|
||||
&db,
|
||||
&w_id,
|
||||
http_trigger_config.raw_string.unwrap_or(false),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
@@ -985,31 +984,23 @@ async fn http_payload(
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect();
|
||||
|
||||
let extra = args.extra.get_or_insert_with(HashMap::new);
|
||||
let preprocessor_args = args
|
||||
.clone()
|
||||
.to_v2_preprocessor_args(&http_trigger_config.route_path, &route_path, ¶ms)
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
extra.insert(
|
||||
"wm_trigger".to_string(),
|
||||
build_http_trigger_extra(
|
||||
&http_trigger_config.route_path,
|
||||
route_path,
|
||||
&method,
|
||||
¶ms,
|
||||
&query,
|
||||
&headers,
|
||||
)
|
||||
.await,
|
||||
);
|
||||
let main_args = args
|
||||
.to_main_args(http_trigger_config.wrap_body.unwrap_or(false))
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
let extra = Some(to_raw_value(&extra));
|
||||
args.extra = None;
|
||||
insert_capture_payload(
|
||||
&db,
|
||||
&w_id,
|
||||
&path,
|
||||
is_flow,
|
||||
&TriggerKind::Http,
|
||||
args,
|
||||
extra,
|
||||
main_args,
|
||||
preprocessor_args,
|
||||
&owner,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -48,6 +48,9 @@ lazy_static::lazy_static! {
|
||||
(20250102145420, include_str!(
|
||||
"../../migrations/20250102145420_more_captures.up.sql"
|
||||
).replace("public.", "")),
|
||||
(20250429211554, include_str!(
|
||||
"../../migrations/20250429211554_create_indices_on_queue.up.sql"
|
||||
).replace("public.", "")),
|
||||
(20241006144414, include_str!(
|
||||
"../../custom_migrations/grant_all_current_schema.sql"
|
||||
).to_string()),
|
||||
@@ -231,7 +234,7 @@ pub async fn migrate(db: &DB) -> Result<Option<JoinHandle<()>>, Error> {
|
||||
{
|
||||
Ok(_) => Ok(()),
|
||||
Err(sqlx::migrate::MigrateError::VersionMissing(e)) => {
|
||||
tracing::error!("Database had been applied more migrations than this container.
|
||||
tracing::error!("Database had been applied more migrations than this container.
|
||||
This usually mean than another container on a more recent version migrated the database and this one is on an earlier version.
|
||||
Please update the container to latest. Not critical, but may cause issues if migration introduced a breaking change. Version missing: {e:#}");
|
||||
custom_migrator.unlock().await?;
|
||||
@@ -433,7 +436,7 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
|
||||
r#"
|
||||
LOCK TABLE v2_job_completed IN ACCESS EXCLUSIVE MODE;
|
||||
DROP FUNCTION IF EXISTS v2_job_completed_before_insert CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_completed_before_update CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_completed_before_update CASCADE;
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
@@ -445,7 +448,7 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
|
||||
LOCK TABLE v2_job_queue IN ACCESS EXCLUSIVE MODE;
|
||||
DROP FUNCTION IF EXISTS v2_job_queue_after_insert CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_queue_before_insert CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_queue_before_update CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_queue_before_update CASCADE;
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
@@ -456,7 +459,7 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
|
||||
r#"
|
||||
LOCK TABLE v2_job_runtime IN ACCESS EXCLUSIVE MODE;
|
||||
DROP FUNCTION IF EXISTS v2_job_runtime_before_insert CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_runtime_before_update CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_runtime_before_update CASCADE;
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
@@ -467,7 +470,7 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
|
||||
r#"
|
||||
LOCK TABLE v2_job_status IN ACCESS EXCLUSIVE MODE;
|
||||
DROP FUNCTION IF EXISTS v2_job_status_before_insert CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_status_before_update CASCADE;
|
||||
DROP FUNCTION IF EXISTS v2_job_status_before_update CASCADE;
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -1345,7 +1345,7 @@ mod tests {
|
||||
}),
|
||||
stop_after_if: Some(StopAfterIf {
|
||||
expr: "foo = 'bar'".to_string(),
|
||||
skip_if_stopped: false,
|
||||
..Default::default()
|
||||
}),
|
||||
stop_after_all_iters_if: None,
|
||||
summary: None,
|
||||
@@ -1374,7 +1374,7 @@ mod tests {
|
||||
}),
|
||||
stop_after_if: Some(StopAfterIf {
|
||||
expr: "previous.isEmpty()".to_string(),
|
||||
skip_if_stopped: false,
|
||||
..Default::default()
|
||||
}),
|
||||
stop_after_all_iters_if: None,
|
||||
summary: None,
|
||||
@@ -1402,7 +1402,7 @@ mod tests {
|
||||
.into(),
|
||||
stop_after_if: Some(StopAfterIf {
|
||||
expr: "previous.isEmpty()".to_string(),
|
||||
skip_if_stopped: false,
|
||||
..Default::default()
|
||||
}),
|
||||
stop_after_all_iters_if: None,
|
||||
summary: None,
|
||||
@@ -1452,7 +1452,8 @@ mod tests {
|
||||
},
|
||||
"stop_after_if": {
|
||||
"expr": "foo = 'bar'",
|
||||
"skip_if_stopped": false
|
||||
"skip_if_stopped": false,
|
||||
"error_message": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1474,6 +1475,7 @@ mod tests {
|
||||
"stop_after_if": {
|
||||
"expr": "previous.isEmpty()",
|
||||
"skip_if_stopped": false,
|
||||
"error_message": null
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1486,7 +1488,8 @@ mod tests {
|
||||
},
|
||||
"stop_after_if": {
|
||||
"expr": "previous.isEmpty()",
|
||||
"skip_if_stopped": false
|
||||
"skip_if_stopped": false,
|
||||
"error_message": null
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user