Skip to content

Commit

Permalink
fix: load large args of previous runs dynamically
Browse files Browse the repository at this point in the history
  • Loading branch information
HugoCasa committed May 7, 2024
1 parent 1795522 commit 3b67fe8
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 13 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions backend/windmill-api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7271,6 +7271,26 @@ paths:
items:
$ref: "#/components/schemas/Input"

/w/{workspace}/inputs/{jobOrInputId}/args:
get:
summary: Get args from history or saved input
operationId: getArgsFromHistoryOrSavedInput
tags:
- input
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: jobOrInputId
in: path
required: true
schema:
type: string
responses:
"200":
description: args
content:
application/json:
schema: {}

/w/{workspace}/inputs/list:
get:
summary: List saved Inputs for a Runnable
Expand Down
31 changes: 28 additions & 3 deletions backend/windmill-api/src/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use windmill_common::{
error::JsonResult,
jobs::JobKind,
scripts::to_i64,
utils::{paginate, Pagination},
utils::{not_found_if_none, paginate, Pagination},
};
pub fn workspaced_service() -> Router {
Router::new()
Expand All @@ -34,6 +34,10 @@ pub fn workspaced_service() -> Router {
.route("/create", post(create_input))
.route("/update", post(update_input))
.route("/delete/:id", post(delete_input))
.route(
"/:job_or_input_id/args",
get(get_args_from_history_or_saved_input),
)
}

#[derive(Debug, sqlx::FromRow, Serialize, Deserialize)]
Expand Down Expand Up @@ -123,7 +127,7 @@ async fn get_input_history(
let mut tx = user_db.begin(&authed).await?;

let sql = &format!(
"select id, created_at, created_by, args, success from completed_job \
"select id, created_at, created_by, CASE WHEN args is null or pg_column_size(args) < 2000000 THEN args ELSE '\"WINDMILL_TOO_BIG\"'::jsonb END as args, success from completed_job \
where {} = $1 and job_kind = $2 and workspace_id = $3 \
order by created_at desc limit $4 offset $5",
r.runnable_type.column_name()
Expand Down Expand Up @@ -167,6 +171,27 @@ async fn get_input_history(
Ok(Json(inputs))
}

async fn get_args_from_history_or_saved_input(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Path((w_id, job_or_input_id)): Path<(String, Uuid)>,
) -> JsonResult<Option<Value>> {
let mut tx = user_db.begin(&authed).await?;
let result_o = sqlx::query_scalar!(
"SELECT args FROM completed_job WHERE id = $1 AND workspace_id = $2 UNION ALL SELECT args FROM input WHERE id = $1 AND workspace_id = $2",
job_or_input_id,
w_id
)
.fetch_optional(&mut *tx)
.await?;

tx.commit().await?;

let result = not_found_if_none(result_o, "Input args", job_or_input_id.to_string())?;

Ok(Json(result))
}

async fn list_saved_inputs(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Expand All @@ -179,7 +204,7 @@ async fn list_saved_inputs(
let mut tx = user_db.begin(&authed).await?;

let rows = sqlx::query_as::<_, InputRow>(
"select * from input \
"select id, workspace_id, runnable_id, runnable_type, name, CASE WHEN pg_column_size(args) < 2000000 THEN args ELSE '\"WINDMILL_TOO_BIG\"'::jsonb END as args, created_at, created_by, is_public from input \
where runnable_id = $1 and runnable_type = $2 and workspace_id = $3 \
and (is_public IS true OR created_by = $4) \
order by created_at desc limit $5 offset $6",
Expand Down
50 changes: 40 additions & 10 deletions frontend/src/lib/components/SavedInputs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import Tooltip from './Tooltip.svelte'
import TimeAgo from './TimeAgo.svelte'
import JobLoader from './runs/JobLoader.svelte'
import Skeleton from './common/skeleton/Skeleton.svelte'
export let scriptHash: string | null = null
export let scriptPath: string | null = null
Expand All @@ -32,8 +33,8 @@
isSaving?: boolean
}
let previousInputs: Input[] = []
let savedInputs: EditableInput[] = []
let previousInputs: Input[] | undefined = undefined
let savedInputs: EditableInput[] | undefined = undefined
let selectedInput: Input | null
let jobs: Job[] = []
let loading: boolean = false
Expand Down Expand Up @@ -92,7 +93,7 @@
is_public: false,
...requestBody
}
savedInputs = [input, ...savedInputs]
savedInputs = [input, ...(savedInputs ?? [])]
} catch (err) {
console.error(err)
sendUserToast(`Failed to save Input: ${err}`, true)
Expand Down Expand Up @@ -127,7 +128,7 @@
workspace: $workspaceStore!,
input: input.id
})
savedInputs = savedInputs.filter((i) => i.id !== input.id)
savedInputs = (savedInputs ?? []).filter((i) => i.id !== input.id)
if (selectedInput === input) {
selectedInput = null
}
Expand All @@ -148,6 +149,20 @@
function selectArgs(selected_args: any) {
dispatch('selected_args', selected_args)
}
async function loadLargeArgs(id: string | undefined) {
if (!id) return
largeArgs = await InputService.getArgsFromHistoryOrSavedInput({
jobOrInputId: id,
workspace: $workspaceStore!
})
}
let hasLargeArgs = false
$: hasLargeArgs =
typeof selectedInput?.args === 'string' && selectedInput?.args === 'WINDMILL_TOO_BIG'
let largeArgs: any = undefined
$: hasLargeArgs && loadLargeArgs(selectedInput?.id)
</script>

<JobLoader
Expand Down Expand Up @@ -192,7 +207,9 @@
</div>

<div class="w-full flex flex-col gap-2 h-full overflow-y-auto p">
{#if savedInputs.length > 0}
{#if savedInputs === undefined}
<Skeleton layout={[[8]]} />
{:else if savedInputs.length > 0}
{#each savedInputs as i}
<button
class={classNames(
Expand Down Expand Up @@ -290,7 +307,9 @@
<span class="text-sm font-semibold">Previous runs</span>

<div class="w-full flex flex-col gap-1 p-0 h-full overflow-y-auto">
{#if jobs.length > 0}
{#if loading}
<Skeleton layout={[[2]]} />
{:else if jobs.length > 0}
{#each jobs as i (i.id)}
<button
class={classNames(
Expand Down Expand Up @@ -331,7 +350,9 @@
</div>

<div class="w-full flex flex-col gap-1 p-0 h-full overflow-y-auto">
{#if previousInputs.length > 0}
{#if previousInputs === undefined}
<Skeleton layout={[[8]]} />
{:else if previousInputs.length > 0}
{#each previousInputs as i (i.id)}
<button
class={classNames(
Expand Down Expand Up @@ -390,15 +411,24 @@
btnClasses="w-full"
size="sm"
spacingSize="xl"
on:click={() => selectArgs(selectedInput?.args)}
disabled={Object.keys(selectedInput?.args || {}).length === 0}
on:click={() => selectArgs(hasLargeArgs ? largeArgs : selectedInput?.args)}
disabled={Object.keys(selectedInput?.args || {}).length === 0 ||
(hasLargeArgs && Object.keys(largeArgs || {}).length === 0)}
>
<ArrowLeftIcon class="w-4 h-4 mr-2" />
Use Input
</Button>
</div>
<div class="w-full min-h-0 grow overflow-auto">
{#if Object.keys(selectedInput?.args || {}).length > 0}
{#if hasLargeArgs}
{#if largeArgs}
<div class=" overflow-auto h-full p-2">
<ObjectViewer json={largeArgs} />
</div>
{:else}
<Skeleton layout={[[8]]} />
{/if}
{:else if Object.keys(selectedInput?.args || {}).length > 0}
<div class=" overflow-auto h-full p-2">
<ObjectViewer json={selectedInput?.args} />
</div>
Expand Down

0 comments on commit 3b67fe8

Please sign in to comment.