refactor database crate / move it

This commit is contained in:
Hanashi 2026-07-31 01:10:36 -04:00
parent 294f71f9cc
commit 4aaf2fa6dd
61 changed files with 112 additions and 113 deletions

View File

@ -16,9 +16,8 @@ artcraftx/
│ ├── desktop/ # Desktop (Tauri) apps
│ │ └── artcraftx/ # (Important) ArtCraftX, the desktop app
│ ├── lib/ # Various utility libraries
│ ├── sqlite_database/ # Desktop app's "tasks" SQLite database: queries + embedded migrations
│ ├── schema/ # Data definition layer
│ │ ├── database/
│ │ │ └── sqlite_tasks/ # Queries for the desktop app's "tasks" SQLite database
│ │ └── public/ # Token identifier and enum variant definitions
│ │ ├── enums/ # Enum variants stored as strings
│ │ └── tokens/ # Identifiers with Stripe-like ID prefixes, eg. "user_{entropy}"
@ -37,7 +36,7 @@ artcraftx/
- Rust with no minimum supported version
- A mix of wreq and reqwest for Rust HTTP clients
- SQLx for SQLite (the desktop app's local task database in `sqlite_tasks`)
- SQLx for SQLite (the desktop app's local task database in `sqlite_database`)
- Never use `println!` or `eprintln!` outside of tests; use `log` crate macros instead
- When two crates export the same type name, alias imports with a suffix: `use foo::Bar as BarFoo;`
- Prefer `use` imports over inline fully-qualified paths; only qualify inline for true one-offs or std collisions

4
Cargo.lock generated
View File

@ -271,7 +271,7 @@ dependencies = [
"serde_derive",
"serde_json",
"serial_test",
"sqlite_tasks",
"sqlite_database",
"tauri",
"tauri-build",
"tauri-plugin-dialog",
@ -6320,7 +6320,7 @@ dependencies = [
]
[[package]]
name = "sqlite_tasks"
name = "sqlite_database"
version = "0.0.1"
dependencies = [
"anyhow",

View File

@ -39,8 +39,8 @@ members = [
"crates/lib/url_utils",
"crates/lib/uuid_utils",
# Schema (database): local task storage
"crates/schema/database/sqlite_tasks",
# Local task storage (SQLite, embedded migrations)
"crates/sqlite_database",
# Schema (public): common strongly-typed tokens, ids, payloads, etc.
"crates/schema/public/enums",
@ -103,7 +103,7 @@ mimetypes = { path = "crates/lib/files/mimetypes" }
openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
primitives = { path = "crates/lib/data/primitives" }
seedance2pro_client = { path = "crates/api_clients/seedance2pro_client" }
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
sqlite_database = { path = "crates/sqlite_database" }
test_data = { path = "crates/testing/test_data" }
test_utils = { path = "crates/testing/test_utils" }
tokens = { path = "crates/schema/public/tokens" }

View File

@ -43,7 +43,7 @@ helpers go in the parent `mod tests` so sub-modules can `use super::*`.
## Building
- Most crates: `cargo check -p {crate_name}` or `cargo test -p {crate_name}`
- Crates using SQLx (eg. `sqlite_tasks`): `SQLX_OFFLINE=true cargo check -p {crate_name}`
- Crates using SQLx (eg. `sqlite_database`): `SQLX_OFFLINE=true cargo check -p {crate_name}`
## Key Crates
@ -53,4 +53,4 @@ helpers go in the parent `mod tests` so sub-modules can `use super::*`.
- `seedance2pro_client` — HTTP client for the Kinovi/Seedance2Pro video generation service
- `enums` — enum variants stored as strings
- `tokens` — identifiers with Stripe-like prefixes (e.g. `user_`, `mf_`)
- `sqlite_tasks` — SQLx queries for the desktop app's local task database
- `sqlite_database` — SQLx queries + embedded migrations for the desktop app's local task database

View File

@ -42,7 +42,7 @@ midjourney_client.workspace = true
mimetypes.workspace = true
openai_sora_client.workspace = true
primitives.workspace = true
sqlite_tasks.workspace = true
sqlite_database.workspace = true
tokens.workspace = true
url_utils.workspace = true
web_base64.workspace = true

View File

@ -40,7 +40,7 @@ use openai_sora_client::recipes::image_upload_from_file_with_session_auto_renew:
use openai_sora_client::recipes::maybe_upgrade_or_renew_session::maybe_upgrade_or_renew_session;
use openai_sora_client::requests::image_gen::common::{ImageSize, NumImages};
use serde_derive::{Deserialize, Serialize};
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use std::time::Duration;
use tauri::{AppHandle, Manager, State};
use tokens::tokens::media_files::MediaFileToken;

View File

@ -38,7 +38,7 @@ use openai_sora_client::recipes::image_upload_from_file_with_session_auto_renew:
use openai_sora_client::recipes::maybe_upgrade_or_renew_session::maybe_upgrade_or_renew_session;
use openai_sora_client::requests::image_gen::common::{ImageSize, NumImages};
use serde_derive::{Deserialize, Serialize};
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use std::time::Duration;
use tauri::{AppHandle, Manager, State};
use tokens::tokens::media_files::MediaFileToken;

View File

@ -34,7 +34,7 @@ use enums::common::generation_provider::GenerationProvider;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use log::{error, info, warn};
use serde::{Deserialize, Serialize};
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use tauri::{AppHandle, State};
use tokens::tokens::media_files::MediaFileToken;

View File

@ -31,7 +31,7 @@ use openai_sora_client::recipes::image_upload_from_file_with_session_auto_renew:
use openai_sora_client::recipes::maybe_upgrade_or_renew_session::maybe_upgrade_or_renew_session;
use openai_sora_client::requests::image_gen::common::{ImageSize, NumImages};
use serde_derive::{Deserialize, Serialize};
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use std::time::Duration;
use artcraft_client::endpoints::media_files::get_media_file::get_media_file;
use artcraft_client::error::storyteller_error::StorytellerError;

View File

@ -26,7 +26,7 @@ use enums::common::generation_provider::GenerationProvider;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use log::{error, info, warn};
use serde::{Deserialize, Serialize};
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use tauri::{AppHandle, State};
use tokens::tokens::media_files::MediaFileToken;
use crate::core::state::artcraft_usage_tracker::artcraft_usage_tracker::ArtcraftUsageTracker;

View File

@ -5,8 +5,8 @@ use enums::tauri::tasks::task_model_type::TaskModelType;
use enums::tauri::tasks::task_status::TaskStatus;
use enums::tauri::tasks::task_type::TaskType;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use sqlite_tasks::error::SqliteTasksError;
use sqlite_tasks::queries::create_task::{create_task, CreateTaskArgs};
use sqlite_database::error::SqliteTasksError;
use sqlite_database::queries::create_task::{create_task, CreateTaskArgs};
use tokens::tokens::prompts::PromptToken;
use tokens::tokens::sqlite::tasks::TaskId;

View File

@ -15,7 +15,7 @@ use enums::tauri::tasks::task_type::TaskType;
use errors::AnyhowResult;
use log::{debug, error, info, warn};
use serde_derive::{Deserialize, Serialize};
use sqlite_tasks::queries::list_tasks_for_frontend::list_tasks_for_frontend;
use sqlite_database::queries::list_tasks_for_frontend::list_tasks_for_frontend;
use artcraft_client::endpoints::media_files::delete_media_file::delete_media_file;
use tauri::{AppHandle, State};
use enums::tauri::tasks::task_failure_type::TaskFailureType;

View File

@ -11,8 +11,8 @@ use chrono::{DateTime, Utc};
use errors::AnyhowResult;
use log::{error, info, warn};
use serde_derive::{Deserialize, Serialize};
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_database::queries::list_tasks_for_frontend::list_tasks_for_frontend;
use sqlite_database::queries::mark_task_as_dismissed::mark_task_as_dismissed;
use artcraft_client::endpoints::media_files::delete_media_file::delete_media_file;
use tauri::{AppHandle, State};
use tokens::tokens::media_files::MediaFileToken;

View File

@ -11,10 +11,10 @@ use chrono::{DateTime, Utc};
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 sqlite_database::queries::dismiss_all_tasks::dismiss_all_tasks;
use sqlite_database::queries::list_tasks_for_frontend::list_tasks_for_frontend;
use sqlite_database::queries::mark_task_as_dismissed::mark_task_as_dismissed;
use sqlite_database::queries::nuke_all_tasks::nuke_all_tasks;
use artcraft_client::endpoints::media_files::delete_media_file::delete_media_file;
use tauri::{AppHandle, State};
use tokens::tokens::media_files::MediaFileToken;

View File

@ -1,6 +1,6 @@
use crate::core::state::data_dir::app_data_root::AppDataRoot;
use errors::AnyhowResult;
use sqlite_tasks::connection::TaskDbConnection;
use sqlite_database::connection::TaskDbConnection;
#[derive(Clone)]
pub struct TaskDatabase {

View File

@ -17,7 +17,7 @@ use enums::tauri::tasks::task_media_file_class::TaskMediaFileClass;
use enums::tauri::tasks::task_model_type::TaskModelType;
use enums::tauri::tasks::task_type::TaskType;
use log::{error, info, warn};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::task::Task;
use tauri::AppHandle;
use reqwest::Url;
use tokens::tokens::batch_generations::BatchGenerationToken;

View File

@ -26,8 +26,8 @@ use enums::tauri::tasks::task_type::TaskType;
use fal_client::polling::poll_job_response::poll_job_response::PollJobResponse;
use fal_client::polling::poll_job_response::success_case_extractors::PollResponseExtractedContents;
use log::{error, info, warn};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{
update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs,
};
use std::fs::File;

View File

@ -5,8 +5,8 @@ use crate::core::state::task_database::TaskDatabase;
use enums::tauri::tasks::task_status::TaskStatus;
use enums::tauri::tasks::task_type::TaskType;
use log::{error, info};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use tauri::AppHandle;
pub async fn handle_fal_failure(

View File

@ -12,8 +12,8 @@ use fal_client::creds::fal_api_key::FalApiKey;
use fal_client::polling::poll_job_response::poll_job_response::{poll_job_response, PollJobResponseArgs};
use fal_client::polling::poll_job_status::poll_job_status::{poll_job_status, FalJobStatus, PollJobStatusArgs};
use log::{error, info, warn};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use tauri::AppHandle;
pub async fn poll_fal_tasks(

View File

@ -7,10 +7,10 @@ use crate::core::utils::task_database_pending_statuses::TASK_DATABASE_PENDING_ST
use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager;
use enums::common::generation_provider::GenerationProvider;
use log::{error, info, warn};
use sqlite_tasks::queries::list_non_artcraft_pending_tasks::{
use sqlite_database::queries::list_non_artcraft_pending_tasks::{
list_non_artcraft_pending_tasks, ListNonArtcraftPendingTasksArgs,
};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::task::Task;
use std::time::Duration;
use tauri::AppHandle;
@ -120,11 +120,11 @@ async fn poll_iteration(
#[derive(Debug)]
enum PollError {
SqliteTasksError(sqlite_tasks::error::SqliteTasksError),
SqliteTasksError(sqlite_database::error::SqliteTasksError),
}
impl From<sqlite_tasks::error::SqliteTasksError> for PollError {
fn from(err: sqlite_tasks::error::SqliteTasksError) -> Self {
impl From<sqlite_database::error::SqliteTasksError> for PollError {
fn from(err: sqlite_database::error::SqliteTasksError) -> Self {
Self::SqliteTasksError(err)
}
}

View File

@ -26,11 +26,11 @@ use grok_consumer_client::requests::image_websocket::messages::websocket_client_
use grok_consumer_client::requests::image_websocket::prompt_websocket_image::{prompt_websocket_image, PromptWebsocketImageArgs};
use uuid_utils::uuid::generate_random_uuid;
use log::{error, info, warn};
use sqlite_tasks::queries::get_task_by_provider_and_provider_job_id::{get_task_by_provider_and_provider_job_id, GetTaskByProviderAndProviderJobIdArgs};
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_tasks::queries::update_successful_task_status_with_metadata_by_provider::{update_successful_task_status_with_metadata_by_provider, UpdateSuccessfulTaskByProviderArgs};
use sqlite_database::queries::get_task_by_provider_and_provider_job_id::{get_task_by_provider_and_provider_job_id, GetTaskByProviderAndProviderJobIdArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::update_successful_task_status_with_metadata_by_provider::{update_successful_task_status_with_metadata_by_provider, UpdateSuccessfulTaskByProviderArgs};
use std::time::Duration;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use artcraft_client::endpoints::media_files::get_media_file::get_media_file;

View File

@ -31,10 +31,10 @@ use midjourney_client::endpoints::imagine::{imagine, ImagineItem, ImagineRequest
use midjourney_client::utils::get_image_url::get_image_url;
use midjourney_client::utils::image_downloader_client::ImageDownloaderClient;
use once_cell::sync::Lazy;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;

View File

@ -7,8 +7,8 @@ use enums::tauri::tasks::task_type::TaskType;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use errors::AnyhowResult;
use log::{error, warn};
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use artcraft_client::endpoints::media_files::list_batch_generated_redux_media_files::list_batch_generated_redux_media_files;
use tauri::AppHandle;

View File

@ -25,10 +25,10 @@ use midjourney_client::endpoints::imagine::{imagine, ImagineItem, ImagineRequest
use midjourney_client::utils::get_image_url::get_image_url;
use midjourney_client::utils::image_downloader_client::ImageDownloaderClient;
use once_cell::sync::Lazy;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;

View File

@ -11,8 +11,8 @@ use errors::AnyhowResult;
use log::info;
use openai_sora_client::requests::common::task_id::TaskId;
use openai_sora_client::requests::list_classic_tasks::list_classic_tasks::PartialTaskResponse;
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::HashMap;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use tauri::AppHandle;
@ -24,14 +24,14 @@ pub struct FailedGeneration {
pub async fn handle_classic_failed_generations(
app_handle: &AppHandle,
task_database: &TaskDatabase,
local_sqlite_tasks_by_sora_task_id: &HashMap<String, Task>,
local_sqlite_database_by_sora_task_id: &HashMap<String, Task>,
sora_failed_tasks_by_id: &HashMap<TaskId, FailedGeneration>,
sora_task_queue: &SoraTaskQueue,
) -> AnyhowResult<()> {
for (task_id, task) in sora_failed_tasks_by_id.iter() {
// Emit events for failed tasks.
if local_sqlite_tasks_by_sora_task_id.contains_key(task_id.as_str()) {
if local_sqlite_database_by_sora_task_id.contains_key(task_id.as_str()) {
let event = GenerationFailedEvent {
action: GenerationAction::GenerateImage,
service: GenerationServiceProvider::Sora,
@ -43,7 +43,7 @@ pub async fn handle_classic_failed_generations(
}
// Clear from SQLite task database.
if let Some(local_task) = local_sqlite_tasks_by_sora_task_id.get(task_id.as_str()) {
if let Some(local_task) = local_sqlite_database_by_sora_task_id.get(task_id.as_str()) {
info!("Marking local task as failed: {:?}", local_task.id);
let _updated = update_task_status(UpdateTaskArgs {

View File

@ -27,10 +27,10 @@ use openai_sora_client::recipes::list_classic_sora_tasks_with_session_auto_renew
use openai_sora_client::requests::common::task_id::TaskId;
use openai_sora_client::requests::list_classic_tasks::list_classic_tasks::{PartialGeneration, PartialTaskResponse};
use reqwest::Url;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;
@ -62,12 +62,12 @@ pub async fn handle_classic_successful_generations(
task_database: &TaskDatabase,
storyteller_creds: &StorytellerCredentialSet,
succeeded_tasks_by_id: &HashMap<TaskId, SuccessfulGeneration>,
sqlite_tasks_by_sora_task_id: &HashMap<String, Task>,
sqlite_database_by_sora_task_id: &HashMap<String, Task>,
recommended_download_extension: DownloadExtension,
) -> AnyhowResult<()> {
for (task_id, generation) in succeeded_tasks_by_id.iter() {
if !sqlite_tasks_by_sora_task_id.contains_key(task_id.as_str()) {
if !sqlite_database_by_sora_task_id.contains_key(task_id.as_str()) {
continue; // Task is irrelevant - previously completed, generated elsewhere, etc.
}
@ -128,7 +128,7 @@ pub async fn handle_classic_successful_generations(
}
// Clear from SQLite task database.
if let Some(local_task) = sqlite_tasks_by_sora_task_id.get(task_id.as_str()) {
if let Some(local_task) = sqlite_database_by_sora_task_id.get(task_id.as_str()) {
info!("Marking local task as succeeded: {:?}", local_task.id);
let generation_class = match generation_type {

View File

@ -25,9 +25,9 @@ use openai_sora_client::recipes::list_classic_sora_tasks_with_session_auto_renew
use openai_sora_client::requests::common::task_id::TaskId;
use openai_sora_client::requests::list_classic_tasks::list_classic_tasks::TaskStatus;
use reqwest::Url;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;
@ -46,7 +46,7 @@ pub async fn poll_classic_sora_tasks(
storyteller_creds_manager: &StorytellerCredentialManager,
sora_task_queue: &SoraTaskQueue,
app_data_root: &AppDataRoot,
local_sqlite_tasks_by_sora_task_id: &HashMap<String, Task>,
local_sqlite_database_by_sora_task_id: &HashMap<String, Task>,
) -> AnyhowResult<()> {
let (sora_response, maybe_new_creds) =
@ -103,7 +103,7 @@ pub async fn poll_classic_sora_tasks(
handle_classic_failed_generations(
&app_handle,
&task_database,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
&sora_failed_tasks_by_id,
&sora_task_queue,
).await?;
@ -116,7 +116,7 @@ pub async fn poll_classic_sora_tasks(
&task_database,
&storyteller_creds,
&sora_succeeded_tasks_by_id,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
DownloadExtension::Png,
).await?;

View File

@ -27,9 +27,9 @@ use openai_sora_client::requests::common::task_id::TaskId;
use openai_sora_client::requests::list_classic_tasks::list_classic_tasks::TaskStatus;
use openai_sora_client::requests::list_sora2_drafts::list_sora2_drafts::Draft;
use reqwest::Url;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;
@ -48,7 +48,7 @@ pub async fn poll_sora_2_tasks(
storyteller_creds_manager: &StorytellerCredentialManager,
sora_task_queue: &SoraTaskQueue,
app_data_root: &AppDataRoot,
local_sqlite_tasks_by_sora_task_id: &HashMap<String, Task>,
local_sqlite_database_by_sora_task_id: &HashMap<String, Task>,
) -> AnyhowResult<()> {
let (sora_response, maybe_new_creds) =
@ -95,7 +95,7 @@ pub async fn poll_sora_2_tasks(
handle_classic_failed_generations(
&app_handle,
&task_database,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
&sora_failed_drafts_by_id,
&sora_task_queue,
).await?;
@ -108,7 +108,7 @@ pub async fn poll_sora_2_tasks(
&task_database,
&storyteller_creds,
&sora_succeeded_drafts_by_id,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
DownloadExtension::Mp4,
).await?;

View File

@ -26,9 +26,9 @@ use openai_sora_client::recipes::list_classic_sora_tasks_with_session_auto_renew
use openai_sora_client::requests::common::task_id::TaskId;
use openai_sora_client::requests::list_classic_tasks::list_classic_tasks::TaskStatus;
use reqwest::Url;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;
@ -74,13 +74,13 @@ async fn local_task_polling_loop(
app_data_root: &AppDataRoot,
) -> AnyhowResult<()> {
loop {
let local_sqlite_tasks = list_tasks_by_provider_and_status(ListTasksByProviderAndStatusArgs {
let local_sqlite_database = list_tasks_by_provider_and_status(ListTasksByProviderAndStatusArgs {
db: task_database.get_connection(),
provider: GenerationProvider::Sora,
task_statuses: &TASK_DATABASE_PENDING_STATUSES,
}).await?;
if local_sqlite_tasks.tasks.is_empty() {
if local_sqlite_database.tasks.is_empty() {
// No need to poll if we don't have pending tasks.
tokio::time::sleep(std::time::Duration::from_millis(2_000)).await;
continue;
@ -89,7 +89,7 @@ async fn local_task_polling_loop(
let creds = sora_creds_manager.get_credentials_required()?;
// Map of Sora Task ID to Local Task.
let local_sqlite_tasks_by_sora_task_id = local_sqlite_tasks.tasks.iter()
let local_sqlite_database_by_sora_task_id = local_sqlite_database.tasks.iter()
.filter_map(|task| {
if let Some(provider_job_id) = &task.provider_job_id {
Some((provider_job_id.clone(), task.clone()))
@ -110,7 +110,7 @@ async fn local_task_polling_loop(
&storyteller_creds_manager,
&sora_task_queue,
&app_data_root,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
).await?;
// TODO: Only poll if we have new items
@ -124,7 +124,7 @@ async fn local_task_polling_loop(
&storyteller_creds_manager,
&sora_task_queue,
&app_data_root,
&local_sqlite_tasks_by_sora_task_id,
&local_sqlite_database_by_sora_task_id,
).await?;
tokio::time::sleep(std::time::Duration::from_millis(2_000)).await;

View File

@ -9,7 +9,7 @@ use artcraft_client::error::api_error::ApiError;
use artcraft_client::error::storyteller_error::StorytellerError;
use errors::AnyhowResult;
use log::{debug, error, info};
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use std::time::Instant;
use tokens::tokens::app_session::AppSessionToken;

View File

@ -12,8 +12,8 @@ use artcraft_client::api_defs::utils::media_links_to_thumbnail_template::media_l
use enums::tauri::tasks::task_type::TaskType;
use errors::AnyhowResult;
use log::{error, warn};
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::task::Task;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use artcraft_client::endpoints::media_files::list_batch_generated_redux_media_files::list_batch_generated_redux_media_files;
use tauri::AppHandle;

View File

@ -9,8 +9,8 @@ use enums::tauri::tasks::task_type::TaskType;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use errors::AnyhowResult;
use log::{error, warn};
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::task::Task;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use artcraft_client::endpoints::media_files::list_batch_generated_redux_media_files::list_batch_generated_redux_media_files;
use tauri::AppHandle;

View File

@ -7,8 +7,8 @@ use enums::tauri::tasks::task_type::TaskType;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use errors::AnyhowResult;
use log::{error, warn};
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::task::Task;
use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet;
use artcraft_client::endpoints::media_files::list_batch_generated_redux_media_files::list_batch_generated_redux_media_files;
use tauri::AppHandle;

View File

@ -6,8 +6,8 @@ use enums::tauri::tasks::task_type::TaskType;
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
use errors::AnyhowResult;
use log::error;
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::task::Task;
use tokens::tokens::media_files::MediaFileToken;
pub async fn maybe_send_background_removal_complete_event(

View File

@ -7,11 +7,11 @@ use artcraft_client::api_defs::jobs::list_session_jobs::ListSessionJobsItem;
use enums::tauri::tasks::task_status::TaskStatus;
use errors::AnyhowResult;
use log::info;
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use tauri::AppHandle;
use enums::tauri::tasks::task_failure_type::TaskFailureType;
use sqlite_tasks::queries::update_task_status_with_rich_failure::{update_task_status_with_rich_failure, UpdateTaskWithRichFailureArgs};
use sqlite_database::queries::update_task_status_with_rich_failure::{update_task_status_with_rich_failure, UpdateTaskWithRichFailureArgs};
pub async fn handle_failed_job(
app_handle: &AppHandle,

View File

@ -15,8 +15,8 @@ use enums::tauri::tasks::task_media_file_class::TaskMediaFileClass;
use errors::AnyhowResult;
use log::error;
use log::info;
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use tauri::AppHandle;
use tokens::tokens::media_files::MediaFileToken;

View File

@ -12,8 +12,8 @@ use enums::common::job_status_plus::JobStatusPlus;
use enums::tauri::tasks::task_status::TaskStatus;
use errors::AnyhowResult;
use log::error;
use sqlite_tasks::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_tasks::queries::task::Task;
use sqlite_database::queries::list_tasks_by_provider_and_tokens::{list_tasks_by_provider_and_tokens, ListTasksArgs};
use sqlite_database::queries::task::Task;
use std::collections::HashMap;
use tauri::AppHandle;

View File

@ -33,10 +33,10 @@ use midjourney_client::endpoints::imagine::{imagine, ImagineItem, ImagineRequest
use midjourney_client::utils::get_image_url::get_image_url;
use midjourney_client::utils::image_downloader_client::ImageDownloaderClient;
use once_cell::sync::Lazy;
use sqlite_tasks::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_tasks::queries::task::Task;
use sqlite_tasks::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_tasks::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use sqlite_database::queries::list_tasks_by_provider_and_status::{list_tasks_by_provider_and_status, ListTasksByProviderAndStatusArgs, TaskList};
use sqlite_database::queries::task::Task;
use sqlite_database::queries::update_successful_task_status_with_metadata::{update_successful_task_status_with_metadata, UpdateSuccessfulTaskArgs};
use sqlite_database::queries::update_task_status::{update_task_status, UpdateTaskArgs};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Write;

View File

@ -1,5 +1,5 @@
[package]
name = "sqlite_tasks"
name = "sqlite_database"
edition = "2024"
version = "0.0.1"
publish = false
@ -8,7 +8,7 @@ publish = false
normal = ["workspace-build-acceleration"]
[lib]
name = "sqlite_tasks"
name = "sqlite_database"
path = "src/lib.rs"
[dependencies]

View File

@ -28,9 +28,9 @@ impl TaskDbConnection {
// NB: Scope change here is an attempt to drop the open file connection for Windows.
// On Windows, we've observed that the file might still be open, preventing deletion:
// [2025-08-08][06:42:29][sqlite_tasks::connection][INFO] Deleting and recreating SQLite
// [2025-08-08][06:42:29][sqlite_database::connection][INFO] Deleting and recreating SQLite
// database at "C:\Users\User\Artcraft\state\tasks_v2.sqlite"
// [2025-08-08][06:42:29][sqlite_tasks::connection][ERROR] Error deleting SQLite database
// [2025-08-08][06:42:29][sqlite_database::connection][ERROR] Error deleting SQLite database
// file: Os { code: 32, kind: Uncategorized, message: "The process cannot access the file
// because it is being used by another process." }
}
@ -58,7 +58,7 @@ async fn run_migrations<P: AsRef<Path>>(database_file: P) -> Result<SqlitePool,
// The migrations text get compiled into the binary, so no worries about build inclusion.
// Since the task database is being treated as ephemeral, we can always run migrations without
// worrying about previous state if we simply blow away old versions of the schema.
sqlx::migrate!("../../../../_database/sql/artcraft_migrations").run(&pool).await?;
sqlx::migrate!().run(&pool).await?;
Ok(pool)
}

View File

@ -1,4 +1,4 @@
//! sqlite_tasks
//! sqlite_database
//!
//! sqlx is happier with different compilation units? So be it!
//!

View File

@ -31,7 +31,7 @@ sqlx_migrate() {
echo "SQLx migrate database file..."
sqlx migrate run \
--database-url "sqlite:${sqlite_db_file}" \
--source "${root_dir}/_database/sql/artcraft_migrations"
--source "${root_dir}/crates/sqlite_database/migrations"
export DATABASE_URL="sqlite:${sqlite_db_file}"
}

View File

@ -32,7 +32,7 @@ sqlx_migrate() {
echo "SQLx migrate database file..."
sqlx migrate run \
--database-url "sqlite:${sqlite_db_file}" \
--source "${root_dir}/_database/sql/artcraft_migrations"
--source "${root_dir}/crates/sqlite_database/migrations"
export DATABASE_URL="sqlite:${sqlite_db_file}"
}