From 20f75d0983d3d8cc756ad079c460bf70541429a6 Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 4 Nov 2021 21:34:16 +0100 Subject: [PATCH] Implement api to get tags for a list of file hashes Signed-off-by: trivernis --- mediarepo-daemon/Cargo.lock | 4 +-- mediarepo-daemon/mediarepo-model/src/repo.rs | 10 +++++-- mediarepo-daemon/mediarepo-model/src/tag.rs | 26 ++++++++++++++++++- mediarepo-daemon/mediarepo-socket/Cargo.lock | 4 +-- mediarepo-daemon/mediarepo-socket/Cargo.toml | 2 +- .../mediarepo-socket/src/namespaces/tags.rs | 23 ++++++++++++++-- mediarepo-daemon/src/main.rs | 2 +- 7 files changed, 60 insertions(+), 11 deletions(-) diff --git a/mediarepo-daemon/Cargo.lock b/mediarepo-daemon/Cargo.lock index 305c167..d4117de 100644 --- a/mediarepo-daemon/Cargo.lock +++ b/mediarepo-daemon/Cargo.lock @@ -828,8 +828,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mediarepo-api" -version = "0.1.0" -source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=faf363da10c22cb2d7262ed7fe27301583fcbb9a#faf363da10c22cb2d7262ed7fe27301583fcbb9a" +version = "0.2.0" +source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=ea72553cd5284e785abea815d6d6b9ad262d880a#ea72553cd5284e785abea815d6d6b9ad262d880a" dependencies = [ "chrono", "serde", diff --git a/mediarepo-daemon/mediarepo-model/src/repo.rs b/mediarepo-daemon/mediarepo-model/src/repo.rs index b6ad42f..026e487 100644 --- a/mediarepo-daemon/mediarepo-model/src/repo.rs +++ b/mediarepo-daemon/mediarepo-model/src/repo.rs @@ -110,7 +110,7 @@ impl Repo { .map(|t| parse_namespace_and_tag(t.0.clone())) .collect(); - let db_tags = self.find_all_tags(parsed_tags).await?; + let db_tags = self.all_tags(parsed_tags).await?; let tag_map: HashMap = HashMap::from_iter(tags.into_iter()); let tag_ids: Vec<(i64, bool)> = db_tags @@ -197,10 +197,16 @@ impl Repo { /// Finds all tags by name #[tracing::instrument(level = "debug", skip(self))] - pub async fn find_all_tags(&self, tags: Vec<(Option, String)>) -> RepoResult> { + pub async fn all_tags(&self, tags: Vec<(Option, String)>) -> RepoResult> { Tag::all_by_name(self.db.clone(), tags).await } + /// Finds all tags that are assigned to the given list of hashes + #[tracing::instrument(level = "debug", skip_all)] + pub async fn find_tags_for_hashes(&self, hashes: Vec) -> RepoResult> { + Tag::for_hash_list(self.db.clone(), hashes).await + } + /// Adds or finds a tag #[tracing::instrument(level = "debug", skip(self))] pub async fn add_or_find_tag(&self, tag: S) -> RepoResult { diff --git a/mediarepo-daemon/mediarepo-model/src/tag.rs b/mediarepo-daemon/mediarepo-model/src/tag.rs index 0576245..7a8ad42 100644 --- a/mediarepo-daemon/mediarepo-model/src/tag.rs +++ b/mediarepo-daemon/mediarepo-model/src/tag.rs @@ -1,10 +1,13 @@ use crate::namespace::Namespace; use mediarepo_core::error::RepoResult; +use mediarepo_database::entities::hash; +use mediarepo_database::entities::hash_tag; use mediarepo_database::entities::namespace; use mediarepo_database::entities::tag; use sea_orm::prelude::*; use sea_orm::sea_query::Expr; -use sea_orm::{Condition, DatabaseConnection, Set}; +use sea_orm::QuerySelect; +use sea_orm::{Condition, DatabaseConnection, JoinType, Set}; use std::fmt::Debug; #[derive(Clone)] @@ -101,6 +104,27 @@ impl Tag { Ok(tags) } + /// Returns all tags that are assigned to any of the passed hashes + #[tracing::instrument(level = "debug", skip_all)] + pub async fn for_hash_list( + db: DatabaseConnection, + hashes: Vec, + ) -> RepoResult> { + let tags: Vec = tag::Entity::find() + .find_also_related(namespace::Entity) + .join(JoinType::LeftJoin, hash_tag::Relation::Tag.def().rev()) + .join(JoinType::InnerJoin, hash_tag::Relation::Hash.def()) + .filter(hash::Column::Value.is_in(hashes)) + .group_by(tag::Column::Id) + .all(&db) + .await? + .into_iter() + .map(|(t, n)| Self::new(db.clone(), t, n)) + .collect(); + + Ok(tags) + } + /// Adds a new tag to the database #[tracing::instrument(level = "debug", skip(db))] pub async fn add( diff --git a/mediarepo-daemon/mediarepo-socket/Cargo.lock b/mediarepo-daemon/mediarepo-socket/Cargo.lock index 4ea2af1..a655bca 100644 --- a/mediarepo-daemon/mediarepo-socket/Cargo.lock +++ b/mediarepo-daemon/mediarepo-socket/Cargo.lock @@ -769,8 +769,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mediarepo-api" -version = "0.1.0" -source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=faf363da10c22cb2d7262ed7fe27301583fcbb9a#faf363da10c22cb2d7262ed7fe27301583fcbb9a" +version = "0.2.0" +source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=ea72553cd5284e785abea815d6d6b9ad262d880a#ea72553cd5284e785abea815d6d6b9ad262d880a" dependencies = [ "chrono", "serde", diff --git a/mediarepo-daemon/mediarepo-socket/Cargo.toml b/mediarepo-daemon/mediarepo-socket/Cargo.toml index b100d08..75c62c8 100644 --- a/mediarepo-daemon/mediarepo-socket/Cargo.toml +++ b/mediarepo-daemon/mediarepo-socket/Cargo.toml @@ -33,4 +33,4 @@ features = ["tokio-executor"] [dependencies.mediarepo-api] git = "https://github.com/Trivernis/mediarepo-api.git" -rev = "faf363da10c22cb2d7262ed7fe27301583fcbb9a" \ No newline at end of file +rev = "ea72553cd5284e785abea815d6d6b9ad262d880a" \ No newline at end of file diff --git a/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs b/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs index a83c9f7..c12d181 100644 --- a/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs +++ b/mediarepo-daemon/mediarepo-socket/src/namespaces/tags.rs @@ -1,6 +1,6 @@ use crate::from_model::FromModel; use crate::utils::{file_by_identifier, get_repo_from_context}; -use mediarepo_api::types::files::GetFileTagsRequest; +use mediarepo_api::types::files::{GetFileTagsRequest, GetFilesTagsRequest}; use mediarepo_api::types::tags::TagResponse; use mediarepo_core::rmp_ipc::prelude::*; @@ -14,7 +14,8 @@ impl NamespaceProvider for TagsNamespace { fn register(handler: &mut EventHandler) { events!(handler, "all_tags" => Self::all_tags, - "tags_for_file" => Self::tags_for_file + "tags_for_file" => Self::tags_for_file, + "tags_for_files" => Self::tags_for_files ); } } @@ -52,4 +53,22 @@ impl TagsNamespace { Ok(()) } + + /// Returns all tags for a given list of file hashes + #[tracing::instrument(skip_all)] + async fn tags_for_files(ctx: &Context, event: Event) -> IPCResult<()> { + let repo = get_repo_from_context(ctx).await; + let request = event.data::()?; + let tag_responses: Vec = repo + .find_tags_for_hashes(request.hashes) + .await? + .into_iter() + .map(TagResponse::from_model) + .collect(); + ctx.emitter + .emit_response_to(event.id(), Self::name(), "tags_for_files", tag_responses) + .await?; + + Ok(()) + } } diff --git a/mediarepo-daemon/src/main.rs b/mediarepo-daemon/src/main.rs index acbccb9..eface57 100644 --- a/mediarepo-daemon/src/main.rs +++ b/mediarepo-daemon/src/main.rs @@ -233,7 +233,7 @@ async fn add_tags_from_tags_file( log::info!("Adding tags"); if tags_path.exists() { let mut tags = parse_tags_file(tags_path).await?; - let resolved_tags = repo.find_all_tags(tags.clone()).await?; + let resolved_tags = repo.all_tags(tags.clone()).await?; tags.retain(|tag| { resolved_tags .iter()