mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 16:00:38 +00:00
nits and fix
This commit is contained in:
@@ -1 +1 @@
|
||||
3e7a82db7a8716d76557c4994a79910aaf4d765c
|
||||
a01942048c2464317fc0484c0b2414e14aa5f2a4
|
||||
@@ -8582,21 +8582,28 @@ paths:
|
||||
items:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/jobs/queue/resume_suspended:
|
||||
/w/{workspace}/trigger/{trigger_kind}/resume_suspended_trigger_job/{trigger_path}:
|
||||
post:
|
||||
summary: resume all suspended jobs with the given suspend number
|
||||
operationId: resumeSuspendedJobs
|
||||
summary: resume all suspended jobs for a specific trigger
|
||||
operationId: resumeSuspendedTriggerJobs
|
||||
tags:
|
||||
- job
|
||||
- trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: suspend number of the jobs to resume
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SuspendedJobRequest"
|
||||
- name: trigger_kind
|
||||
description: The kind of trigger
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/components/schemas/JobTriggerKind"
|
||||
- name: trigger_path
|
||||
description: The path of the trigger (can contain forward slashes)
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
style: simple
|
||||
explode: false
|
||||
responses:
|
||||
"200":
|
||||
description: confirmation message
|
||||
@@ -8605,21 +8612,28 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/jobs/queue/cancel_suspended:
|
||||
/w/{workspace}/trigger/{trigger_kind}/cancel_suspended_trigger_job/{trigger_path}:
|
||||
post:
|
||||
summary: cancel all suspended jobs with the given suspend number
|
||||
operationId: cancelSuspendedJobs
|
||||
summary: cancel all suspended jobs for a specific trigger
|
||||
operationId: cancelSuspendedTriggerJobs
|
||||
tags:
|
||||
- job
|
||||
- trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: suspend number of the jobs to cancel
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SuspendedJobRequest"
|
||||
- name: trigger_kind
|
||||
description: The kind of trigger
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/components/schemas/JobTriggerKind"
|
||||
- name: trigger_path
|
||||
description: The path of the trigger (can contain forward slashes)
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
style: simple
|
||||
explode: false
|
||||
responses:
|
||||
"200":
|
||||
description: confirmation message
|
||||
@@ -17258,18 +17272,6 @@ components:
|
||||
- poll
|
||||
- cli
|
||||
|
||||
SuspendedJobRequest:
|
||||
type: object
|
||||
properties:
|
||||
trigger_path:
|
||||
type: string
|
||||
description: The path of the trigger
|
||||
trigger_kind:
|
||||
$ref: "#/components/schemas/JobTriggerKind"
|
||||
required:
|
||||
- runnable_path
|
||||
- trigger_kind
|
||||
|
||||
TriggerExtraProperty:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -37,7 +37,7 @@ use windmill_common::jobs::{
|
||||
DynamicInput, JobTriggerKind, ENTRYPOINT_OVERRIDE,
|
||||
};
|
||||
use windmill_common::s3_helpers::{upload_artifact_to_store, BundleFormat};
|
||||
use windmill_common::triggers::TriggerInfo;
|
||||
use windmill_common::triggers::TriggerMetadata;
|
||||
use windmill_common::utils::{RunnableKind, WarnAfterExt};
|
||||
use windmill_common::worker::{Connection, CLOUD_HOSTED, TMP_DIR};
|
||||
use windmill_common::DYNAMIC_INPUT_CACHE;
|
||||
@@ -1823,6 +1823,7 @@ pub struct ListQueueQuery {
|
||||
pub concurrency_key: Option<String>,
|
||||
pub allow_wildcards: Option<bool>,
|
||||
pub trigger_kind: Option<JobTriggerKind>,
|
||||
pub trigger_path: Option<String>,
|
||||
}
|
||||
|
||||
impl From<ListCompletedQuery> for ListQueueQuery {
|
||||
@@ -1855,6 +1856,7 @@ impl From<ListCompletedQuery> for ListQueueQuery {
|
||||
concurrency_key: lcq.concurrency_key,
|
||||
allow_wildcards: lcq.allow_wildcards,
|
||||
trigger_kind: lcq.trigger_kind,
|
||||
trigger_path: lcq.trigger_path,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1982,6 +1984,10 @@ pub fn filter_list_queue_query(
|
||||
sqlb.and_where_eq("trigger_kind", "?".bind(&format!("{}", tk)));
|
||||
}
|
||||
|
||||
if let Some(tp) = &lq.trigger_path {
|
||||
sqlb.and_where_eq("trigger", "?".bind(tp));
|
||||
}
|
||||
|
||||
sqlb
|
||||
}
|
||||
|
||||
@@ -2435,7 +2441,7 @@ async fn list_jobs(
|
||||
}
|
||||
sqlc.unwrap().limit(per_page).offset(offset).query()?
|
||||
};
|
||||
// tracing::info!("sql: {}", sql);
|
||||
// tracing::info!("sql: {}", &sql);
|
||||
let mut tx: Transaction<'_, Postgres> = user_db.begin(&authed).await?;
|
||||
|
||||
let jobs: Vec<UnifiedJob> = sqlx::query_as(&sql)
|
||||
@@ -4053,7 +4059,7 @@ pub async fn run_flow(
|
||||
flow_version_info: FlowVersionInfo,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<(Uuid, Option<String>)> {
|
||||
let FlowVersionInfo {
|
||||
version,
|
||||
@@ -4159,7 +4165,7 @@ pub async fn run_flow_and_wait_result(
|
||||
flow_version_info: FlowVersionInfo,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<Response> {
|
||||
let (uuid, early_return) = run_flow(
|
||||
authed,
|
||||
@@ -4185,7 +4191,7 @@ pub async fn push_flow_job_by_path_into_queue(
|
||||
flow_path: StripPath,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<(Uuid, Option<String>)> {
|
||||
#[cfg(feature = "enterprise")]
|
||||
check_license_key_valid().await?;
|
||||
@@ -4246,7 +4252,7 @@ pub async fn run_flow_by_version_inner(
|
||||
version: i64,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<(Uuid, Option<String>)> {
|
||||
#[cfg(feature = "enterprise")]
|
||||
check_license_key_valid().await?;
|
||||
@@ -4426,7 +4432,7 @@ pub async fn push_script_job_by_path_into_queue(
|
||||
script_path: StripPath,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<(Uuid, Option<bool>)> {
|
||||
#[cfg(feature = "enterprise")]
|
||||
check_license_key_valid().await?;
|
||||
@@ -6868,7 +6874,7 @@ pub async fn run_job_by_hash_inner(
|
||||
script_hash: ScriptHash,
|
||||
run_query: RunJobQuery,
|
||||
args: PushArgsOwned,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> error::Result<(Uuid, Option<bool>)> {
|
||||
#[cfg(feature = "enterprise")]
|
||||
check_license_key_valid().await?;
|
||||
@@ -7936,6 +7942,10 @@ pub fn filter_list_completed_query(
|
||||
sqlb.and_where_eq("trigger_kind", "?".bind(&format!("{}", tk)));
|
||||
}
|
||||
|
||||
if let Some(tp) = &lq.trigger_path {
|
||||
sqlb.and_where_eq("trigger", "?".bind(tp));
|
||||
}
|
||||
|
||||
sqlb
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
use crate::{db::{ApiAuthed, DB}, triggers::INACTIVE_TRIGGER_SCHEDULED_FOR_DATE};
|
||||
use axum::{
|
||||
extract::{Extension, Path},
|
||||
response::Json,
|
||||
};
|
||||
use windmill_common::{error, jobs::JobTriggerKind, utils::require_admin};
|
||||
|
||||
pub async fn resume_suspended_trigger_jobs(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, trigger_kind, trigger_path)): Path<(String, JobTriggerKind, String)>,
|
||||
) -> error::Result<Json<String>> {
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
let scheduled_for = INACTIVE_TRIGGER_SCHEDULED_FOR_DATE.clone();
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
UPDATE
|
||||
v2_job_queue
|
||||
SET
|
||||
scheduled_for = now()
|
||||
FROM
|
||||
v2_job
|
||||
WHERE
|
||||
v2_job_queue.id = v2_job.id AND
|
||||
v2_job_queue.running is FALSE AND
|
||||
v2_job_queue.scheduled_for = $1 AND
|
||||
v2_job_queue.workspace_id = $2 AND
|
||||
v2_job.trigger_kind = $3 AND
|
||||
v2_job.trigger = $4
|
||||
"#,
|
||||
scheduled_for,
|
||||
w_id,
|
||||
trigger_kind as _,
|
||||
trigger_path
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
|
||||
let count = result.rows_affected();
|
||||
|
||||
let message = format!(
|
||||
"Successfully resumed {} suspended job{} for trigger at path: {}",
|
||||
count,
|
||||
if count == 1 { "" } else { "s" },
|
||||
&trigger_path
|
||||
);
|
||||
Ok(Json(message))
|
||||
}
|
||||
|
||||
pub async fn cancel_suspended_trigger_jobs(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, trigger_kind, trigger_path)): Path<(String, JobTriggerKind, String)>,
|
||||
) -> error::Result<Json<String>> {
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
let scheduled_for = INACTIVE_TRIGGER_SCHEDULED_FOR_DATE.clone();
|
||||
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
UPDATE
|
||||
v2_job_queue
|
||||
SET
|
||||
canceled_by = $1,
|
||||
canceled_reason = 'cancelled by trigger bulk operation',
|
||||
scheduled_for = now()
|
||||
FROM
|
||||
v2_job
|
||||
WHERE
|
||||
v2_job_queue.id = v2_job.id AND
|
||||
v2_job_queue.workspace_id = $2 AND
|
||||
v2_job_queue.running is FALSE AND
|
||||
v2_job_queue.scheduled_for = $3 AND
|
||||
v2_job.trigger_kind = $4 AND
|
||||
v2_job.trigger = $5
|
||||
"#,
|
||||
authed.username,
|
||||
w_id,
|
||||
scheduled_for,
|
||||
trigger_kind as _,
|
||||
trigger_path
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
|
||||
let count = result.rows_affected();
|
||||
|
||||
let message = format!(
|
||||
"Successfully cancelled {} suspended job{} for trigger at path: {}",
|
||||
count,
|
||||
if count == 1 { "" } else { "s" },
|
||||
&trigger_path
|
||||
);
|
||||
Ok(Json(message))
|
||||
}
|
||||
@@ -739,6 +739,22 @@ pub fn generate_trigger_routers() -> Router {
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
use crate::triggers::global_handler::{
|
||||
cancel_suspended_trigger_jobs, resume_suspended_trigger_jobs,
|
||||
};
|
||||
|
||||
router = router
|
||||
.route(
|
||||
"/trigger/:trigger_kind/resume_suspended_trigger_job/*trigger_path",
|
||||
post(resume_suspended_trigger_jobs),
|
||||
)
|
||||
.route(
|
||||
"/trigger/:trigger_kind/cancel_suspended_trigger_job/*trigger_path",
|
||||
post(cancel_suspended_trigger_jobs),
|
||||
);
|
||||
}
|
||||
|
||||
router
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ use windmill_common::{
|
||||
db::UserDB,
|
||||
error::{Error, Result},
|
||||
jobs::JobTriggerKind,
|
||||
triggers::{TriggerInfo, TriggerKind},
|
||||
triggers::{TriggerMetadata, TriggerKind},
|
||||
utils::{not_found_if_none, require_admin, StripPath},
|
||||
worker::CLOUD_HOSTED,
|
||||
};
|
||||
@@ -1040,7 +1040,7 @@ async fn route_job(
|
||||
)
|
||||
.map_err(|e| e.into_response())?;
|
||||
|
||||
let trigger_info = TriggerInfo::new(Some(trigger.path.clone()), JobTriggerKind::Http);
|
||||
let trigger_info = TriggerMetadata::new(Some(trigger.path.clone()), JobTriggerKind::Http);
|
||||
if !trigger.active_mode {
|
||||
let _ = trigger_runnable(
|
||||
&db,
|
||||
|
||||
@@ -22,7 +22,7 @@ use tokio::sync::RwLock;
|
||||
use windmill_common::{
|
||||
error::{Error, Result},
|
||||
jobs::JobTriggerKind,
|
||||
triggers::{TriggerInfo, TriggerKind},
|
||||
triggers::{TriggerMetadata, TriggerKind},
|
||||
utils::report_critical_error,
|
||||
DB, INSTANCE_NAME,
|
||||
};
|
||||
@@ -507,7 +507,7 @@ pub trait Listener: TriggerCrud + TriggerJobArgs {
|
||||
format!("{}_trigger/{}", Self::TRIGGER_KIND, listening_trigger.path),
|
||||
None,
|
||||
listening_trigger.active_mode.unwrap_or(false),
|
||||
TriggerInfo::new(Some(listening_trigger.path.clone()), Self::JOB_TRIGGER_KIND),
|
||||
TriggerMetadata::new(Some(listening_trigger.path.clone()), Self::JOB_TRIGGER_KIND),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ pub mod websocket;
|
||||
mod handler;
|
||||
mod listener;
|
||||
pub mod trigger_helpers;
|
||||
pub mod global_handler;
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) use handler::TriggerCrud;
|
||||
|
||||
@@ -16,7 +16,7 @@ use windmill_common::{
|
||||
jobs::{get_has_preprocessor_from_content_and_lang, script_path_to_payload, JobPayload},
|
||||
scripts::{get_full_hub_script_by_path, ScriptHash, ScriptLang},
|
||||
triggers::{
|
||||
HubOrWorkspaceId, RunnableFormat, RunnableFormatVersion, TriggerInfo, TriggerKind,
|
||||
HubOrWorkspaceId, RunnableFormat, RunnableFormatVersion, TriggerMetadata, TriggerKind,
|
||||
RUNNABLE_FORMAT_VERSION_CACHE,
|
||||
},
|
||||
users::username_to_permissioned_as,
|
||||
@@ -519,7 +519,7 @@ pub async fn trigger_runnable_inner(
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, serde_json::Value>>>,
|
||||
trigger_path: String,
|
||||
job_id: Option<Uuid>,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
active_mode: Option<bool>,
|
||||
) -> Result<(Uuid, Option<bool>, Option<String>)> {
|
||||
let error_handler_args = error_handler_args.map(|args| {
|
||||
@@ -588,7 +588,7 @@ pub async fn trigger_runnable(
|
||||
trigger_path: String,
|
||||
job_id: Option<Uuid>,
|
||||
active_mode: bool,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
) -> Result<axum::response::Response> {
|
||||
let uuid = trigger_runnable_inner(
|
||||
db,
|
||||
@@ -624,7 +624,7 @@ pub async fn trigger_runnable_and_wait_for_result(
|
||||
error_handler_path: Option<&str>,
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, serde_json::Value>>>,
|
||||
trigger_path: String,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
) -> Result<axum::response::Response> {
|
||||
let username = authed.username.clone();
|
||||
let (uuid, delete_after_use, early_return) = trigger_runnable_inner(
|
||||
@@ -667,7 +667,7 @@ pub async fn trigger_runnable_and_wait_for_raw_result(
|
||||
error_handler_path: Option<&str>,
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, serde_json::Value>>>,
|
||||
trigger_path: String,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
) -> Result<(Box<RawValue>, bool)> {
|
||||
let username = authed.username.clone();
|
||||
let (uuid, delete_after_use, early_return) = trigger_runnable_inner(
|
||||
@@ -718,7 +718,7 @@ pub async fn trigger_runnable_and_wait_for_raw_result_with_error_ctx(
|
||||
error_handler_path: Option<&str>,
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, serde_json::Value>>>,
|
||||
trigger_path: String,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
) -> Result<Box<RawValue>> {
|
||||
let (result, success) = trigger_runnable_and_wait_for_raw_result(
|
||||
db,
|
||||
@@ -759,7 +759,7 @@ async fn trigger_script_internal(
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, Box<RawValue>>>>,
|
||||
trigger_path: String,
|
||||
job_id: Option<Uuid>,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
scheduled_for: Option<DateTime<Utc>>,
|
||||
) -> Result<(Uuid, Option<bool>)> {
|
||||
if retry.is_none() && error_handler_path.is_none() {
|
||||
@@ -808,7 +808,7 @@ async fn trigger_script_with_retry_and_error_handler(
|
||||
error_handler_args: Option<&sqlx::types::Json<HashMap<String, Box<RawValue>>>>,
|
||||
trigger_path: String,
|
||||
job_id: Option<Uuid>,
|
||||
trigger: TriggerInfo,
|
||||
trigger: TriggerMetadata,
|
||||
scheduled_for: Option<DateTime<Utc>>,
|
||||
) -> Result<(Uuid, Option<bool>)> {
|
||||
#[cfg(feature = "enterprise")]
|
||||
|
||||
@@ -24,7 +24,7 @@ use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, Web
|
||||
use windmill_common::{
|
||||
error::{to_anyhow, Error, Result},
|
||||
jobs::JobTriggerKind,
|
||||
triggers::TriggerInfo,
|
||||
triggers::TriggerMetadata,
|
||||
utils::report_critical_error,
|
||||
worker::to_raw_value,
|
||||
DB,
|
||||
@@ -95,7 +95,7 @@ impl ListeningTrigger<WebsocketConfig> {
|
||||
None,
|
||||
None,
|
||||
"".to_string(), // doesn't matter as no retry/error handler
|
||||
TriggerInfo::new(Some(self.path.to_owned()), JobTriggerKind::Websocket),
|
||||
TriggerMetadata::new(Some(self.path.to_owned()), JobTriggerKind::Websocket),
|
||||
)
|
||||
.await
|
||||
.map(|r| r.get().to_owned())?;
|
||||
@@ -368,7 +368,7 @@ impl Listener for WebsocketTrigger {
|
||||
None => (None, None, None),
|
||||
};
|
||||
let active_mode = active_mode.unwrap_or(false);
|
||||
let trigger = TriggerInfo::new(Some(path.to_owned()), Self::JOB_TRIGGER_KIND);
|
||||
let trigger = TriggerMetadata::new(Some(path.to_owned()), Self::JOB_TRIGGER_KIND);
|
||||
if active_mode || extra.is_none() {
|
||||
trigger_runnable(
|
||||
db,
|
||||
|
||||
@@ -12,7 +12,7 @@ use sqlx::{types::Json as SqlxJson, FromRow};
|
||||
use windmill_common::{
|
||||
error::{Error, Result},
|
||||
jobs::JobTriggerKind,
|
||||
triggers::{TriggerInfo, TriggerKind},
|
||||
triggers::{TriggerMetadata, TriggerKind},
|
||||
worker::to_raw_value,
|
||||
DB,
|
||||
};
|
||||
@@ -114,7 +114,7 @@ pub async fn get_url_from_runnable_value(
|
||||
None,
|
||||
None,
|
||||
"".to_string(), // doesn't matter as no retry/error handler
|
||||
TriggerInfo::new(Some(path.to_owned()), JobTriggerKind::Websocket),
|
||||
TriggerMetadata::new(Some(path.to_owned()), JobTriggerKind::Websocket),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -85,13 +85,13 @@ lazy_static! {
|
||||
Cache::new(1000);
|
||||
}
|
||||
|
||||
pub struct TriggerInfo {
|
||||
pub struct TriggerMetadata {
|
||||
pub trigger_path: Option<String>,
|
||||
pub trigger_kind: JobTriggerKind,
|
||||
}
|
||||
|
||||
impl TriggerInfo {
|
||||
pub fn new(trigger_path: Option<String>, trigger_kind: JobTriggerKind) -> TriggerInfo {
|
||||
TriggerInfo { trigger_path, trigger_kind }
|
||||
impl TriggerMetadata {
|
||||
pub fn new(trigger_path: Option<String>, trigger_kind: JobTriggerKind) -> TriggerMetadata {
|
||||
TriggerMetadata { trigger_path, trigger_kind }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ use windmill_common::auth::JobPerms;
|
||||
use windmill_common::bench::BenchmarkIter;
|
||||
use windmill_common::lockfiles::is_generated_from_raw_requirements;
|
||||
use windmill_common::jobs::{JobTriggerKind, EMAIL_ERROR_HANDLER_USER_EMAIL};
|
||||
use windmill_common::triggers::TriggerInfo;
|
||||
use windmill_common::triggers::TriggerMetadata;
|
||||
use windmill_common::utils::{configure_client, now_from_db};
|
||||
use windmill_common::worker::{Connection, MIN_VERSION_SUPPORTS_DEBOUNCING, SCRIPT_TOKEN_EXPIRY};
|
||||
|
||||
@@ -3887,7 +3887,7 @@ pub async fn push<'c, 'd>(
|
||||
// If we know there is already a debounce job, we can use this for debouncing.
|
||||
// NOTE: Only works with dependency jobs triggered by relative imports
|
||||
debounce_job_id_o: Option<Uuid>,
|
||||
trigger: Option<TriggerInfo>,
|
||||
trigger: Option<TriggerMetadata>,
|
||||
) -> Result<(Uuid, Transaction<'c, Postgres>), Error> {
|
||||
#[cfg(feature = "cloud")]
|
||||
if *CLOUD_HOSTED {
|
||||
|
||||
@@ -24,7 +24,7 @@ use windmill_common::jobs::JobPayload;
|
||||
use windmill_common::jobs::JobTriggerKind;
|
||||
use windmill_common::schedule::schedule_to_user;
|
||||
use windmill_common::scripts::ScriptHash;
|
||||
use windmill_common::triggers::TriggerInfo;
|
||||
use windmill_common::triggers::TriggerMetadata;
|
||||
use windmill_common::utils::WarnAfterExt;
|
||||
use windmill_common::worker::to_raw_value;
|
||||
use windmill_common::FlowVersionInfo;
|
||||
@@ -502,7 +502,7 @@ pub async fn push_scheduled_job<'c>(
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
Some(TriggerInfo::new(
|
||||
Some(TriggerMetadata::new(
|
||||
Some(schedule.path.clone()),
|
||||
JobTriggerKind::Schedule,
|
||||
)),
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import RunRow from '../runs/RunRow.svelte'
|
||||
import '../runs/runs-grid.css'
|
||||
import { JobService } from '$lib/gen'
|
||||
import { JobService, TriggerService } from '$lib/gen'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { type JobTriggerType } from './utils'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
|
||||
type Props = {
|
||||
active_mode: boolean
|
||||
triggerPath: string
|
||||
@@ -32,15 +33,23 @@
|
||||
let loading = $state(false)
|
||||
let error = $state<string | null>(null)
|
||||
let processingAction = $state(false)
|
||||
let isPreviousLoading = $state(false)
|
||||
let isNextLoading = $state(false)
|
||||
let workspace = $workspaceStore!
|
||||
let containerWidth = $state(1000)
|
||||
let currentPage = $state(1)
|
||||
let perPage = $state(20)
|
||||
let hasMorePages = $derived(queuedJobs.length === perPage)
|
||||
$effect(() => {
|
||||
if (shouldShowModal) {
|
||||
fetchQueuedJobs()
|
||||
}
|
||||
})
|
||||
|
||||
async function fetchQueuedJobs() {
|
||||
async function fetchQueuedJobs(resetPage = false) {
|
||||
if (resetPage) {
|
||||
currentPage = 1
|
||||
}
|
||||
loading = true
|
||||
error = null
|
||||
|
||||
@@ -50,7 +59,8 @@
|
||||
triggerKind: jobTriggerKind,
|
||||
triggerPath,
|
||||
running: false,
|
||||
perPage: 100
|
||||
perPage,
|
||||
page: currentPage
|
||||
})
|
||||
|
||||
queuedJobs = allSuspendedJobs
|
||||
@@ -62,6 +72,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
if (hasMorePages && !loading) {
|
||||
isNextLoading = true
|
||||
currentPage += 1
|
||||
fetchQueuedJobs().finally(() => {
|
||||
isNextLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
if (currentPage > 1 && !loading) {
|
||||
isPreviousLoading = true
|
||||
currentPage -= 1
|
||||
fetchQueuedJobs().finally(() => {
|
||||
isPreviousLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function runAllJobs() {
|
||||
if (queuedJobs.length === 0) return
|
||||
|
||||
@@ -69,12 +99,10 @@
|
||||
error = null
|
||||
|
||||
try {
|
||||
const resumedJobs = await JobService.resumeSuspendedJobs({
|
||||
const resumedJobs = await TriggerService.resumeSuspendedTriggerJobs({
|
||||
workspace,
|
||||
requestBody: {
|
||||
trigger_kind: jobTriggerKind,
|
||||
trigger_path: triggerPath
|
||||
}
|
||||
triggerKind: jobTriggerKind,
|
||||
triggerPath
|
||||
})
|
||||
sendUserToast(resumedJobs)
|
||||
} catch (e) {
|
||||
@@ -82,7 +110,6 @@
|
||||
console.error('Failed to run jobs:', e)
|
||||
} finally {
|
||||
processingAction = false
|
||||
|
||||
closeModal()
|
||||
}
|
||||
}
|
||||
@@ -94,12 +121,10 @@
|
||||
error = null
|
||||
|
||||
try {
|
||||
await JobService.cancelSuspendedJobs({
|
||||
await TriggerService.cancelSuspendedTriggerJobs({
|
||||
workspace,
|
||||
requestBody: {
|
||||
trigger_kind: jobTriggerKind,
|
||||
trigger_path: triggerPath
|
||||
}
|
||||
triggerKind: jobTriggerKind,
|
||||
triggerPath
|
||||
})
|
||||
|
||||
sendUserToast(`Successfully canceled all jobs`)
|
||||
@@ -123,7 +148,9 @@
|
||||
{#if shouldShowModal}
|
||||
<Modal2
|
||||
bind:isOpen={shouldShowModal}
|
||||
title="{queuedJobs.length} job{queuedJobs.length === 1 ? '' : 's'} queued for this trigger"
|
||||
title="{hasMorePages
|
||||
? `${queuedJobs.length}+ suspended`
|
||||
: `${queuedJobs.length} suspended`} job{queuedJobs.length === 1 ? '' : 's'} for this trigger"
|
||||
target="#content"
|
||||
fixedSize="lg"
|
||||
>
|
||||
@@ -142,16 +169,18 @@
|
||||
{:else if queuedJobs.length === 0}
|
||||
<div class="flex flex-col items-center w-full py-12 px-4">
|
||||
<div class="text-center">
|
||||
<div class="text-base font-medium text-secondary mb-2">No queued jobs found</div>
|
||||
<div class="text-base font-medium text-secondary mb-2">No suspended jobs found</div>
|
||||
<div class="text-sm text-tertiary"
|
||||
>This trigger has no jobs waiting to be processed.</div
|
||||
>This trigger has no suspended jobs waiting to be processed.</div
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex-1 overflow-auto">
|
||||
<div class="mb-3">
|
||||
<h3 class="text-sm font-medium">Queued Jobs ({queuedJobs.length})</h3>
|
||||
<h3 class="text-sm font-medium">
|
||||
Suspended Jobs {#if hasMorePages}(Page {currentPage}){:else}({queuedJobs.length}){/if}
|
||||
</h3>
|
||||
<p class="text-xs text-gray-500 mt-1">Click on any job to view details</p>
|
||||
</div>
|
||||
|
||||
@@ -185,10 +214,51 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if queuedJobs.length > 0 && (currentPage > 1 || hasMorePages)}
|
||||
<div
|
||||
class="w-full bg-surface border-t flex flex-row justify-between p-2 items-center gap-2"
|
||||
>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<span class="text-xs text-secondary">
|
||||
{queuedJobs.length}
|
||||
{hasMorePages ? '+' : ''} suspended job{queuedJobs.length === 1 ? '' : 's'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-3 items-center">
|
||||
<div class="flex text-xs text-secondary">Page {currentPage}</div>
|
||||
|
||||
<Button
|
||||
variant="subtle"
|
||||
size="xs2"
|
||||
startIcon={{ icon: ChevronLeft }}
|
||||
on:click={prevPage}
|
||||
disabled={currentPage === 1 || loading}
|
||||
loading={isPreviousLoading}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="subtle"
|
||||
size="xs2"
|
||||
endIcon={{ icon: ChevronRight }}
|
||||
on:click={nextPage}
|
||||
disabled={!hasMorePages || loading}
|
||||
loading={isNextLoading}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<p class="text-sm text-blue-700">
|
||||
You are switching this trigger from inactive to active mode. What would you like to do
|
||||
with the {queuedJobs.length} queued job{queuedJobs.length === 1 ? '' : 's'}?
|
||||
with the {hasMorePages
|
||||
? `${queuedJobs.length}+ suspended`
|
||||
: `${queuedJobs.length} suspended`} job{queuedJobs.length === 1 ? '' : 's'}?
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -198,7 +268,7 @@
|
||||
<Button
|
||||
variant="border"
|
||||
size="sm"
|
||||
on:click={discardAllJobs}
|
||||
onClick={discardAllJobs}
|
||||
disabled={processingAction}
|
||||
color="red"
|
||||
>
|
||||
@@ -208,7 +278,7 @@
|
||||
<Button
|
||||
variant="contained"
|
||||
size="sm"
|
||||
on:click={runAllJobs}
|
||||
onClick={runAllJobs}
|
||||
disabled={processingAction}
|
||||
color="green"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user