mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 00:01:49 +00:00
feat: add running filter
This commit is contained in:
@@ -5,7 +5,7 @@ use chrono::Timelike;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use futures::StreamExt;
|
||||
|
||||
use futures::{stream, Stream};
|
||||
use futures::{stream, Stream, StreamExt};
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
use sqlx::{postgres::PgListener, types::Uuid, Pool, Postgres};
|
||||
@@ -15,7 +15,7 @@ use tokio::sync::RwLock;
|
||||
use tokio::time::{timeout, Duration};
|
||||
|
||||
use windmill_api_client::types::{
|
||||
CreateFlowBody, RawScript
|
||||
CreateFlowBody, RawScript, NewScript, NewScriptLanguage
|
||||
};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
@@ -2925,7 +2925,7 @@ async fn run_deployed_relative_imports(db: &Pool<Postgres>, script_content: Stri
|
||||
completed.next().await; // deployed script
|
||||
|
||||
let script =
|
||||
query!("SELECT hash FROM script WHERE path = $1", "f/system/test_import".to_string())
|
||||
sqlx::query!("SELECT hash FROM script WHERE path = $1", "f/system/test_import".to_string())
|
||||
.fetch_one(&db2)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -4117,6 +4117,7 @@ paths:
|
||||
- $ref: "#/components/parameters/StartedBefore"
|
||||
- $ref: "#/components/parameters/StartedAfter"
|
||||
- $ref: "#/components/parameters/CreatedOrStartedBefore"
|
||||
- $ref: "#/components/parameters/Running"
|
||||
- $ref: "#/components/parameters/CreatedOrStartedAfter"
|
||||
- $ref: "#/components/parameters/JobKinds"
|
||||
- $ref: "#/components/parameters/ArgsFilter"
|
||||
|
||||
@@ -780,7 +780,14 @@ async fn list_jobs(
|
||||
let (per_page, offset) = paginate(pagination);
|
||||
let lqc = lq.clone();
|
||||
|
||||
let sqlc = list_completed_jobs_query(
|
||||
if lq.success.is_some() && lq.running.is_some_and(|x| x) {
|
||||
return Err(error::Error::BadRequest(
|
||||
"cannot specify both success and running".to_string(),
|
||||
));
|
||||
|
||||
}
|
||||
let sqlc = if lq.running.is_none() {
|
||||
Some(list_completed_jobs_query(
|
||||
&w_id,
|
||||
per_page + offset,
|
||||
0,
|
||||
@@ -817,7 +824,10 @@ async fn list_jobs(
|
||||
"null as concurrent_limit",
|
||||
"null as concurrency_time_window_s",
|
||||
],
|
||||
);
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let sql = if lq.success.is_none() {
|
||||
let sqlq = list_queue_jobs_query(
|
||||
@@ -833,7 +843,7 @@ async fn list_jobs(
|
||||
created_after: lq.created_after,
|
||||
created_or_started_before: lq.created_or_started_before,
|
||||
created_or_started_after: lq.created_or_started_after,
|
||||
running: None,
|
||||
running: lq.running,
|
||||
parent_job: lq.parent_job,
|
||||
order_desc: Some(true),
|
||||
job_kinds: lq.job_kinds,
|
||||
@@ -876,6 +886,7 @@ async fn list_jobs(
|
||||
],
|
||||
);
|
||||
|
||||
if let Some(sqlc) = sqlc {
|
||||
format!(
|
||||
"{} UNION ALL {} LIMIT {} OFFSET {};",
|
||||
&sqlq.subquery()?,
|
||||
@@ -883,8 +894,11 @@ async fn list_jobs(
|
||||
per_page,
|
||||
offset
|
||||
)
|
||||
} else {
|
||||
sqlq.query()?
|
||||
}
|
||||
} else {
|
||||
sqlc.query()?
|
||||
sqlc.unwrap().query()?
|
||||
};
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let jobs: Vec<UnifiedJob> = sqlx::query_as(&sql).fetch_all(&mut *tx).await?;
|
||||
@@ -2721,6 +2735,7 @@ pub struct ListCompletedQuery {
|
||||
pub created_or_started_before: Option<chrono::DateTime<chrono::Utc>>,
|
||||
pub created_or_started_after: Option<chrono::DateTime<chrono::Utc>>,
|
||||
pub success: Option<bool>,
|
||||
pub running: Option<bool>,
|
||||
pub parent_job: Option<String>,
|
||||
pub order_desc: Option<bool>,
|
||||
pub job_kinds: Option<String>,
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
export let value: any
|
||||
export let login = true
|
||||
|
||||
$: if (value && value?.['allowed_domains'] == undefined) {
|
||||
value = { ...(value ?? {}), allowed_domains: [] }
|
||||
}
|
||||
|
||||
$: enabled = value != undefined
|
||||
|
||||
|
||||
let allowed_domains = value?.['allowed_domains'] ?? ''
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-1">
|
||||
@@ -39,14 +38,19 @@
|
||||
</label>
|
||||
{#if login}
|
||||
<label class="block pb-2">
|
||||
{#if value['allowed_domains']}
|
||||
<span class="text-primary font-semibold text-sm">Allowed domain</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="windmill.dev"
|
||||
bind:value={value['allowed_domains'][0]}
|
||||
/>
|
||||
{/if}
|
||||
<span class="text-primary font-semibold text-sm">Allowed domain</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="windmill.dev"
|
||||
bind:value={allowed_domains}
|
||||
on:keyup={() => {
|
||||
if (allowed_domains == '') {
|
||||
value['allowed_domains'] = undefined
|
||||
} else {
|
||||
value['allowed_domains'] = [allowed_domains]
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
{#if name == 'google'}
|
||||
@@ -83,3 +87,4 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
// Filters
|
||||
export let path: string | null = null
|
||||
export let success: boolean | undefined = undefined
|
||||
export let success: "running" | "success" | "failure" | undefined = undefined
|
||||
export let isSkipped: boolean | undefined = undefined
|
||||
export let argFilter: string
|
||||
export let argError: string
|
||||
@@ -187,8 +187,9 @@
|
||||
<span class="text-xs absolute -top-4">Status</span>
|
||||
<ToggleButtonGroup bind:selected={success}>
|
||||
<ToggleButton value={undefined} label="All" />
|
||||
<ToggleButton value={true} label="Success" class="whitespace-nowrap" />
|
||||
<ToggleButton value={false} label="Failure" class="whitespace-nowrap" />
|
||||
<ToggleButton value={"running"} label="Running" class="whitespace-nowrap" />
|
||||
<ToggleButton value={"success"} label="Success" class="whitespace-nowrap" />
|
||||
<ToggleButton value={"failure"} label="Failure" class="whitespace-nowrap" />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="relative w-32">
|
||||
|
||||
@@ -42,10 +42,7 @@
|
||||
let user: string | null = $page.url.searchParams.get('user')
|
||||
let folder: string | null = $page.url.searchParams.get('folder')
|
||||
// Rest of filters handled by RunsFilter
|
||||
let success: boolean | undefined =
|
||||
$page.url.searchParams.get('success') != undefined
|
||||
? $page.url.searchParams.get('success') == 'true'
|
||||
: undefined
|
||||
let success: "running" | "success" | "failure" | undefined = ($page.url.searchParams.get('success') ?? undefined) as "running" | "success" | "failure" | undefined
|
||||
let isSkipped: boolean | undefined =
|
||||
$page.url.searchParams.get('is_skipped') != undefined
|
||||
? $page.url.searchParams.get('is_skipped') == 'true'
|
||||
@@ -128,7 +125,8 @@
|
||||
createdBy: user === null || user === '' ? undefined : user,
|
||||
scriptPathStart: folder === null || folder === '' ? undefined : `f/${folder}/`,
|
||||
jobKinds,
|
||||
success,
|
||||
success: success == "success" ? true : (success == 'failure' ? false : undefined),
|
||||
running: success == 'running' ? true : undefined,
|
||||
isSkipped,
|
||||
isFlowStep: jobKindsCat != 'all' ? false : undefined,
|
||||
args:
|
||||
@@ -166,34 +164,38 @@
|
||||
async function syncer() {
|
||||
getCount()
|
||||
if (sync && jobs && maxTs == undefined) {
|
||||
let ts: string | undefined = undefined
|
||||
let cursor = 0
|
||||
while (cursor < jobs.length && minTs == undefined) {
|
||||
let invCursor = jobs.length - 1 - cursor
|
||||
let isQueuedJob = cursor == jobs?.length - 1 || jobs[invCursor].type == Job.type.QUEUED_JOB
|
||||
if (isQueuedJob) {
|
||||
if (cursor > 0) {
|
||||
const date = new Date(jobs[invCursor + 1]?.created_at!)
|
||||
date.setMilliseconds(date.getMilliseconds() + 1)
|
||||
ts = date.toISOString()
|
||||
if (success == 'running') {
|
||||
loadJobs()
|
||||
} else {
|
||||
let ts: string | undefined = undefined
|
||||
let cursor = 0
|
||||
while (cursor < jobs.length && minTs == undefined) {
|
||||
let invCursor = jobs.length - 1 - cursor
|
||||
let isQueuedJob = cursor == jobs?.length - 1 || jobs[invCursor].type == Job.type.QUEUED_JOB
|
||||
if (isQueuedJob) {
|
||||
if (cursor > 0) {
|
||||
const date = new Date(jobs[invCursor + 1]?.created_at!)
|
||||
date.setMilliseconds(date.getMilliseconds() + 1)
|
||||
ts = date.toISOString()
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
cursor++
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
|
||||
loading = true
|
||||
const newJobs = await fetchJobs(maxTs, minTs ?? ts)
|
||||
if (newJobs && newJobs.length > 0 && jobs) {
|
||||
const oldJobs = jobs?.map((x) => x.id)
|
||||
jobs = newJobs.filter((x) => !oldJobs.includes(x.id)).concat(jobs)
|
||||
newJobs
|
||||
.filter((x) => oldJobs.includes(x.id))
|
||||
.forEach((x) => (jobs![jobs?.findIndex((y) => y.id == x.id)!] = x))
|
||||
jobs = jobs
|
||||
computeCompletedJobs()
|
||||
loading = true
|
||||
const newJobs = await fetchJobs(maxTs, minTs ?? ts)
|
||||
if (newJobs && newJobs.length > 0 && jobs) {
|
||||
const oldJobs = jobs?.map((x) => x.id)
|
||||
jobs = newJobs.filter((x) => !oldJobs.includes(x.id)).concat(jobs)
|
||||
newJobs
|
||||
.filter((x) => oldJobs.includes(x.id))
|
||||
.forEach((x) => (jobs![jobs?.findIndex((y) => y.id == x.id)!] = x))
|
||||
jobs = jobs
|
||||
computeCompletedJobs()
|
||||
}
|
||||
loading = false
|
||||
}
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,10 +206,7 @@
|
||||
path = $page.params.path
|
||||
user = $page.url.searchParams.get('user')
|
||||
folder = $page.url.searchParams.get('folder')
|
||||
success =
|
||||
$page.url.searchParams.get('success') != undefined
|
||||
? $page.url.searchParams.get('success') == 'true'
|
||||
: undefined
|
||||
success = ($page.url.searchParams.get('success') ?? undefined) as "success" | "failure" | "running" | undefined
|
||||
isSkipped =
|
||||
$page.url.searchParams.get('is_skipped') != undefined
|
||||
? $page.url.searchParams.get('is_skipped') == 'true'
|
||||
|
||||
Reference in New Issue
Block a user