Add functions to write and retrieve file contents

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent 0f90ad8984
commit a2c6e4cdf1

@ -5,11 +5,16 @@ use sea_orm::prelude::*;
pub struct Model { pub struct Model {
#[sea_orm(primary_key)] #[sea_orm(primary_key)]
pub id: u64, pub id: u64,
pub value: String pub value: String,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation { pub enum Relation {}
impl Related<super::file::Entity> for Entity {
fn to() -> RelationDef {
super::file::Relation::Hash.def().rev()
}
} }
impl Related<super::tag::Entity> for Entity { impl Related<super::tag::Entity> for Entity {

@ -9,6 +9,7 @@ use mediarepo_database::entities::hash;
use mediarepo_database::entities::hash::Model as HashModel; use mediarepo_database::entities::hash::Model as HashModel;
use sea_orm::prelude::*; use sea_orm::prelude::*;
use sea_orm::{DatabaseConnection, Set}; use sea_orm::{DatabaseConnection, Set};
use tokio::io::BufReader;
pub struct File { pub struct File {
db: DatabaseConnection, db: DatabaseConnection,
@ -35,6 +36,24 @@ impl File {
} }
} }
/// Finds the file by hash
pub async fn by_hash<S: AsRef<str>>(
db: DatabaseConnection,
hash: S,
) -> RepoResult<Option<Self>> {
if let Some((hash, Some(model))) = hash::Entity::find()
.filter(hash::Column::Value.eq(hash.as_ref()))
.find_also_related(file::Entity)
.one(&db)
.await?
{
let file = File::new(db, model, hash);
Ok(Some(file))
} else {
Ok(None)
}
}
/// Returns the unique identifier of the file /// Returns the unique identifier of the file
pub fn id(&self) -> u64 { pub fn id(&self) -> u64 {
self.model.id self.model.id
@ -119,6 +138,13 @@ impl File {
Ok(()) Ok(())
} }
/// Returns the reader for the file
pub async fn get_reader(&self) -> RepoResult<BufReader<tokio::fs::File>> {
let storage = self.storage().await?;
storage.get_file_reader(&self.hash.value).await
}
/// Returns the active model of the file with only the id set /// Returns the active model of the file with only the id set
fn get_active_model(&self) -> ActiveFile { fn get_active_model(&self) -> ActiveFile {
ActiveFile { ActiveFile {

@ -1,4 +1,5 @@
use mediarepo_core::error::RepoResult; use mediarepo_core::error::RepoResult;
use mediarepo_core::file_hash_store::FileHashStore;
use mediarepo_database::entities::storage; use mediarepo_database::entities::storage;
use mediarepo_database::entities::storage::ActiveModel as ActiveStorage; use mediarepo_database::entities::storage::ActiveModel as ActiveStorage;
use mediarepo_database::entities::storage::Model as StorageModel; use mediarepo_database::entities::storage::Model as StorageModel;
@ -6,15 +7,22 @@ use sea_orm::prelude::*;
use sea_orm::{DatabaseConnection, Set, Unset}; use sea_orm::{DatabaseConnection, Set, Unset};
use std::path::PathBuf; use std::path::PathBuf;
use tokio::fs; use tokio::fs;
use tokio::io::{AsyncRead, BufReader};
pub struct Storage { pub struct Storage {
db: DatabaseConnection, db: DatabaseConnection,
model: StorageModel, model: StorageModel,
store: FileHashStore,
} }
impl Storage { impl Storage {
fn new(db: DatabaseConnection, model: StorageModel) -> Self { fn new(db: DatabaseConnection, model: StorageModel) -> Self {
Self { db, model } let path = PathBuf::from(&model.path);
Self {
store: FileHashStore::new(path),
db,
model,
}
} }
/// Returns the storage by id /// Returns the storage by id
@ -27,6 +35,7 @@ impl Storage {
} }
} }
/// Returns the storage by path
pub async fn by_path<S: ToString>(db: DatabaseConnection, path: S) -> RepoResult<Option<Self>> { pub async fn by_path<S: ToString>(db: DatabaseConnection, path: S) -> RepoResult<Option<Self>> {
if let Some(model) = storage::Entity::find() if let Some(model) = storage::Entity::find()
.filter(storage::Column::Path.eq(path.to_string())) .filter(storage::Column::Path.eq(path.to_string()))
@ -110,6 +119,21 @@ impl Storage {
path.exists() path.exists()
} }
/// Adds a file to the store
pub async fn add_file<R: AsyncRead + Unpin>(&self, reader: R) -> RepoResult<String> {
self.store.add_file(reader, None).await
}
/// Returns the buf reader to the given hash
pub async fn get_file_reader<S: ToString>(
&self,
hash: S,
) -> RepoResult<BufReader<tokio::fs::File>> {
let (_ext, reader) = self.store.get_file(hash.to_string()).await?;
Ok(reader)
}
/// Returns the active model with only the ID filled so saves always perform an update /// Returns the active model with only the ID filled so saves always perform an update
fn get_active_model(&self) -> ActiveStorage { fn get_active_model(&self) -> ActiveStorage {
ActiveStorage { ActiveStorage {

Loading…
Cancel
Save