pub struct Database { /* private fields */ }Expand description
Database handle for usenet-dl
Implementations§
Source§impl Database
impl Database
Sourcepub async fn insert_article(&self, article: &NewArticle) -> Result<i64>
pub async fn insert_article(&self, article: &NewArticle) -> Result<i64>
Insert a single article
Sourcepub async fn insert_articles_batch(&self, articles: &[NewArticle]) -> Result<()>
pub async fn insert_articles_batch(&self, articles: &[NewArticle]) -> Result<()>
Insert multiple articles in a batch (more efficient for large NZB files)
Automatically chunks the input to stay within SQLite’s bind variable limit (5 variables per article, chunked to max 199 articles per INSERT).
Sourcepub async fn update_article_status(
&self,
article_id: i64,
status: i32,
) -> Result<()>
pub async fn update_article_status( &self, article_id: i64, status: i32, ) -> Result<()>
Update article status
Sourcepub async fn update_article_status_by_message_id(
&self,
download_id: DownloadId,
message_id: &str,
status: i32,
) -> Result<()>
pub async fn update_article_status_by_message_id( &self, download_id: DownloadId, message_id: &str, status: i32, ) -> Result<()>
Update article status by message_id
Sourcepub async fn update_articles_status_batch(
&self,
updates: &[(i64, i32)],
) -> Result<()>
pub async fn update_articles_status_batch( &self, updates: &[(i64, i32)], ) -> Result<()>
Update multiple article statuses in a single transaction (more efficient for batch operations)
§Arguments
updates- Vector of tuples containing (article_id, status)
§Performance
This method uses a CASE-WHEN statement to update multiple rows in a single query,
which is significantly faster than individual UPDATE statements. With 100 updates,
this can be 50-100x faster than calling update_article_status 100 times.
§Example
let updates = vec![
(123, article_status::DOWNLOADED),
(124, article_status::DOWNLOADED),
(125, article_status::FAILED),
];
db.update_articles_status_batch(&updates).await?;Update multiple article statuses in a single transaction (more efficient for batch operations)
Automatically chunks the input to stay within SQLite’s bind variable limit. Each update uses ~3-4 bind variables (article_id x3 + optional timestamp), so we chunk to max 100 updates per query.
Sourcepub async fn get_articles(
&self,
download_id: DownloadId,
) -> Result<Vec<Article>>
pub async fn get_articles( &self, download_id: DownloadId, ) -> Result<Vec<Article>>
Get all articles for a download
Sourcepub async fn get_pending_articles(
&self,
download_id: DownloadId,
) -> Result<Vec<Article>>
pub async fn get_pending_articles( &self, download_id: DownloadId, ) -> Result<Vec<Article>>
Get pending articles for a download, excluding paused files.
Sourcepub async fn get_article_by_message_id(
&self,
download_id: DownloadId,
message_id: &str,
) -> Result<Option<Article>>
pub async fn get_article_by_message_id( &self, download_id: DownloadId, message_id: &str, ) -> Result<Option<Article>>
Get article by message_id
Sourcepub async fn count_articles_by_status(
&self,
download_id: DownloadId,
status: i32,
) -> Result<i64>
pub async fn count_articles_by_status( &self, download_id: DownloadId, status: i32, ) -> Result<i64>
Count articles by status for a download
Sourcepub async fn count_articles(&self, download_id: DownloadId) -> Result<i64>
pub async fn count_articles(&self, download_id: DownloadId) -> Result<i64>
Get total article count for a download
Sourcepub async fn delete_articles(&self, download_id: DownloadId) -> Result<()>
pub async fn delete_articles(&self, download_id: DownloadId) -> Result<()>
Delete all articles for a download (automatic via CASCADE, but explicit method for clarity)
Sourcepub async fn insert_files_batch(&self, files: &[NewDownloadFile]) -> Result<()>
pub async fn insert_files_batch(&self, files: &[NewDownloadFile]) -> Result<()>
Insert multiple download files in a batch
Sourcepub async fn get_download_files(
&self,
download_id: DownloadId,
) -> Result<Vec<DownloadFile>>
pub async fn get_download_files( &self, download_id: DownloadId, ) -> Result<Vec<DownloadFile>>
Get all download files for a download
Sourcepub async fn get_newly_completed_files(
&self,
download_id: DownloadId,
) -> Result<Vec<DownloadFile>>
pub async fn get_newly_completed_files( &self, download_id: DownloadId, ) -> Result<Vec<DownloadFile>>
Get newly completed files for DirectUnpack processing.
Returns unpaused files where completed=0 and all articles have been downloaded.
Sourcepub async fn mark_file_completed(
&self,
download_id: DownloadId,
file_index: i32,
) -> Result<()>
pub async fn mark_file_completed( &self, download_id: DownloadId, file_index: i32, ) -> Result<()>
Mark a file as completed (all segments downloaded)
Sourcepub async fn update_direct_unpack_state(
&self,
download_id: DownloadId,
state: i32,
) -> Result<()>
pub async fn update_direct_unpack_state( &self, download_id: DownloadId, state: i32, ) -> Result<()>
Update the DirectUnpack state for a download
Sourcepub async fn get_direct_unpack_state(
&self,
download_id: DownloadId,
) -> Result<i32>
pub async fn get_direct_unpack_state( &self, download_id: DownloadId, ) -> Result<i32>
Get the DirectUnpack state for a download
Sourcepub async fn rename_download_file(
&self,
download_id: DownloadId,
file_index: i32,
new_filename: &str,
) -> Result<()>
pub async fn rename_download_file( &self, download_id: DownloadId, file_index: i32, new_filename: &str, ) -> Result<()>
Rename a download file (for DirectRename), storing the original filename
Sourcepub async fn update_direct_unpack_extracted_count(
&self,
download_id: DownloadId,
count: i32,
) -> Result<()>
pub async fn update_direct_unpack_extracted_count( &self, download_id: DownloadId, count: i32, ) -> Result<()>
Update the DirectUnpack extracted count for a download
Sourcepub async fn get_direct_unpack_extracted_count(
&self,
download_id: DownloadId,
) -> Result<i32>
pub async fn get_direct_unpack_extracted_count( &self, download_id: DownloadId, ) -> Result<i32>
Get the DirectUnpack extracted count for a download
Sourcepub async fn set_file_paused(
&self,
download_id: DownloadId,
file_index: i32,
paused: bool,
) -> Result<()>
pub async fn set_file_paused( &self, download_id: DownloadId, file_index: i32, paused: bool, ) -> Result<()>
Set a file’s paused state.
Sourcepub async fn get_download_file(
&self,
download_id: DownloadId,
file_index: i32,
) -> Result<Option<DownloadFile>>
pub async fn get_download_file( &self, download_id: DownloadId, file_index: i32, ) -> Result<Option<DownloadFile>>
Get a single download file by download and file index.
Sourcepub async fn has_active_pending_articles(
&self,
download_id: DownloadId,
) -> Result<bool>
pub async fn has_active_pending_articles( &self, download_id: DownloadId, ) -> Result<bool>
Return true when a download still has unpaused pending articles.
Sourcepub async fn has_any_pending_articles(
&self,
download_id: DownloadId,
) -> Result<bool>
pub async fn has_any_pending_articles( &self, download_id: DownloadId, ) -> Result<bool>
Return true when a download still has any pending articles, including paused files.
Sourcepub async fn count_failed_articles(
&self,
download_id: DownloadId,
) -> Result<i64>
pub async fn count_failed_articles( &self, download_id: DownloadId, ) -> Result<i64>
Count failed articles for a download
Source§impl Database
impl Database
Sourcepub async fn insert_download(
&self,
download: &NewDownload,
) -> Result<DownloadId>
pub async fn insert_download( &self, download: &NewDownload, ) -> Result<DownloadId>
Insert a new download record
Sourcepub async fn get_download(&self, id: DownloadId) -> Result<Option<Download>>
pub async fn get_download(&self, id: DownloadId) -> Result<Option<Download>>
Get a download by ID
Sourcepub async fn list_downloads(&self) -> Result<Vec<Download>>
pub async fn list_downloads(&self) -> Result<Vec<Download>>
List all downloads
Sourcepub async fn list_downloads_by_status(
&self,
status: i32,
) -> Result<Vec<Download>>
pub async fn list_downloads_by_status( &self, status: i32, ) -> Result<Vec<Download>>
List downloads with a specific status
Sourcepub async fn update_status(&self, id: DownloadId, status: i32) -> Result<()>
pub async fn update_status(&self, id: DownloadId, status: i32) -> Result<()>
Update download status
Sourcepub async fn update_progress(
&self,
id: DownloadId,
progress: f32,
speed_bps: u64,
downloaded_bytes: u64,
) -> Result<()>
pub async fn update_progress( &self, id: DownloadId, progress: f32, speed_bps: u64, downloaded_bytes: u64, ) -> Result<()>
Update download progress
Sourcepub async fn update_priority(&self, id: DownloadId, priority: i32) -> Result<()>
pub async fn update_priority(&self, id: DownloadId, priority: i32) -> Result<()>
Update download priority
Sourcepub async fn set_error(&self, id: DownloadId, error: &str) -> Result<()>
pub async fn set_error(&self, id: DownloadId, error: &str) -> Result<()>
Set download error message
Sourcepub async fn set_started(&self, id: DownloadId) -> Result<()>
pub async fn set_started(&self, id: DownloadId) -> Result<()>
Set download started timestamp
Sourcepub async fn set_completed(&self, id: DownloadId) -> Result<()>
pub async fn set_completed(&self, id: DownloadId) -> Result<()>
Set download completed timestamp
Sourcepub async fn delete_download(&self, id: DownloadId) -> Result<()>
pub async fn delete_download(&self, id: DownloadId) -> Result<()>
Delete a download
Sourcepub async fn get_incomplete_downloads(&self) -> Result<Vec<Download>>
pub async fn get_incomplete_downloads(&self) -> Result<Vec<Download>>
Get incomplete downloads (for resume on startup)
Sourcepub async fn get_all_downloads(&self) -> Result<Vec<Download>>
pub async fn get_all_downloads(&self) -> Result<Vec<Download>>
Get all downloads (for state persistence during shutdown)
Source§impl Database
impl Database
Sourcepub async fn find_by_nzb_hash(&self, nzb_hash: &str) -> Result<Option<Download>>
pub async fn find_by_nzb_hash(&self, nzb_hash: &str) -> Result<Option<Download>>
Find a download by NZB hash
This is the most reliable duplicate detection method as it compares the actual NZB file content (via SHA-256 hash).
Source§impl Database
impl Database
Sourcepub async fn insert_history(&self, entry: &NewHistoryEntry) -> Result<i64>
pub async fn insert_history(&self, entry: &NewHistoryEntry) -> Result<i64>
Insert a download into history
This is typically called when a download is completed (successfully or failed) to create a historical record separate from the active downloads table.
Sourcepub async fn query_history(
&self,
status_filter: Option<i32>,
limit: usize,
offset: usize,
) -> Result<Vec<HistoryEntry>>
pub async fn query_history( &self, status_filter: Option<i32>, limit: usize, offset: usize, ) -> Result<Vec<HistoryEntry>>
Query history with pagination and optional status filter
Returns history entries ordered by completion time (most recent first). Use limit and offset for pagination.
Sourcepub async fn count_history(&self, status_filter: Option<i32>) -> Result<i64>
pub async fn count_history(&self, status_filter: Option<i32>) -> Result<i64>
Count history entries (optionally filtered by status)
Useful for pagination - returns total count of records matching the filter.
Sourcepub async fn delete_history_before(&self, before_timestamp: i64) -> Result<u64>
pub async fn delete_history_before(&self, before_timestamp: i64) -> Result<u64>
Delete history entries older than the specified timestamp
Returns the number of records deleted. This is useful for cleanup - e.g., delete history older than 30 days.
Sourcepub async fn delete_history_by_status(&self, status: i32) -> Result<u64>
pub async fn delete_history_by_status(&self, status: i32) -> Result<u64>
Delete history entries with a specific status
Returns the number of records deleted. This is useful for cleanup - e.g., delete all failed downloads from history.
Sourcepub async fn clear_history(&self) -> Result<u64>
pub async fn clear_history(&self) -> Result<u64>
Clear all history
Returns the number of records deleted. This is a destructive operation - use with caution.
Sourcepub async fn delete_history_filtered(
&self,
before_timestamp: Option<i64>,
status: Option<i32>,
) -> Result<u64>
pub async fn delete_history_filtered( &self, before_timestamp: Option<i64>, status: Option<i32>, ) -> Result<u64>
Delete history entries with optional filters
Returns the number of records deleted. Supports filtering by:
- before_timestamp: Delete entries completed before this timestamp
- status: Delete only entries with this status
If both filters are None, deletes all history (same as clear_history).
Sourcepub async fn get_history_entry(&self, id: i64) -> Result<Option<HistoryEntry>>
pub async fn get_history_entry(&self, id: i64) -> Result<Option<HistoryEntry>>
Get a single history entry by ID
Source§impl Database
impl Database
Sourcepub async fn set_correct_password(
&self,
download_id: DownloadId,
password: &str,
) -> Result<()>
pub async fn set_correct_password( &self, download_id: DownloadId, password: &str, ) -> Result<()>
Cache a correct password for a download
This is used after successfully extracting an archive with a password, so if the download needs to be reprocessed, we can try this password first.
Sourcepub async fn get_cached_password(
&self,
download_id: DownloadId,
) -> Result<Option<String>>
pub async fn get_cached_password( &self, download_id: DownloadId, ) -> Result<Option<String>>
Get the cached correct password for a download
Returns None if no password is cached for this download.
Sourcepub async fn delete_cached_password(
&self,
download_id: DownloadId,
) -> Result<()>
pub async fn delete_cached_password( &self, download_id: DownloadId, ) -> Result<()>
Delete cached password for a download
Note: This is automatically deleted via CASCADE when the download is deleted.
Source§impl Database
impl Database
Sourcepub async fn get_all_rss_feeds(&self) -> Result<Vec<RssFeed>>
pub async fn get_all_rss_feeds(&self) -> Result<Vec<RssFeed>>
Get all RSS feeds
Sourcepub async fn insert_rss_feed(
&self,
params: InsertRssFeedParams<'_>,
) -> Result<i64>
pub async fn insert_rss_feed( &self, params: InsertRssFeedParams<'_>, ) -> Result<i64>
Insert a new RSS feed
Sourcepub async fn update_rss_feed(
&self,
params: UpdateRssFeedParams<'_>,
) -> Result<bool>
pub async fn update_rss_feed( &self, params: UpdateRssFeedParams<'_>, ) -> Result<bool>
Update an existing RSS feed
Sourcepub async fn delete_rss_feed(&self, id: i64) -> Result<bool>
pub async fn delete_rss_feed(&self, id: i64) -> Result<bool>
Delete an RSS feed (cascades to filters and seen items)
Sourcepub async fn get_rss_filters(&self, feed_id: i64) -> Result<Vec<RssFilterRow>>
pub async fn get_rss_filters(&self, feed_id: i64) -> Result<Vec<RssFilterRow>>
Get all filters for a specific RSS feed
Sourcepub async fn insert_rss_filter(
&self,
params: InsertRssFilterParams<'_>,
) -> Result<i64>
pub async fn insert_rss_filter( &self, params: InsertRssFilterParams<'_>, ) -> Result<i64>
Insert a new RSS filter
Sourcepub async fn delete_rss_filters(&self, feed_id: i64) -> Result<()>
pub async fn delete_rss_filters(&self, feed_id: i64) -> Result<()>
Delete all filters for a feed (used during update)
Source§impl Database
impl Database
Sourcepub async fn was_unclean_shutdown(&self) -> Result<bool>
pub async fn was_unclean_shutdown(&self) -> Result<bool>
Check if the last shutdown was unclean
Returns true if the previous session did not call set_clean_shutdown(), indicating a crash or forced termination.
This method is called on startup to determine if state recovery is needed.
Sourcepub async fn set_clean_start(&self) -> Result<()>
pub async fn set_clean_start(&self) -> Result<()>
Mark that the application has started cleanly
This should be called during UsenetDownloader::new() to indicate that the application is running. If shutdown() is not called before the next startup, was_unclean_shutdown() will return true.
Sourcepub async fn set_clean_shutdown(&self) -> Result<()>
pub async fn set_clean_shutdown(&self) -> Result<()>
Mark that the application is shutting down cleanly
This should be called during UsenetDownloader::shutdown() to indicate a graceful shutdown. If this is not called before the process exits, the next startup will detect an unclean shutdown.
Sourcepub async fn mark_nzb_processed(&self, path: &Path) -> Result<()>
pub async fn mark_nzb_processed(&self, path: &Path) -> Result<()>
Mark an NZB file as processed
This is used by the folder watcher with WatchFolderAction::Keep to track which NZB files have already been processed to avoid re-adding them.
Sourcepub async fn is_nzb_processed(&self, path: &Path) -> Result<bool>
pub async fn is_nzb_processed(&self, path: &Path) -> Result<bool>
Check if an NZB file has been processed
Auto Trait Implementations§
impl Freeze for Database
impl !RefUnwindSafe for Database
impl Send for Database
impl Sync for Database
impl Unpin for Database
impl UnsafeUnpin for Database
impl !UnwindSafe for Database
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more