batch execution logic (simple case)
This commit is contained in:
@@ -1,30 +1,74 @@
|
||||
<script lang="ts">
|
||||
import { JobService, type Job, type ScriptArgs } from '$lib/gen'
|
||||
import { JobService, type Job, type RunScriptByPathData, type ScriptArgs } from '$lib/gen'
|
||||
import Modal from '../common/modal/Modal.svelte'
|
||||
import Button from '../common/button/Button.svelte'
|
||||
import Toggle from '../Toggle.svelte'
|
||||
|
||||
export let jobs: Job[] | undefined
|
||||
let modalIsOpen = true
|
||||
export let modalIsOpen = false
|
||||
|
||||
type NewJob = {
|
||||
prior: Job & { args: ScriptArgs }
|
||||
newArgs: ScriptArgs
|
||||
isSelected: boolean
|
||||
}
|
||||
|
||||
// local state
|
||||
let innerJobs: (Job & { priorArgs: ScriptArgs; isSelected: boolean })[] = []
|
||||
// $: innerJobs
|
||||
let newJobs: NewJob[] = []
|
||||
|
||||
if (jobs) {
|
||||
const fewJobs = jobs.slice(0, 10)
|
||||
const promises = fewJobs.map((job) => JobService.getJobArgs({ id: job.id, workspace: 'demo' }))
|
||||
Promise.allSettled(promises)
|
||||
.then((r) => r.filter((result) => result.status === 'fulfilled'))
|
||||
.then((resArr) => resArr.map((p) => p.value) as ScriptArgs[])
|
||||
.then((r) => {
|
||||
innerJobs = fewJobs.map((job, i) => ({
|
||||
...job,
|
||||
priorArgs: r[i],
|
||||
args: structuredClone(r[i]),
|
||||
isSelected: false
|
||||
}))
|
||||
Promise.allSettled(promises).then((results) => {
|
||||
const priorArgs = results
|
||||
.filter((result) => result.status === 'fulfilled')
|
||||
.map((p) => p.value) as ScriptArgs[]
|
||||
|
||||
newJobs = fewJobs.map((job, i) => ({
|
||||
prior: { ...job, args: priorArgs[i] },
|
||||
newArgs: structuredClone(priorArgs[i]),
|
||||
isSelected: false
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
type RunnableNewJob = NewJob & {
|
||||
prior: {
|
||||
script_path: string
|
||||
workspace_id: string
|
||||
}
|
||||
}
|
||||
|
||||
function isRunnableNewJob(newJob: NewJob): newJob is RunnableNewJob {
|
||||
const { prior } = newJob
|
||||
|
||||
return prior.script_path !== undefined && prior.workspace_id !== undefined
|
||||
}
|
||||
|
||||
async function executeBatch() {
|
||||
console.log(newJobs)
|
||||
|
||||
const payloads: RunScriptByPathData[] = newJobs.reduce((payloadsArr, newJob) => {
|
||||
if (!isRunnableNewJob(newJob)) {
|
||||
console.error('this job is not runnable:', newJob) // TODO: rm line
|
||||
return payloadsArr
|
||||
}
|
||||
|
||||
payloadsArr.push({
|
||||
path: newJob.prior.script_path,
|
||||
requestBody: newJob.newArgs,
|
||||
workspace: newJob.prior.workspace_id
|
||||
})
|
||||
return payloadsArr
|
||||
}, [] as RunScriptByPathData[])
|
||||
|
||||
console.log(payloads)
|
||||
|
||||
const promises = payloads.map((payload) => JobService.runScriptByPath(payload))
|
||||
|
||||
Promise.allSettled(promises).then((results) => {
|
||||
console.log(results)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -32,43 +76,22 @@
|
||||
bind:open={modalIsOpen}
|
||||
on:confirmed={() => {
|
||||
modalIsOpen = false
|
||||
// dispatch('confirmed')
|
||||
}}
|
||||
on:canceled
|
||||
title="Runnable batch"
|
||||
class="w-full max-w-full xl:max-w-7xl"
|
||||
>
|
||||
<!-- <Toggle options={{ left: 'Select all' }} />
|
||||
<ul class=" list-disc pl-5">
|
||||
{#each jobsWithArgs as job}
|
||||
<li class="p-2 break-all">{JSON.stringify(job)}</li>
|
||||
<Toggle />
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<Button
|
||||
slot="actions"
|
||||
on:click={() => {
|
||||
open = false
|
||||
// dispatch('confirmed')
|
||||
}}
|
||||
color="light"
|
||||
size="sm"
|
||||
>
|
||||
<span class="inline-flex gap-2">Add something</span>
|
||||
</Button> -->
|
||||
<button on:click={() => console.log(innerJobs)}>console.log(jobsWithArgs)</button>
|
||||
<div class="flex space-x-6">
|
||||
<!-- Left Side: Job List -->
|
||||
<div class="w-1/3 p-4 border-r">
|
||||
<h3 class="text-lg font-semibold mb-4">Runnable Jobs</h3>
|
||||
<ul class="space-y-2">
|
||||
{#each innerJobs as job}
|
||||
{#each newJobs as job}
|
||||
<li>
|
||||
<Toggle bind:checked={job.isSelected} />
|
||||
<span>{job.id}</span>
|
||||
<span>{job.script_path}</span>
|
||||
<span>{job.tag}</span>
|
||||
<span>{job.prior.id}</span>
|
||||
<span>{job.prior.script_path}</span>
|
||||
<span>{job.prior.tag}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
@@ -79,25 +102,35 @@
|
||||
<h3 class="text-lg font-semibold mb-4">Job Configurations</h3>
|
||||
<Button
|
||||
on:click={() => {
|
||||
innerJobs = innerJobs.map((job) => ({
|
||||
newJobs = newJobs.map((job) => ({
|
||||
...job,
|
||||
args: { ...job.priorArgs }
|
||||
isSelected: true
|
||||
}))
|
||||
}}
|
||||
color="light"
|
||||
size="sm">Select all</Button
|
||||
>
|
||||
<Button
|
||||
on:click={() => {
|
||||
newJobs = newJobs.map((job) => ({
|
||||
...job,
|
||||
newArgs: structuredClone(job.prior.args)
|
||||
}))
|
||||
}}
|
||||
color="light"
|
||||
size="sm">Reset job args to prior execution</Button
|
||||
>
|
||||
|
||||
{#each innerJobs as job}
|
||||
{#each newJobs as job}
|
||||
{#if job.isSelected}
|
||||
<div class="mb-6">
|
||||
<h4 class="text-md font-semibold mb-2">{job.id} Config</h4>
|
||||
<h4 class="text-md font-semibold mb-2">{job.prior.id} Config</h4>
|
||||
<div class="space-y-2">
|
||||
{#if job.args !== undefined}
|
||||
{#each Object.keys(job.args) as key}
|
||||
{#if job.newArgs !== undefined}
|
||||
{#each Object.keys(job.newArgs) as key}
|
||||
<div class="flex items-center space-x-4">
|
||||
<label class="w-20" for={key}>{key}</label>
|
||||
<input type="text" class="p-2 border rounded" bind:value={job.args[key]} />
|
||||
<input type="text" class="p-2 border rounded" bind:value={job.newArgs[key]} />
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
@@ -107,4 +140,16 @@
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
slot="actions"
|
||||
on:click={() => {
|
||||
executeBatch()
|
||||
// modalIsOpen = false
|
||||
}}
|
||||
color="light"
|
||||
size="sm"
|
||||
>
|
||||
<span class="inline-flex gap-2">Execute</span>
|
||||
</Button>
|
||||
</Modal>
|
||||
|
||||
@@ -186,17 +186,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let batchModalIsOpen = false
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={() => computeHeight()} />
|
||||
|
||||
<RunnableBatchModal {jobs} />
|
||||
<RunnableBatchModal {jobs} bind:modalIsOpen={batchModalIsOpen} />
|
||||
|
||||
<div
|
||||
class="divide-y min-w-[640px] h-full"
|
||||
id="runs-table-wrapper"
|
||||
bind:clientWidth={containerWidth}
|
||||
>
|
||||
<button on:click={() => (batchModalIsOpen = !batchModalIsOpen)}>Batch execution</button>
|
||||
<div bind:clientHeight={header}>
|
||||
{#if isSelectingJobsToCancel && cancelableJobCount != 0}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
||||
Reference in New Issue
Block a user