From 25595cb45b219e1d5cbe95afee81dfa38aa1b50b Mon Sep 17 00:00:00 2001 From: Tahsin Tunan Date: Thu, 22 Jun 2023 22:56:05 +0600 Subject: [PATCH] Merge `json-uri` optional arg (#64) * Add structured logging and reduce log noisiness (#48) * Fix GetAssetsByCreator query (#8) * Bump to 0.7.1 * Handle HTTP errors Handle and log http errors separately. * Make bgtask runner configurable Partially addresses metaplex-foundation/digital-asset-rpc-infrastructure#50. * Enable configurable retries Enable configurable retries for the bgtask. * Add purged task metric * add new task metric * Fixed nft ingester * Fix the reading of task timeout * Set slow statements to debug * Remove task name * Fix purge task * acc forwarder (#11) * acc forwarder * version to .0.1 * Fixing unused imports Cleaning out unused imports. * Hopefully final fix for interval handling * Fix interval * fix(das-api): fix getAssetProof * Fix before/after cursors. (#67) * Fix edition nonce (#78) * fix(ingester): fix compressed nft burn indexing (#24) (#80) * fix(ingester): fix compressed nft burn indexing * Small fix for asssetId calculation * feat(das-api): support searching assets by `jsonUri` parameter (#79) * add dto parameter * add dao condition * upd asset_data fetching to ensure single presence of asset_data in query * use asset.asset_data key for linking between asset/asset_data * fix: breaking arg order for array queries * chore: consistent arg order in `SearchAssets` destructuring * fix: breaking arg count for array params in searchAssets * fix: use IndexMap instead of BTreeMap --------- Co-authored-by: Nicolas Pennie Co-authored-by: Linus Kendall Co-authored-by: ethyi <37843741+ethyi@users.noreply.github.com> Co-authored-by: Richard Wu Co-authored-by: Austin Adams Co-authored-by: Alex Tsymbal --- das_api/src/api/api_impl.rs | 2 + das_api/src/api/mod.rs | 2 + digital_asset_types/src/dao/mod.rs | 19 ++++++++++ digital_asset_types/src/dao/scopes/asset.rs | 42 +++++++++++++-------- 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/das_api/src/api/api_impl.rs b/das_api/src/api/api_impl.rs index 477b1576c..d32f3c880 100644 --- a/das_api/src/api/api_impl.rs +++ b/das_api/src/api/api_impl.rs @@ -300,6 +300,7 @@ impl ApiContract for DasApi { page, before, after, + json_uri, } = payload; // Deserialize search assets query self.validate_pagination(&limit, &page, &before, &after)?; @@ -348,6 +349,7 @@ impl ApiContract for DasApi { royalty_target, royalty_amount, burnt, + json_uri, }; let sort_by = sort_by.unwrap_or_default(); let transform = AssetTransform { diff --git a/das_api/src/api/mod.rs b/das_api/src/api/mod.rs index c9cd8ed79..38a6e5850 100644 --- a/das_api/src/api/mod.rs +++ b/das_api/src/api/mod.rs @@ -79,6 +79,8 @@ pub struct SearchAssets { pub page: Option, pub before: Option, pub after: Option, + #[serde(default)] + pub json_uri: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] diff --git a/digital_asset_types/src/dao/mod.rs b/digital_asset_types/src/dao/mod.rs index abe40b2f1..673a7559a 100644 --- a/digital_asset_types/src/dao/mod.rs +++ b/digital_asset_types/src/dao/mod.rs @@ -53,6 +53,7 @@ pub struct SearchAssetsQuery { pub royalty_target: Option>, pub royalty_amount: Option, pub burnt: Option, + pub json_uri: Option, } impl SearchAssetsQuery { @@ -111,6 +112,9 @@ impl SearchAssetsQuery { if self.grouping.is_some() { num_conditions += 1; } + if self.json_uri.is_some() { + num_conditions += 1; + } num_conditions } @@ -223,6 +227,21 @@ impl SearchAssetsQuery { joins.push(rel); } + if let Some(ju) = self.json_uri.to_owned() { + let cond = Condition::all() + .add(asset_data::Column::MetadataUrl.eq(ju)); + conditions = conditions.add(cond); + let rel = asset_data::Relation::Asset + .def() + .rev() + .on_condition(|left, right| { + Expr::tbl(right, asset_data::Column::Id) + .eq(Expr::tbl(left, asset::Column::AssetData)) + .into_condition() + }); + joins.push(rel); + } + Ok(( match self.negate { None | Some(false) => conditions, diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index fdba3b846..18f2467c5 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -4,6 +4,7 @@ use crate::dao::{ }; use indexmap::IndexMap; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; +use std::collections::HashMap; pub fn paginate<'db, T>(pagination: &Pagination, limit: u64, stmt: T) -> T where @@ -156,7 +157,6 @@ where E: RelationTrait, { let mut stmt = asset::Entity::find() - .find_also_related(asset_data::Entity) .filter(condition) .join(JoinType::LeftJoin, relation.def()) .order_by(sort_by, sort_direction); @@ -170,27 +170,39 @@ where pub async fn get_related_for_assets( conn: &impl ConnectionTrait, - assets: Vec<(asset::Model, Option)>, + assets: Vec, ) -> Result, DbErr> { - let mut ids = Vec::with_capacity(assets.len()); + let asset_ids = assets.iter().map(|a| a.id.clone()).collect::>(); + + let asset_data: Vec = asset_data::Entity::find() + .filter(asset_data::Column::Id.is_in(asset_ids)) + .all(conn) + .await?; + let asset_data_map = asset_data.into_iter().fold(HashMap::new(), |mut acc, ad| { + acc.insert(ad.id.clone(), ad); + acc + }); + // Using IndexMap to preserve order. - let mut assets_map = assets.into_iter().fold(IndexMap::new(), |mut x, asset| { - if let Some(ad) = asset.1 { - let id = asset.0.id.clone(); + let mut assets_map = assets.into_iter().fold(IndexMap::new(), |mut acc, asset| { + if let Some(ad) = asset + .asset_data + .clone() + .and_then(|ad_id| asset_data_map.get(&ad_id)) + { + let id = asset.id.clone(); let fa = FullAsset { - asset: asset.0, - data: ad, + asset: asset, + data: ad.clone(), authorities: vec![], creators: vec![], groups: vec![], }; - - x.insert(id.clone(), fa); - ids.push(id); - } - x + acc.insert(id, fa); + }; + acc }); - + let ids = assets_map.keys().cloned().collect::>(); let authorities = asset_authority::Entity::find() .filter(asset_authority::Column::AssetId.is_in(ids.clone())) .order_by_asc(asset_authority::Column::AssetId) @@ -243,7 +255,7 @@ pub async fn get_assets_by_condition( stmt = stmt.filter(condition).order_by(sort_by, sort_direction); stmt = paginate(pagination, limit, stmt); - let asset_list = stmt.find_also_related(asset_data::Entity).all(conn).await?; + let asset_list = stmt.all(conn).await?; get_related_for_assets(conn, asset_list).await }