diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 71b26a3a41..3ba8aa1b96 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -3e7a82db7a8716d76557c4994a79910aaf4d765c \ No newline at end of file +a01942048c2464317fc0484c0b2414e14aa5f2a4 \ No newline at end of file diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 822c132b74..c76f1c55cf 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -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: diff --git a/backend/windmill-api/src/jobs.rs b/backend/windmill-api/src/jobs.rs index 398fe2a2de..4b93e91a9f 100644 --- a/backend/windmill-api/src/jobs.rs +++ b/backend/windmill-api/src/jobs.rs @@ -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, pub allow_wildcards: Option, pub trigger_kind: Option, + pub trigger_path: Option, } impl From for ListQueueQuery { @@ -1855,6 +1856,7 @@ impl From 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 = sqlx::query_as(&sql) @@ -4053,7 +4059,7 @@ pub async fn run_flow( flow_version_info: FlowVersionInfo, run_query: RunJobQuery, args: PushArgsOwned, - trigger: Option, + trigger: Option, ) -> error::Result<(Uuid, Option)> { 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, + trigger: Option, ) -> error::Result { 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, + trigger: Option, ) -> error::Result<(Uuid, Option)> { #[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, + trigger: Option, ) -> error::Result<(Uuid, Option)> { #[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, + trigger: Option, ) -> error::Result<(Uuid, Option)> { #[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, + trigger: Option, ) -> error::Result<(Uuid, Option)> { #[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 } diff --git a/backend/windmill-api/src/triggers/global_handler.rs b/backend/windmill-api/src/triggers/global_handler.rs new file mode 100644 index 0000000000..619e676580 --- /dev/null +++ b/backend/windmill-api/src/triggers/global_handler.rs @@ -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, + Path((w_id, trigger_kind, trigger_path)): Path<(String, JobTriggerKind, String)>, +) -> error::Result> { + 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, + Path((w_id, trigger_kind, trigger_path)): Path<(String, JobTriggerKind, String)>, +) -> error::Result> { + 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)) +} diff --git a/backend/windmill-api/src/triggers/handler.rs b/backend/windmill-api/src/triggers/handler.rs index d1d3d8c341..4a293569a0 100644 --- a/backend/windmill-api/src/triggers/handler.rs +++ b/backend/windmill-api/src/triggers/handler.rs @@ -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 } diff --git a/backend/windmill-api/src/triggers/http/handler.rs b/backend/windmill-api/src/triggers/http/handler.rs index f98c8ee7ca..d01ee5e2a7 100644 --- a/backend/windmill-api/src/triggers/http/handler.rs +++ b/backend/windmill-api/src/triggers/http/handler.rs @@ -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, diff --git a/backend/windmill-api/src/triggers/listener.rs b/backend/windmill-api/src/triggers/listener.rs index f931d036d8..a17aaa2379 100644 --- a/backend/windmill-api/src/triggers/listener.rs +++ b/backend/windmill-api/src/triggers/listener.rs @@ -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?; diff --git a/backend/windmill-api/src/triggers/mod.rs b/backend/windmill-api/src/triggers/mod.rs index 276e741171..2bd8237962 100644 --- a/backend/windmill-api/src/triggers/mod.rs +++ b/backend/windmill-api/src/triggers/mod.rs @@ -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; diff --git a/backend/windmill-api/src/triggers/trigger_helpers.rs b/backend/windmill-api/src/triggers/trigger_helpers.rs index 031b200021..874a687e7a 100644 --- a/backend/windmill-api/src/triggers/trigger_helpers.rs +++ b/backend/windmill-api/src/triggers/trigger_helpers.rs @@ -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>>, trigger_path: String, job_id: Option, - trigger: TriggerInfo, + trigger: TriggerMetadata, active_mode: Option, ) -> Result<(Uuid, Option, Option)> { let error_handler_args = error_handler_args.map(|args| { @@ -588,7 +588,7 @@ pub async fn trigger_runnable( trigger_path: String, job_id: Option, active_mode: bool, - trigger: TriggerInfo, + trigger: TriggerMetadata, ) -> Result { 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>>, trigger_path: String, - trigger: TriggerInfo, + trigger: TriggerMetadata, ) -> Result { 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>>, trigger_path: String, - trigger: TriggerInfo, + trigger: TriggerMetadata, ) -> Result<(Box, 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>>, trigger_path: String, - trigger: TriggerInfo, + trigger: TriggerMetadata, ) -> Result> { 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>>>, trigger_path: String, job_id: Option, - trigger: TriggerInfo, + trigger: TriggerMetadata, scheduled_for: Option>, ) -> Result<(Uuid, Option)> { 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>>>, trigger_path: String, job_id: Option, - trigger: TriggerInfo, + trigger: TriggerMetadata, scheduled_for: Option>, ) -> Result<(Uuid, Option)> { #[cfg(feature = "enterprise")] diff --git a/backend/windmill-api/src/triggers/websocket/listener.rs b/backend/windmill-api/src/triggers/websocket/listener.rs index b1fd2dc56d..b1261fc30e 100644 --- a/backend/windmill-api/src/triggers/websocket/listener.rs +++ b/backend/windmill-api/src/triggers/websocket/listener.rs @@ -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 { 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, diff --git a/backend/windmill-api/src/triggers/websocket/mod.rs b/backend/windmill-api/src/triggers/websocket/mod.rs index 6d35c77e8e..f20b6334f7 100644 --- a/backend/windmill-api/src/triggers/websocket/mod.rs +++ b/backend/windmill-api/src/triggers/websocket/mod.rs @@ -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?; diff --git a/backend/windmill-common/src/triggers.rs b/backend/windmill-common/src/triggers.rs index 3c28db449c..d3f0e1d98f 100644 --- a/backend/windmill-common/src/triggers.rs +++ b/backend/windmill-common/src/triggers.rs @@ -85,13 +85,13 @@ lazy_static! { Cache::new(1000); } -pub struct TriggerInfo { +pub struct TriggerMetadata { pub trigger_path: Option, pub trigger_kind: JobTriggerKind, } -impl TriggerInfo { - pub fn new(trigger_path: Option, trigger_kind: JobTriggerKind) -> TriggerInfo { - TriggerInfo { trigger_path, trigger_kind } +impl TriggerMetadata { + pub fn new(trigger_path: Option, trigger_kind: JobTriggerKind) -> TriggerMetadata { + TriggerMetadata { trigger_path, trigger_kind } } } diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 5c3bca618c..bc4078fcef 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -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, - trigger: Option, + trigger: Option, ) -> Result<(Uuid, Transaction<'c, Postgres>), Error> { #[cfg(feature = "cloud")] if *CLOUD_HOSTED { diff --git a/backend/windmill-queue/src/schedule.rs b/backend/windmill-queue/src/schedule.rs index 51641bde39..4a658a3682 100644 --- a/backend/windmill-queue/src/schedule.rs +++ b/backend/windmill-queue/src/schedule.rs @@ -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, )), diff --git a/frontend/src/lib/components/triggers/TriggerStateToggle.svelte b/frontend/src/lib/components/triggers/TriggerStateToggle.svelte index d57dc0f9e5..bf0eb7fdf1 100644 --- a/frontend/src/lib/components/triggers/TriggerStateToggle.svelte +++ b/frontend/src/lib/components/triggers/TriggerStateToggle.svelte @@ -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(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} @@ -142,16 +169,18 @@ {:else if queuedJobs.length === 0}
-
No queued jobs found
+
No suspended jobs found
This trigger has no jobs waiting to be processed.
This trigger has no suspended jobs waiting to be processed.
{:else}
-

Queued Jobs ({queuedJobs.length})

+

+ Suspended Jobs {#if hasMorePages}(Page {currentPage}){:else}({queuedJobs.length}){/if} +

Click on any job to view details

@@ -185,10 +214,51 @@
+ {#if queuedJobs.length > 0 && (currentPage > 1 || hasMorePages)} +
+
+ + {queuedJobs.length} + {hasMorePages ? '+' : ''} suspended job{queuedJobs.length === 1 ? '' : 's'} + +
+ +
+
Page {currentPage}
+ + + + +
+
+ {/if} +

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'}?

{/if} @@ -198,7 +268,7 @@