From 005f4b5b5f1f84bc6a2be87a6b6c7c74665b75aa Mon Sep 17 00:00:00 2001 From: Tobias de Bruijn Date: Wed, 13 Mar 2024 16:19:50 +0100 Subject: [PATCH] Remove albums with no known photos --- frontend/package.json | 2 +- server/chroma/Cargo.toml | 2 +- server/chroma/src/routes/authorization.rs | 2 +- server/chroma/src/routes/v1/album/list.rs | 40 ++++++++++++++++++++--- server/dal/src/s3.rs | 4 ++- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 2040395..8769479 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "chroma", - "version": "0.1.21", + "version": "0.1.22", "private": true, "scripts": { "serve": "vue-cli-service serve --port 8008", diff --git a/server/chroma/Cargo.toml b/server/chroma/Cargo.toml index e8eed18..6cacc3f 100644 --- a/server/chroma/Cargo.toml +++ b/server/chroma/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chroma" -version = "0.1.21" +version = "0.1.22" edition = "2021" [dependencies] diff --git a/server/chroma/src/routes/authorization.rs b/server/chroma/src/routes/authorization.rs index 4c4966a..994308c 100644 --- a/server/chroma/src/routes/authorization.rs +++ b/server/chroma/src/routes/authorization.rs @@ -2,7 +2,7 @@ use crate::routes::appdata::{SessionIdCache, WebData}; use actix_web::body::BoxBody; use actix_web::dev::Payload; use actix_web::http::StatusCode; -use actix_web::{FromRequest, HttpRequest, HttpResponse, ResponseError, web}; +use actix_web::{web, FromRequest, HttpRequest, HttpResponse, ResponseError}; use dal::database::{ChromaScope, Database, DbResult, ServiceTokenUser, User, UserType}; use std::future::Future; use std::pin::Pin; diff --git a/server/chroma/src/routes/v1/album/list.rs b/server/chroma/src/routes/v1/album/list.rs index 3c87054..d1ca053 100644 --- a/server/chroma/src/routes/v1/album/list.rs +++ b/server/chroma/src/routes/v1/album/list.rs @@ -5,7 +5,9 @@ use crate::routes::v1::PhotoQuality; use actix_multiresponse::Payload; use actix_web::web; use dal::database::{Album, Photo}; -use dal::storage_engine::EngineType; +use dal::s3::aws_errors::GetObjectErrorKind; +use dal::s3::{S3Error, SdkError}; +use dal::storage_engine::{EngineType, StorageEngineError}; use dal::DalError; use futures::future::{join_all, try_join_all}; use proto::{AlbumWithCoverPhoto, ListAlbumsResponse}; @@ -89,6 +91,7 @@ pub async fn list( let database = data.db.clone(); let qpref: dal::storage_engine::PhotoQuality = query.quality_preference.clone().into(); let include_cover_photo = query.include_cover_photo; + let album_id_cache = &**album_id_cache; async move { // Fetch the cover photo if it is requested @@ -103,7 +106,31 @@ pub async fn list( }; let photo = match storage.engine_type() { - EngineType::S3 => photo.photo_to_proto_url(&storage, quality).await?, + EngineType::S3 => match photo.photo_to_proto_url(&storage, quality).await { + Ok(v) => v, + Err(e) => { + return match &e { + DalError::Storage(s) => match s { + StorageEngineError::S3(s) => match s { + S3Error::GetObject(s) => match s { + SdkError::ServiceError(s) => match s.err().kind { + GetObjectErrorKind::NoSuchKey(_) => { + album_id_cache.remove(&album.id).await; + album.delete(&database).await?; + Ok(None) + } + _ => Err(e), + }, + _ => Err(e), + }, + _ => Err(e), + }, + _ => Err(e), + }, + _ => Err(e), + } + } + }, EngineType::File => photo.photo_to_proto_bytes(&storage, quality).await?, }; @@ -115,10 +142,10 @@ pub async fn list( None }; - Ok(AlbumWithCoverPhoto { + Ok(Some(AlbumWithCoverPhoto { album: Some(album.to_proto(&database).await?), cover_photo, - }) + })) } })) .await @@ -127,7 +154,10 @@ pub async fn list( .map_err(|e| match e { DalError::Storage(e) => Error::from(e), DalError::Db(e) => Error::from(e), - })?; + })? + .into_iter() + .filter_map(|v| v) + .collect::>(); Ok(Payload(ListAlbumsResponse { albums })) } diff --git a/server/dal/src/s3.rs b/server/dal/src/s3.rs index d249b27..df7e950 100644 --- a/server/dal/src/s3.rs +++ b/server/dal/src/s3.rs @@ -1,7 +1,7 @@ use aws_credential_types::Credentials; use aws_sdk_s3::error::{DeleteObjectError, GetObjectError, PutObjectError}; use aws_sdk_s3::presigning::config::PresigningConfig; -use aws_sdk_s3::types::{ByteStream, SdkError}; +use aws_sdk_s3::types::ByteStream; use aws_sdk_s3::{Client, Config, Region}; use std::ops::Deref; use std::time::Duration; @@ -11,6 +11,8 @@ pub mod aws_errors { pub use aws_sdk_s3::error::*; } +pub use aws_sdk_s3::types::SdkError; + #[derive(Debug, Error)] pub enum S3InitError { #[error("Invalid App name provided")]