feat: force cancel in batch cancel

This commit is contained in:
Ruben Fiszel
2025-09-20 11:29:35 +00:00
parent a46ccaef90
commit 2eeaf5639d
3 changed files with 54 additions and 10 deletions
+4
View File
@@ -7727,6 +7727,10 @@ paths:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: force_cancel
in: query
schema:
type: boolean
requestBody:
description: uuids of the jobs to cancel
required: true
+16 -2
View File
@@ -2055,6 +2055,7 @@ async fn cancel_jobs(
db: &DB,
username: &str,
w_id: &str,
force_cancel: bool,
) -> error::JsonResult<Vec<Uuid>> {
let mut uuids = vec![];
let mut tx = db.begin().await?;
@@ -2114,7 +2115,7 @@ async fn cancel_jobs(
w_id,
tx,
db,
false,
force_cancel,
false,
)
.await?;
@@ -2145,11 +2146,17 @@ async fn cancel_jobs(
Ok(Json(uuids))
}
#[derive(Deserialize)]
pub struct CancelSelectionQuery {
force_cancel: Option<bool>,
}
async fn cancel_selection(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Extension(user_db): Extension<UserDB>,
Path(w_id): Path<String>,
Query(query): Query<CancelSelectionQuery>,
Json(jobs): Json<Vec<Uuid>>,
) -> error::JsonResult<Vec<Uuid>> {
let mut tx = user_db.begin(&authed).await?;
@@ -2163,7 +2170,14 @@ async fn cancel_selection(
.await?;
tx.commit().await?;
cancel_jobs(jobs_to_cancel, &db, authed.username.as_str(), w_id.as_str()).await
cancel_jobs(
jobs_to_cancel,
&db,
authed.username.as_str(),
w_id.as_str(),
query.force_cancel.unwrap_or(false),
)
.await
}
async fn list_filtered_job_uuids(
@@ -186,7 +186,7 @@
confirmBtnText: string
loading?: boolean
preContent?: string
onConfirm?: () => void
onConfirm?: (forceCancel: boolean) => void
type?: ConfirmationModal['$$prop_def']['type']
} = $state(undefined)
@@ -544,10 +544,11 @@
}
}
async function cancelJobs(uuidsToCancel: string[]) {
async function cancelJobs(uuidsToCancel: string[], forceCancel: boolean = false) {
const uuids = await JobService.cancelSelection({
workspace: $workspaceStore ?? '',
requestBody: uuidsToCancel
requestBody: uuidsToCancel,
forceCancel: forceCancel
})
selectedIds = []
jobsLoader?.loadJobs(minTs, maxTs, true, true)
@@ -556,6 +557,7 @@
}
async function onCancelFilteredJobs() {
forceCancelInPopup = false
askingForConfirmation = {
title: 'Confirm cancelling all jobs corresponding to the selected filters',
confirmBtnText: 'Loading...',
@@ -570,18 +572,19 @@
title: `Confirm cancelling all jobs corresponding to the selected filters (${jobIdsToCancel.length} jobs)`,
confirmBtnText: `Cancel ${jobIdsToCancel.length} jobs that matched the filters`,
preContent: selectedFiltersString,
onConfirm: () => {
cancelJobs(jobIdsToCancel)
onConfirm: (forceCancel) => {
cancelJobs(jobIdsToCancel, forceCancel)
}
}
}
async function onCancelSelectedJobs() {
forceCancelInPopup = true
askingForConfirmation = {
confirmBtnText: `Cancel ${selectedIds.length} jobs`,
title: 'Confirm cancelling the selected jobs',
onConfirm: () => {
cancelJobs(selectedIds)
onConfirm: (forceCancel) => {
cancelJobs(selectedIds, forceCancel)
}
}
}
@@ -798,6 +801,8 @@
const smallScreenWidth = 1920
const verySmallScreenWidth = 1300
let forceCancelInPopup = $state(false)
</script>
<JobsLoader
@@ -842,7 +847,7 @@
open={!!askingForConfirmation}
on:confirmed={async () => {
const func = askingForConfirmation?.onConfirm
await func?.()
await func?.(forceCancelInPopup)
askingForConfirmation = undefined
}}
type={askingForConfirmation?.type}
@@ -853,6 +858,27 @@
>
{#if askingForConfirmation?.preContent}
<pre>{askingForConfirmation.preContent}</pre>
<Toggle
size="xs"
class="mt-4"
color="red"
bind:checked={forceCancelInPopup}
options={{
right: 'Force cancel',
rightTooltip:
'Only use this for jobs that refuse to gracefully cancel. This is dangerous, only do this if you have no alternatives!'
}}
></Toggle>
{#if forceCancelInPopup}
<div class="mt-4 text-red-500 p-2 text-sm">
<p>
Force cancel is enabled. This is dangerous, only do this if you have no alternatives.
Instead of being gracefully cancelled, all jobs will be immediately sent to the completed
job table regardless of them being processed or not or part of running flows. You may end
up in an inconsistent state.
</p>
</div>
{/if}
{/if}
</ConfirmationModal>