Delete old models

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/5/head
trivernis 3 years ago
parent cb493b4651
commit 745c6bf856
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,101 +0,0 @@
use crate::file::File;
use mediarepo_core::content_descriptor::convert_v1_descriptor_to_v2;
use mediarepo_core::error::RepoResult;
use mediarepo_database::entities::content_descriptor;
use mediarepo_database::entities::file;
use sea_orm::prelude::*;
use sea_orm::{DatabaseConnection, Set};
use std::fmt::Debug;
pub struct ContentDescriptor {
db: DatabaseConnection,
model: content_descriptor::Model,
}
impl ContentDescriptor {
#[tracing::instrument(level = "trace")]
pub(crate) fn new(db: DatabaseConnection, model: content_descriptor::Model) -> Self {
Self { db, model }
}
pub async fn all(db: DatabaseConnection) -> RepoResult<Vec<Self>> {
let descriptors = content_descriptor::Entity::find()
.all(&db)
.await?
.into_iter()
.map(|model| Self::new(db.clone(), model))
.collect();
Ok(descriptors)
}
/// Searches for the hash by id
#[tracing::instrument(level = "debug", skip(db))]
pub async fn by_id(db: DatabaseConnection, id: i64) -> RepoResult<Option<Self>> {
let hash = content_descriptor::Entity::find_by_id(id)
.one(&db)
.await?
.map(|model| Self::new(db, model));
Ok(hash)
}
/// Returns the hash by value
#[tracing::instrument(level = "debug", skip(db))]
pub async fn by_value<D: AsRef<[u8]> + Debug>(
db: DatabaseConnection,
descriptor: D,
) -> RepoResult<Option<Self>> {
let cid = content_descriptor::Entity::find()
.filter(content_descriptor::Column::Descriptor.eq(descriptor.as_ref()))
.one(&db)
.await?
.map(|model| Self::new(db, model));
Ok(cid)
}
/// Adds a new hash to the database
#[tracing::instrument(level = "debug", skip(db))]
pub async fn add(db: DatabaseConnection, descriptor: Vec<u8>) -> RepoResult<Self> {
let active_model = content_descriptor::ActiveModel {
descriptor: Set(descriptor),
..Default::default()
};
let model = active_model.insert(&db).await?;
Ok(Self::new(db, model))
}
pub fn id(&self) -> i64 {
self.model.id
}
pub fn descriptor(&self) -> &[u8] {
&self.model.descriptor[..]
}
/// Returns the file associated with the hash
#[tracing::instrument(level = "debug", skip(self))]
pub async fn file(&self) -> RepoResult<Option<File>> {
let file = self
.model
.find_related(file::Entity)
.one(&self.db)
.await?
.map(|file_model| File::new(self.db.clone(), file_model, self.model.clone()));
Ok(file)
}
pub async fn convert_v1_to_v2(&mut self) -> RepoResult<()> {
let descriptor = convert_v1_descriptor_to_v2(&self.model.descriptor)?;
let active_model = content_descriptor::ActiveModel {
id: Set(self.id()),
descriptor: Set(descriptor),
};
self.model = active_model.update(&self.db).await?;
Ok(())
}
}

@ -0,0 +1,59 @@
use crate::dao::{DaoContext, DaoProvider};
use mediarepo_core::content_descriptor::{
convert_v1_descriptor_to_v2, encode_content_descriptor, is_v1_content_descriptor,
};
use mediarepo_core::error::RepoResult;
use mediarepo_database::entities::content_descriptor;
use sea_orm::prelude::*;
use sea_orm::ActiveValue::Set;
use sea_orm::ConnectionTrait;
pub struct JobDao {
ctx: DaoContext,
}
impl DaoProvider for JobDao {
fn dao_ctx(&self) -> DaoContext {
self.ctx.clone()
}
}
impl JobDao {
pub fn new(ctx: DaoContext) -> JobDao {
Self { ctx }
}
pub async fn migrate_content_descriptors(&self) -> RepoResult<()> {
let cds: Vec<content_descriptor::Model> =
content_descriptor::Entity::find().all(&self.ctx.db).await?;
tracing::info!("Converting content descriptors to v2 format...");
let mut converted_count = 0;
for mut cd in cds {
if is_v1_content_descriptor(&cd.descriptor) {
let trx = self.ctx.db.begin().await?;
let src_cd = cd.descriptor;
let dst_cd = convert_v1_descriptor_to_v2(&src_cd)?;
let active_model = content_descriptor::ActiveModel {
id: Set(cd.id),
descriptor: Set(dst_cd.clone()),
};
self.ctx.main_storage.rename_file(&src_cd, &dst_cd).await?;
self.ctx
.thumbnail_storage
.rename_parent(
encode_content_descriptor(&src_cd),
encode_content_descriptor(&dst_cd),
)
.await?;
trx.commit().await?;
converted_count += 1;
}
}
tracing::info!("Converted {} descriptors", converted_count);
Ok(())
}
}

@ -1,8 +1,10 @@
pub mod file; pub mod file;
pub mod job;
pub mod repo; pub mod repo;
pub mod tag; pub mod tag;
use crate::dao::file::FileDao; use crate::dao::file::FileDao;
use crate::dao::job::JobDao;
use crate::dao::tag::TagDao; use crate::dao::tag::TagDao;
use mediarepo_core::fs::file_hash_store::FileHashStore; use mediarepo_core::fs::file_hash_store::FileHashStore;
use mediarepo_core::fs::thumbnail_store::ThumbnailStore; use mediarepo_core::fs::thumbnail_store::ThumbnailStore;
@ -25,6 +27,10 @@ pub trait DaoProvider {
fn tag(&self) -> TagDao { fn tag(&self) -> TagDao {
TagDao::new(self.dao_ctx()) TagDao::new(self.dao_ctx())
} }
fn job(&self) -> JobDao {
JobDao::new(self.dao_ctx())
}
} }
fn opt_to_active_val<T: Into<sea_orm::Value>>(opt: Option<T>) -> ActiveValue<T> { fn opt_to_active_val<T: Into<sea_orm::Value>>(opt: Option<T>) -> ActiveValue<T> {

@ -1,18 +1,18 @@
use crate::content_descriptor::ContentDescriptor;
use crate::dao::{DaoContext, DaoProvider}; use crate::dao::{DaoContext, DaoProvider};
use crate::file::File;
use crate::file_metadata::FileMetadata; use crate::file_metadata::FileMetadata;
use crate::namespace::Namespace; use crate::namespace::Namespace;
use crate::tag::Tag; use crate::tag::Tag;
use crate::thumbnail::Thumbnail;
use chrono::{Local, NaiveDateTime}; use chrono::{Local, NaiveDateTime};
use mediarepo_core::content_descriptor::{encode_content_descriptor, is_v1_content_descriptor}; use mediarepo_core::content_descriptor::{
convert_v1_descriptor_to_v2, encode_content_descriptor, is_v1_content_descriptor,
};
use mediarepo_core::error::{RepoError, RepoResult}; use mediarepo_core::error::{RepoError, RepoResult};
use mediarepo_core::fs::file_hash_store::FileHashStore; use mediarepo_core::fs::file_hash_store::FileHashStore;
use mediarepo_core::fs::thumbnail_store::{Dimensions, ThumbnailStore}; use mediarepo_core::fs::thumbnail_store::{Dimensions, ThumbnailStore};
use mediarepo_core::itertools::Itertools; use mediarepo_core::itertools::Itertools;
use mediarepo_core::thumbnailer::ThumbnailSize; use mediarepo_core::thumbnailer::ThumbnailSize;
use mediarepo_core::utils::parse_namespace_and_tag; use mediarepo_core::utils::parse_namespace_and_tag;
use mediarepo_database::entities::content_descriptor;
use mediarepo_database::get_database; use mediarepo_database::get_database;
use mediarepo_database::queries::analysis::{get_all_counts, Counts}; use mediarepo_database::queries::analysis::{get_all_counts, Counts};
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
@ -77,158 +77,6 @@ impl Repo {
FileMetadata::all_by_ids(self.db.clone(), ids).await FileMetadata::all_by_ids(self.db.clone(), ids).await
} }
/// Adds a file from bytes to the database
#[tracing::instrument(level = "debug", skip(self, content))]
pub async fn add_file(
&self,
mime_type: Option<String>,
content: Vec<u8>,
creation_time: NaiveDateTime,
change_time: NaiveDateTime,
) -> RepoResult<File> {
let file_size = content.len();
let reader = Cursor::new(content);
let cd_binary = self.main_storage.add_file(reader, None).await?;
let cd = ContentDescriptor::add(self.db.clone(), cd_binary).await?;
let mime_type = mime_type
.and_then(|m| mime::Mime::from_str(&m).ok())
.unwrap_or_else(|| mime::APPLICATION_OCTET_STREAM)
.to_string();
let file = File::add(self.db.clone(), cd.id(), mime_type).await?;
FileMetadata::add(
self.db.clone(),
file.id(),
file_size as i64,
creation_time,
change_time,
)
.await?;
Ok(file)
}
/// Adds a file to the database by its readable path in the file system
#[tracing::instrument(level = "debug", skip(self))]
pub async fn add_file_by_path(&self, path: PathBuf) -> RepoResult<File> {
let mime_type = mime_guess::from_path(&path).first().map(|m| m.to_string());
let mut os_file = OpenOptions::new().read(true).open(&path).await?;
let mut buf = Vec::new();
os_file.read_to_end(&mut buf).await?;
self.add_file(
mime_type,
buf,
Local::now().naive_local(),
Local::now().naive_local(),
)
.await
}
/// Deletes a file from the database and disk
#[tracing::instrument(level = "debug", skip(self, file))]
pub async fn delete_file(&self, file: File) -> RepoResult<()> {
let cd = file.cd().to_owned();
let cd_string = file.encoded_cd();
file.delete().await?;
self.main_storage.delete_file(&cd).await?;
self.thumbnail_storage.delete_parent(&cd_string).await?;
Ok(())
}
/// Returns all thumbnails of a file
pub async fn get_file_thumbnails(&self, file_cd: &[u8]) -> RepoResult<Vec<Thumbnail>> {
let file_cd = encode_content_descriptor(file_cd);
let thumbnails = self
.thumbnail_storage
.get_thumbnails(&file_cd)
.await?
.into_iter()
.map(|(size, path)| Thumbnail {
file_hash: file_cd.to_owned(),
path,
size,
mime_type: mime::IMAGE_PNG.to_string(),
})
.collect_vec();
Ok(thumbnails)
}
pub async fn get_file_bytes(&self, file: &File) -> RepoResult<Vec<u8>> {
let mut buf = Vec::new();
let mut reader = file.get_reader(&self.main_storage).await?;
reader.read_to_end(&mut buf).await?;
Ok(buf)
}
/// Creates thumbnails of all sizes for a file
#[tracing::instrument(level = "debug", skip(self, file))]
pub async fn create_thumbnails_for_file(&self, file: &File) -> RepoResult<Vec<Thumbnail>> {
let size = ThumbnailSize::Medium;
let (height, width) = size.dimensions();
let thumbs = file.create_thumbnail(&self.main_storage, [size]).await?;
let mut created_thumbs = Vec::with_capacity(1);
for thumb in thumbs {
let entry = self
.store_single_thumbnail(file.encoded_cd(), height, width, thumb)
.await?;
created_thumbs.push(entry);
}
Ok(created_thumbs)
}
#[tracing::instrument(level = "debug", skip(self, file))]
pub async fn create_file_thumbnail(
&self,
file: &File,
size: ThumbnailSize,
) -> RepoResult<Thumbnail> {
let (height, width) = size.dimensions();
let thumb = file
.create_thumbnail(&self.main_storage, [size])
.await?
.pop()
.ok_or_else(|| RepoError::from("Failed to create thumbnail"))?;
let thumbnail = self
.store_single_thumbnail(file.encoded_cd(), height, width, thumb)
.await?;
Ok(thumbnail)
}
/// Stores a single thumbnail
async fn store_single_thumbnail(
&self,
file_hash: String,
height: u32,
width: u32,
thumb: mediarepo_core::thumbnailer::Thumbnail,
) -> RepoResult<Thumbnail> {
let mut buf = Vec::new();
thumb.write_png(&mut buf)?;
let size = Dimensions { height, width };
let path = self
.thumbnail_storage
.add_thumbnail(&file_hash, size.clone(), &buf)
.await?;
let thumbnail = Thumbnail {
file_hash,
path,
size,
mime_type: mime::IMAGE_PNG.to_string(),
};
Ok(thumbnail)
}
/// Returns all tags stored in the database /// Returns all tags stored in the database
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub async fn tags(&self) -> RepoResult<Vec<Tag>> { pub async fn tags(&self) -> RepoResult<Vec<Tag>> {
@ -386,30 +234,4 @@ impl Repo {
pub async fn get_counts(&self) -> RepoResult<Counts> { pub async fn get_counts(&self) -> RepoResult<Counts> {
get_all_counts(&self.db).await get_all_counts(&self.db).await
} }
pub async fn migrate(&self) -> RepoResult<()> {
let cds = ContentDescriptor::all(self.db.clone()).await?;
tracing::info!("Converting content descriptors to v2 format...");
let mut converted_count = 0;
for mut cd in cds {
if is_v1_content_descriptor(cd.descriptor()) {
let src_cd = cd.descriptor().to_owned();
cd.convert_v1_to_v2().await?;
let dst_cd = cd.descriptor().to_owned();
self.main_storage.rename_file(&src_cd, &dst_cd).await?;
self.thumbnail_storage
.rename_parent(
encode_content_descriptor(&src_cd),
encode_content_descriptor(&dst_cd),
)
.await?;
converted_count += 1;
}
}
tracing::info!("Converted {} descriptors", converted_count);
Ok(())
}
} }

@ -1,6 +1,7 @@
use mediarepo_core::error::RepoResult; use mediarepo_core::error::RepoResult;
use mediarepo_core::fs::thumbnail_store::Dimensions; use mediarepo_core::fs::thumbnail_store::Dimensions;
use std::path::PathBuf; use std::path::PathBuf;
use tokio::fs;
use tokio::fs::{File, OpenOptions}; use tokio::fs::{File, OpenOptions};
use tokio::io::BufReader; use tokio::io::BufReader;
@ -39,4 +40,12 @@ impl ThumbnailDto {
let file = OpenOptions::new().read(true).open(&self.path).await?; let file = OpenOptions::new().read(true).open(&self.path).await?;
Ok(BufReader::new(file)) Ok(BufReader::new(file))
} }
/// Deletes the thumbnail
#[tracing::instrument(level = "debug")]
pub async fn delete(self) -> RepoResult<()> {
fs::remove_file(&self.path).await?;
Ok(())
}
} }

@ -1,300 +0,0 @@
use std::fmt::Debug;
use std::io::Cursor;
use std::str::FromStr;
use mediarepo_core::content_descriptor::encode_content_descriptor;
use sea_orm::prelude::*;
use sea_orm::{ConnectionTrait, DatabaseConnection, Set};
use sea_orm::{JoinType, QuerySelect};
use tokio::io::{AsyncReadExt, BufReader};
use crate::dao::file::find;
use crate::dao::file::find::FilterProperty;
use crate::dto::FileStatus;
use crate::file_metadata::FileMetadata;
use mediarepo_core::error::{RepoError, RepoResult};
use mediarepo_core::fs::file_hash_store::FileHashStore;
use mediarepo_core::thumbnailer::{self, Thumbnail as ThumbnailerThumb, ThumbnailSize};
use mediarepo_database::entities::content_descriptor;
use mediarepo_database::entities::content_descriptor_tag;
use mediarepo_database::entities::file;
use mediarepo_database::entities::file_metadata;
use mediarepo_database::entities::namespace;
use mediarepo_database::entities::tag;
use crate::tag::Tag;
#[derive(Clone)]
pub struct File {
db: DatabaseConnection,
model: file::Model,
content_descriptor: content_descriptor::Model,
}
impl File {
#[tracing::instrument(level = "trace")]
pub(crate) fn new(
db: DatabaseConnection,
model: file::Model,
hash: content_descriptor::Model,
) -> Self {
Self {
db,
model,
content_descriptor: hash,
}
}
/// Returns a list of all known stored files
#[tracing::instrument(level = "debug", skip(db))]
pub async fn all(db: DatabaseConnection) -> RepoResult<Vec<File>> {
let files: Vec<(file::Model, Option<content_descriptor::Model>)> = file::Entity::find()
.find_also_related(content_descriptor::Entity)
.all(&db)
.await?;
let files = files
.into_iter()
.filter_map(|(f, h)| {
let h = h?;
Some(Self::new(db.clone(), f, h))
})
.collect();
Ok(files)
}
/// Fetches the file by id
#[tracing::instrument(level = "debug", skip(db))]
pub async fn by_id(db: DatabaseConnection, id: i64) -> RepoResult<Option<Self>> {
if let Some((model, Some(hash))) = file::Entity::find_by_id(id)
.find_also_related(content_descriptor::Entity)
.one(&db)
.await?
{
let file = File::new(db, model, hash);
Ok(Some(file))
} else {
Ok(None)
}
}
/// Finds the file by hash
#[tracing::instrument(level = "debug", skip(db))]
pub async fn by_cd(db: DatabaseConnection, cd: &[u8]) -> RepoResult<Option<Self>> {
if let Some((hash, Some(model))) = content_descriptor::Entity::find()
.filter(content_descriptor::Column::Descriptor.eq(cd))
.find_also_related(file::Entity)
.one(&db)
.await?
{
let file = File::new(db, model, hash);
Ok(Some(file))
} else {
Ok(None)
}
}
/// Adds a file with its hash to the database
#[tracing::instrument(level = "debug", skip(db))]
pub(crate) async fn add(
db: DatabaseConnection,
cd_id: i64,
mime_type: String,
) -> RepoResult<Self> {
let file = file::ActiveModel {
cd_id: Set(cd_id),
mime_type: Set(mime_type),
..Default::default()
};
let file: file::ActiveModel = file.insert(&db).await?.into();
let file = Self::by_id(db, file.id.unwrap())
.await?
.expect("Inserted file does not exist");
Ok(file)
}
/// Returns the unique identifier of the file
pub fn id(&self) -> i64 {
self.model.id
}
/// Returns the hash of the file (content identifier)
pub fn cd(&self) -> &[u8] {
&self.content_descriptor.descriptor
}
/// Returns the encoded content descriptor
pub fn encoded_cd(&self) -> String {
encode_content_descriptor(self.cd())
}
/// Returns the id of the civ (content identifier value) of the file
pub fn cd_id(&self) -> i64 {
self.content_descriptor.id
}
/// Returns the mime type of the file
pub fn mime_type(&self) -> &String {
&self.model.mime_type
}
/// Returns the status of the file
pub fn status(&self) -> FileStatus {
match self.model.status {
10 => FileStatus::Imported,
20 => FileStatus::Archived,
30 => FileStatus::Deleted,
_ => FileStatus::Imported,
}
}
pub async fn set_status(&mut self, status: FileStatus) -> RepoResult<()> {
let active_model = file::ActiveModel {
id: Set(self.model.id),
status: Set(status as i32),
..Default::default()
};
self.model = active_model.update(&self.db).await?;
Ok(())
}
/// Returns the metadata associated with this file
/// A file MUST always have metadata associated
pub async fn metadata(&self) -> RepoResult<FileMetadata> {
FileMetadata::by_id(self.db.clone(), self.model.id)
.await
.and_then(|f| f.ok_or_else(|| RepoError::from("missing file metadata")))
}
/// Returns the list of tags of the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn tags(&self) -> RepoResult<Vec<Tag>> {
let tags: Vec<(tag::Model, Option<namespace::Model>)> = tag::Entity::find()
.find_also_related(namespace::Entity)
.join(
JoinType::LeftJoin,
content_descriptor_tag::Relation::Tag.def().rev(),
)
.filter(content_descriptor_tag::Column::CdId.eq(self.content_descriptor.id))
.all(&self.db)
.await?;
let tags = tags
.into_iter()
.map(|(tag, namespace)| Tag::new(self.db.clone(), tag, namespace))
.collect();
Ok(tags)
}
/// Adds a single tag to the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn add_tag(&mut self, tag_id: i64) -> RepoResult<()> {
let cd_id = self.content_descriptor.id;
let active_model = content_descriptor_tag::ActiveModel {
cd_id: Set(cd_id),
tag_id: Set(tag_id),
};
active_model.insert(&self.db).await?;
Ok(())
}
/// Adds multiple tags to the file at once
#[tracing::instrument(level = "debug", skip(self))]
pub async fn add_tags(&self, tag_ids: Vec<i64>) -> RepoResult<()> {
if tag_ids.is_empty() {
return Ok(());
}
let cd_id = self.content_descriptor.id;
let own_tag_ids = self
.tags()
.await?
.into_iter()
.map(|t| t.id())
.collect::<Vec<i64>>();
let models: Vec<content_descriptor_tag::ActiveModel> = tag_ids
.into_iter()
.filter(|tag_id| !own_tag_ids.contains(tag_id))
.map(|tag_id| content_descriptor_tag::ActiveModel {
cd_id: Set(cd_id),
tag_id: Set(tag_id),
})
.collect();
if models.len() > 0 {
content_descriptor_tag::Entity::insert_many(models)
.exec(&self.db)
.await?;
}
Ok(())
}
/// Removes multiple tags from the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn remove_tags(&self, tag_ids: Vec<i64>) -> RepoResult<()> {
let hash_id = self.content_descriptor.id;
content_descriptor_tag::Entity::delete_many()
.filter(content_descriptor_tag::Column::CdId.eq(hash_id))
.filter(content_descriptor_tag::Column::TagId.is_in(tag_ids))
.exec(&self.db)
.await?;
Ok(())
}
/// Returns the reader for the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn get_reader(
&self,
storage: &FileHashStore,
) -> RepoResult<BufReader<tokio::fs::File>> {
storage
.get_file(&self.content_descriptor.descriptor)
.await
.map(|(_, f)| f)
}
/// Creates a thumbnail for the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn create_thumbnail<I: IntoIterator<Item = ThumbnailSize> + Debug>(
&self,
storage: &FileHashStore,
sizes: I,
) -> RepoResult<Vec<ThumbnailerThumb>> {
let mut buf = Vec::new();
self.get_reader(storage)
.await?
.read_to_end(&mut buf)
.await?;
let mime_type = self.model.mime_type.clone();
let mime_type =
mime::Mime::from_str(&mime_type).unwrap_or_else(|_| mime::APPLICATION_OCTET_STREAM);
let thumbs = thumbnailer::create_thumbnails(Cursor::new(buf), mime_type, sizes)?;
Ok(thumbs)
}
/// Deletes the file as well as the content descriptor, tag mappings and metadata about the file
#[tracing::instrument(level = "debug", skip(self))]
pub async fn delete(self) -> RepoResult<()> {
let trx = self.db.begin().await?;
file_metadata::Entity::delete_many()
.filter(file_metadata::Column::FileId.eq(self.model.id))
.exec(&trx)
.await?;
self.model.delete(&trx).await?;
content_descriptor_tag::Entity::delete_many()
.filter(content_descriptor_tag::Column::CdId.eq(self.content_descriptor.id))
.exec(&trx)
.await?;
content_descriptor::Entity::delete_many()
.filter(content_descriptor::Column::Id.eq(self.content_descriptor.id))
.exec(&trx)
.await?;
trx.commit().await?;
Ok(())
}
}

@ -1,9 +1,6 @@
pub mod content_descriptor; pub mod dao;
pub mod file; pub mod dto;
pub mod file_metadata; pub mod file_metadata;
pub mod namespace; pub mod namespace;
pub mod tag; pub mod tag;
pub mod thumbnail;
pub mod type_keys; pub mod type_keys;
pub mod dto;
pub mod dao;

@ -1,30 +0,0 @@
use mediarepo_core::error::RepoResult;
use mediarepo_core::fs::thumbnail_store::Dimensions;
use std::path::PathBuf;
use tokio::fs::{self, File, OpenOptions};
use tokio::io::BufReader;
#[derive(Debug)]
pub struct Thumbnail {
pub file_hash: String,
pub path: PathBuf,
pub size: Dimensions,
pub mime_type: String,
}
impl Thumbnail {
/// Returns the reader of the thumbnail file
#[tracing::instrument(level = "debug")]
pub async fn get_reader(&self) -> RepoResult<BufReader<File>> {
let file = OpenOptions::new().read(true).open(&self.path).await?;
Ok(BufReader::new(file))
}
/// Deletes the thumbnail
#[tracing::instrument(level = "debug")]
pub async fn delete(self) -> RepoResult<()> {
fs::remove_file(&self.path).await?;
Ok(())
}
}

@ -5,11 +5,9 @@ use mediarepo_core::mediarepo_api::types::tags::{NamespaceResponse, TagResponse}
use mediarepo_logic::dto::{ use mediarepo_logic::dto::{
FileDto, FileMetadataDto, FileStatus as FileStatusModel, TagDto, ThumbnailDto, FileDto, FileMetadataDto, FileStatus as FileStatusModel, TagDto, ThumbnailDto,
}; };
use mediarepo_logic::file::File;
use mediarepo_logic::file_metadata::FileMetadata; use mediarepo_logic::file_metadata::FileMetadata;
use mediarepo_logic::namespace::Namespace; use mediarepo_logic::namespace::Namespace;
use mediarepo_logic::tag::Tag; use mediarepo_logic::tag::Tag;
use mediarepo_logic::thumbnail::Thumbnail;
pub trait FromModel<M> { pub trait FromModel<M> {
fn from_model(model: M) -> Self; fn from_model(model: M) -> Self;
@ -41,17 +39,6 @@ impl FromModel<FileMetadataDto> for FileMetadataResponse {
} }
} }
impl FromModel<File> for FileBasicDataResponse {
fn from_model(file: File) -> Self {
FileBasicDataResponse {
id: file.id(),
status: FileStatus::from_model(file.status()),
cd: file.encoded_cd(),
mime_type: file.mime_type().to_owned(),
}
}
}
impl FromModel<FileDto> for FileBasicDataResponse { impl FromModel<FileDto> for FileBasicDataResponse {
fn from_model(model: FileDto) -> Self { fn from_model(model: FileDto) -> Self {
FileBasicDataResponse { FileBasicDataResponse {
@ -93,17 +80,6 @@ impl FromModel<TagDto> for TagResponse {
} }
} }
impl FromModel<Thumbnail> for ThumbnailMetadataResponse {
fn from_model(model: Thumbnail) -> Self {
Self {
file_hash: model.file_hash,
height: model.size.height,
width: model.size.width,
mime_type: model.mime_type.to_owned(),
}
}
}
impl FromModel<ThumbnailDto> for ThumbnailMetadataResponse { impl FromModel<ThumbnailDto> for ThumbnailMetadataResponse {
fn from_model(model: ThumbnailDto) -> Self { fn from_model(model: ThumbnailDto) -> Self {
Self { Self {

@ -350,7 +350,7 @@ impl FilesNamespace {
let repo = get_repo_from_context(ctx).await; let repo = get_repo_from_context(ctx).await;
let id = event.payload::<FileIdentifier>()?; let id = event.payload::<FileIdentifier>()?;
let file = file_by_identifier(id, &repo).await?; let file = file_by_identifier(id, &repo).await?;
let thumbnails = repo.get_file_thumbnails(file.cd()).await?; let thumbnails = repo.file().thumbnails(file.encoded_cd()).await?;
for thumb in thumbnails { for thumb in thumbnails {
thumb.delete().await?; thumb.delete().await?;

@ -8,7 +8,6 @@ use mediarepo_database::queries::tags::{
use mediarepo_logic::dao::repo::Repo; use mediarepo_logic::dao::repo::Repo;
use mediarepo_logic::dao::DaoProvider; use mediarepo_logic::dao::DaoProvider;
use mediarepo_logic::dto::{FileDto, FileMetadataDto}; use mediarepo_logic::dto::{FileDto, FileMetadataDto};
use mediarepo_logic::file::File;
use mediarepo_logic::file_metadata::FileMetadata; use mediarepo_logic::file_metadata::FileMetadata;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use std::cmp::Ordering; use std::cmp::Ordering;

@ -4,6 +4,7 @@ use mediarepo_core::error::RepoResult;
use mediarepo_core::mediarepo_api::types::jobs::{JobType, RunJobRequest}; use mediarepo_core::mediarepo_api::types::jobs::{JobType, RunJobRequest};
use mediarepo_core::mediarepo_api::types::repo::SizeType; use mediarepo_core::mediarepo_api::types::repo::SizeType;
use mediarepo_core::type_keys::SizeMetadataKey; use mediarepo_core::type_keys::SizeMetadataKey;
use mediarepo_logic::dao::DaoProvider;
pub struct JobsNamespace; pub struct JobsNamespace;
@ -23,10 +24,10 @@ impl JobsNamespace {
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub async fn run_job(ctx: &Context, event: Event) -> IPCResult<()> { pub async fn run_job(ctx: &Context, event: Event) -> IPCResult<()> {
let run_request = event.payload::<RunJobRequest>()?; let run_request = event.payload::<RunJobRequest>()?;
let repo = get_repo_from_context(ctx).await; let job_dao = get_repo_from_context(ctx).await.job();
match run_request.job_type { match run_request.job_type {
JobType::MigrateContentDescriptors => repo.migrate().await?, JobType::MigrateContentDescriptors => job_dao.migrate_content_descriptors().await?,
JobType::CalculateSizes => calculate_all_sizes(ctx).await?, JobType::CalculateSizes => calculate_all_sizes(ctx).await?,
JobType::CheckIntegrity => {} JobType::CheckIntegrity => {}
} }

Loading…
Cancel
Save