Compare commits

...
Author SHA1 Message Date
Brandon Thomas ac555b5f14 nuke dead tasks and dismiss them from view 2026-01-03 00:03:37 -05:00
12 changed files with 163 additions and 11 deletions
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "\n UPDATE tasks\n SET task_status = \"cancelled_by_user\"\n WHERE task_status NOT IN (\n \"complete_success\",\n \"complete_failure\",\n \"dead\",\n \"cancelled_by_user\",\n \"cancelled_by_provider\",\n \"cancelled_by_us\"\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 0
},
"nullable": []
},
"hash": "30272128d83543d9fbfca930b7cdd4af30adfb4d90f2de044463a111c6340495"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "\n UPDATE tasks\n SET is_dismissed_by_user = 1\n WHERE is_dismissed_by_user != 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 0
},
"nullable": []
},
"hash": "f83018ec5493982659a56576296914f937bb4e75db3a522eb4bda486d5caa402"
}
@@ -18,7 +18,7 @@ use http_headers::values::pragma::PRAGMA_NO_CACHE;
use http_headers::values::priority::PRIORITY_4;
use http_headers::values::sec::{SEC_FETCH_DEST_EMPTY, SEC_FETCH_MODE_CORS, SEC_FETCH_SITE_CROSS_SITE};
use http_headers::values::te::TE_TRAILERS;
use log::{debug, error};
use log::{debug, error, info};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use uuid::Uuid;
@@ -55,7 +55,7 @@ pub async fn poll_world_status(args: PollWorldStatusArgs<'_>) -> Result<PollWorl
let url = get_url(args.world_id);
debug!("Requesting URL: {}", url);
info!("Polling World: {}", url);
let mut request_builder = client.get(url)
.header(ACCEPT, ACCEPT_ALL)
@@ -1,2 +1,3 @@
pub mod get_task_queue_command;
pub mod mark_task_as_dismissed_command;
pub mod mark_task_as_dismissed_command;
pub mod tasks_nuke_all_command;
@@ -0,0 +1,61 @@
use crate::core::commands::response::shorthand::ResponseOrErrorMessage;
use crate::core::commands::response::success_response_wrapper::SerializeMarker;
use crate::core::events::generation_events::generation_enqueue_success_event::GenerationEnqueueSuccessEvent;
use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs;
use crate::core::state::data_dir::app_data_root::AppDataRoot;
use crate::core::state::provider_priority::{Provider, ProviderPriorityStore};
use crate::core::state::task_database::TaskDatabase;
use crate::services::sora::state::sora_task_queue::SoraTaskQueue;
use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager;
use chrono::{DateTime, Utc};
use enums::common::generation_provider::GenerationProvider;
use enums::tauri::tasks::task_model_type::TaskModelType;
use enums::tauri::tasks::task_status::TaskStatus;
use enums::tauri::tasks::task_type::TaskType;
use errors::AnyhowResult;
use log::{error, info, warn};
use serde_derive::{Deserialize, Serialize};
use sqlite_tasks::queries::dismiss_all_tasks::dismiss_all_tasks;
use sqlite_tasks::queries::list_tasks_for_frontend::list_tasks_for_frontend;
use sqlite_tasks::queries::mark_task_as_dismissed::mark_task_as_dismissed;
use sqlite_tasks::queries::nuke_all_tasks::nuke_all_tasks;
use storyteller_client::endpoints::media_files::delete_media_file::delete_media_file;
use tauri::{AppHandle, State};
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::sqlite::tasks::TaskId;
#[derive(Serialize)]
pub struct TasksNukeAllResponse {
success: bool,
}
impl SerializeMarker for TasksNukeAllResponse {}
#[tauri::command]
pub async fn tasks_nuke_all_command(
task_database: State<'_, TaskDatabase>,
) -> ResponseOrErrorMessage<TasksNukeAllResponse> {
info!("tasks_nuke_all_command called");
let result = handle_request(
&task_database,
).await;
if let Err(err) = &result {
error!("tasks_nuke_all_command failed: {:?}", err);
return Err("tasks_nuke_all_command failed".into())
}
Ok(TasksNukeAllResponse{
success: true,
}.into())
}
pub async fn handle_request(
task_database: &TaskDatabase,
) -> AnyhowResult<()> {
let _result = nuke_all_tasks(task_database.get_connection()).await?;
let _result = dismiss_all_tasks(task_database.get_connection()).await?;
Ok(())
}
+2
View File
@@ -21,6 +21,7 @@ use crate::core::commands::providers::get_provider_order_command::get_provider_o
use crate::core::commands::providers::set_provider_order_command::set_provider_order_command;
use crate::core::commands::task_queue::get_task_queue_command::get_task_queue_command;
use crate::core::commands::task_queue::mark_task_as_dismissed_command::mark_task_as_dismissed_command;
use crate::core::commands::task_queue::tasks_nuke_all_command::tasks_nuke_all_command;
use crate::core::lifecycle::startup::handle_tauri_startup::handle_tauri_startup;
use crate::core::lifecycle::startup::setup_main_window::setup_main_window;
use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs;
@@ -221,6 +222,7 @@ pub fn run() {
storyteller_open_customer_portal_cancel_plan_command,
storyteller_open_customer_portal_manage_plan_command,
storyteller_open_customer_portal_switch_plan_command,
tasks_nuke_all_command,
storyteller_open_customer_portal_update_payment_method_command,
storyteller_open_subscription_purchase_command,
storyteller_purge_credentials_command,
@@ -0,0 +1,19 @@
use crate::connection::TaskDbConnection;
use crate::error::SqliteTasksError;
/// Mark everything as dismissed.
pub async fn dismiss_all_tasks(
db: &TaskDbConnection,
) -> Result<bool, SqliteTasksError> {
let query = sqlx::query!(r#"
UPDATE tasks
SET is_dismissed_by_user = 1
WHERE is_dismissed_by_user != 1
"#);
let res = query.execute(db.get_pool()).await?;
let rows_updated = res.rows_affected() > 0;
Ok(rows_updated)
}
@@ -1,9 +1,11 @@
pub mod create_task;
pub mod dismiss_all_tasks;
pub mod get_task_by_provider_and_provider_job_id;
pub mod list_tasks_by_provider_and_status;
pub mod list_tasks_by_provider_and_tokens;
pub mod list_tasks_for_frontend;
pub mod mark_task_as_dismissed;
pub mod nuke_all_tasks;
pub mod task;
pub mod update_successful_task_status_with_metadata;
pub mod update_successful_task_status_with_metadata_by_provider;
@@ -0,0 +1,28 @@
use crate::connection::TaskDbConnection;
use crate::error::SqliteTasksError;
/// Abandon all in-progress tasks.
/// Marked as user cancellation.
pub async fn nuke_all_tasks(
db: &TaskDbConnection,
) -> Result<bool, SqliteTasksError> {
// TODO(bt,2025-07-15): We can't set a LIMIT without a certain compiler flag for SQLite ?
let query = sqlx::query!(r#"
UPDATE tasks
SET task_status = "cancelled_by_user"
WHERE task_status NOT IN (
"complete_success",
"complete_failure",
"dead",
"cancelled_by_user",
"cancelled_by_provider",
"cancelled_by_us"
)
"#);
let res = query.execute(db.get_pool()).await?;
let rows_updated = res.rows_affected() > 0;
Ok(rows_updated)
}
@@ -18,7 +18,7 @@ import {
} from "@storyteller/ui-gallery-modal";
import type { GalleryItem } from "@storyteller/ui-gallery-modal";
import { useEffect, useMemo, useRef, useState } from "react";
import { GetTaskQueue, MarkTaskAsDismissed } from "@storyteller/tauri-api";
import { GetTaskQueue, MarkTaskAsDismissed, TasksNukeAll } from "@storyteller/tauri-api";
import type { TaskQueueItem } from "@storyteller/tauri-api";
import { listen, UnlistenFn } from "@tauri-apps/api/event";
import {
@@ -528,12 +528,8 @@ export const TaskQueue = () => {
};
const dismissAll = async () => {
const allIds = [
...completed.map((t) => t.id),
...inProgress.map((t) => t.id),
];
try {
await Promise.all(allIds.map((id) => MarkTaskAsDismissed(id)));
await TasksNukeAll();
} catch (_) {
// ignore
} finally {
+3 -2
View File
@@ -3,13 +3,14 @@ export * from "./lib/artcraft/ArtcraftGetSubscription.js";
export * from "./lib/artcraft/media_files/MediaFileDelete.js";
export * from "./lib/artcraft/task_queue/GetTaskQueue.js";
export * from "./lib/artcraft/task_queue/MarkTaskAsDismissed.js";
export * from "./lib/artcraft/task_queue/TasksNukeAll.js";
export * from "./lib/common/CommandStatus.js";
export * from "./lib/enqueue/EnqueueEditImage.js";
export * from "./lib/enqueue/EnqueueImageBgRemovalCommand.js";
export * from "./lib/enqueue/EnqueueImageInpaint.js";
export * from "./lib/enqueue/EnqueueImageTo3dObject.js";
export * from "./lib/enqueue/EnqueueImageToGaussian.js";
export * from "./lib/enqueue/EnqueueImageTo3dWorld.js";
export * from "./lib/enqueue/EnqueueImageToGaussian.js";
export * from "./lib/enqueue/EnqueueImageToVideo.js";
export * from "./lib/enqueue/EnqueueTextToImage.js";
export * from "./lib/events/BasicEventWrapper.js";
@@ -36,4 +37,4 @@ export * from "./lib/sora/useSoraLoginListener.js";
export * from "./lib/sora/waitForSoraLogin.js";
export * from "./lib/system/GetAppInfo.js";
export * from "./lib/util/LoadWithoutCors.js";
export * from "./lib/worldlabs/WorldLabsGetCredentialInfo.js";
export * from "./lib/worldlabs/WorldLabsGetCredentialInfo.js";
@@ -0,0 +1,18 @@
import { invoke } from "@tauri-apps/api/core";
import { CommandResult } from "../../common/CommandStatus";
interface TasksNukeAllSuccess extends CommandResult {
payload: void;
}
export const TasksNukeAll = async () : Promise<TasksNukeAllSuccess> => {
try {
let result = await invoke("tasks_nuke_all_command") as TasksNukeAllSuccess;
return result;
} catch (error) {
throw error;
}
}
// Temporary just for testing -
(window as any).test_tasks_nuke_all = TasksNukeAll;