Formatting
This commit is contained in:
@@ -33,9 +33,7 @@ impl Database {
|
|||||||
.min_connections(1)
|
.min_connections(1)
|
||||||
.sqlx_logging(false);
|
.sqlx_logging(false);
|
||||||
|
|
||||||
let conn = SeaDatabase::connect(opts)
|
let conn = SeaDatabase::connect(opts).await.map_err(DbError::SeaOrm)?;
|
||||||
.await
|
|
||||||
.map_err(DbError::SeaOrm)?;
|
|
||||||
|
|
||||||
// Enable WAL mode for better concurrent read performance
|
// Enable WAL mode for better concurrent read performance
|
||||||
if database_url.starts_with("sqlite:") && !database_url.contains(":memory:") {
|
if database_url.starts_with("sqlite:") && !database_url.contains(":memory:") {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ impl MigrationTrait for Migration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(DeriveIden)]
|
#[derive(DeriveIden)]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
pub(crate) enum Artists {
|
pub(crate) enum Artists {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ impl MigrationTrait for Migration {
|
|||||||
.auto_increment()
|
.auto_increment()
|
||||||
.primary_key(),
|
.primary_key(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(Tracks::FilePath).text().not_null().unique_key())
|
.col(
|
||||||
|
ColumnDef::new(Tracks::FilePath)
|
||||||
|
.text()
|
||||||
|
.not_null()
|
||||||
|
.unique_key(),
|
||||||
|
)
|
||||||
.col(ColumnDef::new(Tracks::Title).text())
|
.col(ColumnDef::new(Tracks::Title).text())
|
||||||
.col(ColumnDef::new(Tracks::Artist).text())
|
.col(ColumnDef::new(Tracks::Artist).text())
|
||||||
.col(ColumnDef::new(Tracks::Album).text())
|
.col(ColumnDef::new(Tracks::Album).text())
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ pub async fn upsert(
|
|||||||
musicbrainz_id: Option<&str>,
|
musicbrainz_id: Option<&str>,
|
||||||
artist_id: Option<i32>,
|
artist_id: Option<i32>,
|
||||||
) -> DbResult<Album> {
|
) -> DbResult<Album> {
|
||||||
if let Some(mbid) = musicbrainz_id {
|
if let Some(mbid) = musicbrainz_id
|
||||||
if let Some(existing) = Albums::find()
|
&& let Some(existing) = Albums::find()
|
||||||
.filter(album::Column::MusicbrainzId.eq(mbid))
|
.filter(album::Column::MusicbrainzId.eq(mbid))
|
||||||
.one(db)
|
.one(db)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
return Ok(existing);
|
return Ok(existing);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(existing) = find_by_name_and_artist(db, name, album_artist).await? {
|
if let Some(existing) = find_by_name_and_artist(db, name, album_artist).await? {
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ use sea_orm::*;
|
|||||||
use crate::entities::artist::{self, ActiveModel, Entity as Artists, Model as Artist};
|
use crate::entities::artist::{self, ActiveModel, Entity as Artists, Model as Artist};
|
||||||
use crate::error::{DbError, DbResult};
|
use crate::error::{DbError, DbResult};
|
||||||
|
|
||||||
pub async fn upsert(db: &DatabaseConnection, name: &str, musicbrainz_id: Option<&str>) -> DbResult<Artist> {
|
pub async fn upsert(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
name: &str,
|
||||||
|
musicbrainz_id: Option<&str>,
|
||||||
|
) -> DbResult<Artist> {
|
||||||
// Try to find by musicbrainz_id first, then by name
|
// Try to find by musicbrainz_id first, then by name
|
||||||
if let Some(mbid) = musicbrainz_id {
|
if let Some(mbid) = musicbrainz_id
|
||||||
if let Some(existing) = Artists::find()
|
&& let Some(existing) = Artists::find()
|
||||||
.filter(artist::Column::MusicbrainzId.eq(mbid))
|
.filter(artist::Column::MusicbrainzId.eq(mbid))
|
||||||
.one(db)
|
.one(db)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
return Ok(existing);
|
return Ok(existing);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(existing) = find_by_name(db, name).await? {
|
if let Some(existing) = find_by_name(db, name).await? {
|
||||||
@@ -80,14 +83,22 @@ pub async fn update(db: &DatabaseConnection, id: i32, model: ActiveModel) -> DbR
|
|||||||
Ok(active.update(db).await?)
|
Ok(active.update(db).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_top_songs(db: &DatabaseConnection, id: i32, top_songs_json: &str) -> DbResult<Artist> {
|
pub async fn update_top_songs(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
id: i32,
|
||||||
|
top_songs_json: &str,
|
||||||
|
) -> DbResult<Artist> {
|
||||||
let existing = get_by_id(db, id).await?;
|
let existing = get_by_id(db, id).await?;
|
||||||
let mut active: ActiveModel = existing.into();
|
let mut active: ActiveModel = existing.into();
|
||||||
active.top_songs = Set(top_songs_json.to_string());
|
active.top_songs = Set(top_songs_json.to_string());
|
||||||
Ok(active.update(db).await?)
|
Ok(active.update(db).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_similar_artists(db: &DatabaseConnection, id: i32, similar_json: &str) -> DbResult<Artist> {
|
pub async fn update_similar_artists(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
id: i32,
|
||||||
|
similar_json: &str,
|
||||||
|
) -> DbResult<Artist> {
|
||||||
let existing = get_by_id(db, id).await?;
|
let existing = get_by_id(db, id).await?;
|
||||||
let mut active: ActiveModel = existing.into();
|
let mut active: ActiveModel = existing.into();
|
||||||
active.similar_artists = Set(similar_json.to_string());
|
active.similar_artists = Set(similar_json.to_string());
|
||||||
|
|||||||
@@ -106,7 +106,11 @@ pub async fn get_needing_metadata(db: &DatabaseConnection) -> DbResult<Vec<Track
|
|||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_metadata(db: &DatabaseConnection, id: i32, model: ActiveModel) -> DbResult<Track> {
|
pub async fn update_metadata(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
id: i32,
|
||||||
|
model: ActiveModel,
|
||||||
|
) -> DbResult<Track> {
|
||||||
let mut active = model;
|
let mut active = model;
|
||||||
active.id = Set(id);
|
active.id = Set(id);
|
||||||
active.updated_at = Set(Utc::now().naive_utc());
|
active.updated_at = Set(Utc::now().naive_utc());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use sea_orm::*;
|
|
||||||
use sea_orm::sea_query::Expr;
|
use sea_orm::sea_query::Expr;
|
||||||
|
use sea_orm::*;
|
||||||
|
|
||||||
use crate::entities::wanted_item::{
|
use crate::entities::wanted_item::{
|
||||||
self, ActiveModel, Entity as WantedItems, ItemType, Model as WantedItem, WantedStatus,
|
self, ActiveModel, Entity as WantedItems, ItemType, Model as WantedItem, WantedStatus,
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ use shanty_db::entities::wanted_item::{ItemType, WantedStatus};
|
|||||||
use shanty_db::{Database, queries};
|
use shanty_db::{Database, queries};
|
||||||
|
|
||||||
async fn test_db() -> Database {
|
async fn test_db() -> Database {
|
||||||
Database::new("sqlite::memory:").await.expect("failed to create test database")
|
Database::new("sqlite::memory:")
|
||||||
|
.await
|
||||||
|
.expect("failed to create test database")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -163,9 +165,17 @@ async fn test_wanted_items_lifecycle() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Add wanted item
|
// Add wanted item
|
||||||
let item = queries::wanted::add(conn, ItemType::Artist, "Radiohead", None, Some(artist.id), None, None)
|
let item = queries::wanted::add(
|
||||||
.await
|
conn,
|
||||||
.unwrap();
|
ItemType::Artist,
|
||||||
|
"Radiohead",
|
||||||
|
None,
|
||||||
|
Some(artist.id),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
assert_eq!(item.status, WantedStatus::Wanted);
|
assert_eq!(item.status, WantedStatus::Wanted);
|
||||||
assert_eq!(item.item_type, ItemType::Artist);
|
assert_eq!(item.item_type, ItemType::Artist);
|
||||||
|
|
||||||
@@ -219,14 +229,9 @@ async fn test_download_queue_lifecycle() {
|
|||||||
assert!(next.is_none());
|
assert!(next.is_none());
|
||||||
|
|
||||||
// Fail it
|
// Fail it
|
||||||
queries::downloads::update_status(
|
queries::downloads::update_status(conn, item.id, DownloadStatus::Failed, Some("network error"))
|
||||||
conn,
|
.await
|
||||||
item.id,
|
.unwrap();
|
||||||
DownloadStatus::Failed,
|
|
||||||
Some("network error"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// List failed
|
// List failed
|
||||||
let failed = queries::downloads::list(conn, Some(DownloadStatus::Failed))
|
let failed = queries::downloads::list(conn, Some(DownloadStatus::Failed))
|
||||||
@@ -236,7 +241,9 @@ async fn test_download_queue_lifecycle() {
|
|||||||
assert_eq!(failed[0].error_message.as_deref(), Some("network error"));
|
assert_eq!(failed[0].error_message.as_deref(), Some("network error"));
|
||||||
|
|
||||||
// Retry
|
// Retry
|
||||||
queries::downloads::retry_failed(conn, item.id).await.unwrap();
|
queries::downloads::retry_failed(conn, item.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let pending = queries::downloads::list(conn, Some(DownloadStatus::Pending))
|
let pending = queries::downloads::list(conn, Some(DownloadStatus::Pending))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -286,7 +293,9 @@ async fn test_search_cache_ttl() {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let purged = queries::cache::purge_prefix(conn, "artist_totals:").await.unwrap();
|
let purged = queries::cache::purge_prefix(conn, "artist_totals:")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
assert_eq!(purged, 2);
|
assert_eq!(purged, 2);
|
||||||
|
|
||||||
// other_key should still exist
|
// other_key should still exist
|
||||||
|
|||||||
Reference in New Issue
Block a user