diff --git a/core/src/metadata_json.rs b/core/src/metadata_json.rs index ce5c8cac6..3eecbd462 100644 --- a/core/src/metadata_json.rs +++ b/core/src/metadata_json.rs @@ -1,12 +1,12 @@ use { backon::{ExponentialBuilder, Retryable}, clap::Parser, - digital_asset_types::dao::{asset_data, sea_orm_active_enums::LastRequestedStatusCode}, + digital_asset_types::dao::asset_data::{self}, futures::{future::BoxFuture, stream::FuturesUnordered, StreamExt}, indicatif::HumanDuration, log::{debug, error}, reqwest::{Client, Url as ReqwestUrl}, - sea_orm::{entity::*, SqlxPostgresConnector}, + sea_orm::{entity::*, ConnectionTrait, SqlxPostgresConnector, TransactionTrait}, serde::{Deserialize, Serialize}, tokio::{ sync::mpsc::{error::SendError, unbounded_channel, UnboundedSender}, @@ -17,9 +17,9 @@ use { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct DownloadMetadataInfo { - pub asset_data_id: Vec, - pub uri: String, - pub slot: i64, + asset_data_id: Vec, + uri: String, + slot: i64, } impl DownloadMetadataInfo { @@ -206,17 +206,12 @@ pub async fn perform_metadata_json_task( download_metadata_info: &DownloadMetadataInfo, ) -> Result { let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); - let start = Instant::now(); - let fetch_res = fetch_metadata_json(client, &download_metadata_info.uri).await; - let time_elapsed = start.elapsed().as_millis() as u64; - match fetch_res { + match fetch_metadata_json(client, &download_metadata_info.uri).await { Ok(metadata) => { let active_model = asset_data::ActiveModel { id: Set(download_metadata_info.asset_data_id.clone()), metadata: Set(metadata), reindex: Set(Some(false)), - last_requested_status_code: Set(Some(LastRequestedStatusCode::Success)), - fetch_duration_in_ms: Set(Some(time_elapsed)), ..Default::default() }; @@ -228,8 +223,6 @@ pub async fn perform_metadata_json_task( let active_model = asset_data::ActiveModel { id: Set(download_metadata_info.asset_data_id.clone()), reindex: Set(Some(true)), - last_requested_status_code: Set(Some(LastRequestedStatusCode::Failure)), - fetch_duration_in_ms: Set(Some(time_elapsed)), ..Default::default() }; @@ -263,3 +256,14 @@ impl DownloadMetadata { .map(|_| ()) } } + +pub async fn skip_metadata_json_download(asset_data_id: &[u8], uri: &str, conn: &T) -> bool +where + T: ConnectionTrait + TransactionTrait, +{ + asset_data::Entity::find_by_id(asset_data_id.to_vec()) + .one(conn) + .await + .unwrap_or(None) + .is_some_and(|model| model.metadata_url.eq(uri)) +} diff --git a/digital_asset_types/src/dao/generated/asset_data.rs b/digital_asset_types/src/dao/generated/asset_data.rs index a7b24a56c..c96c265e6 100644 --- a/digital_asset_types/src/dao/generated/asset_data.rs +++ b/digital_asset_types/src/dao/generated/asset_data.rs @@ -1,7 +1,6 @@ //! SeaORM Entity. Generated by sea-orm-codegen 0.9.3 use super::sea_orm_active_enums::ChainMutability; -use super::sea_orm_active_enums::LastRequestedStatusCode; use super::sea_orm_active_enums::Mutability; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; @@ -28,8 +27,6 @@ pub struct Model { pub raw_name: Option>, pub raw_symbol: Option>, pub base_info_seq: Option, - pub fetch_duration_in_ms: Option, - pub last_requested_status_code: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] @@ -45,8 +42,6 @@ pub enum Column { RawName, RawSymbol, BaseInfoSeq, - FetchDurationInMs, - LastRequestedStatusCode, } #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] @@ -79,8 +74,6 @@ impl ColumnTrait for Column { Self::RawName => ColumnType::Binary.def().null(), Self::RawSymbol => ColumnType::Binary.def().null(), Self::BaseInfoSeq => ColumnType::BigInteger.def().null(), - Self::FetchDurationInMs => ColumnType::Unsigned.def().null(), - Self::LastRequestedStatusCode => LastRequestedStatusCode::db_type().null(), } } } diff --git a/digital_asset_types/src/dao/generated/sea_orm_active_enums.rs b/digital_asset_types/src/dao/generated/sea_orm_active_enums.rs index 3f4106394..cf7470c6f 100644 --- a/digital_asset_types/src/dao/generated/sea_orm_active_enums.rs +++ b/digital_asset_types/src/dao/generated/sea_orm_active_enums.rs @@ -165,16 +165,3 @@ pub enum Instruction { #[sea_orm(string_value = "verify_creator")] VerifyCreator, } - -#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] -#[sea_orm( - rs_type = "String", - db_type = "Enum", - enum_name = "last_requested_status_code" -)] -pub enum LastRequestedStatusCode { - #[sea_orm(string_value = "success")] - Success, - #[sea_orm(string_value = "failure")] - Failure, -} diff --git a/digital_asset_types/tests/common.rs b/digital_asset_types/tests/common.rs index 22b59b041..6f40f610e 100644 --- a/digital_asset_types/tests/common.rs +++ b/digital_asset_types/tests/common.rs @@ -86,8 +86,6 @@ pub fn create_asset_data( raw_name: Some(metadata.name.into_bytes().to_vec().clone()), raw_symbol: Some(metadata.symbol.into_bytes().to_vec().clone()), base_info_seq: Some(0), - fetch_duration_in_ms: None, - last_requested_status_code: None, }, ) } diff --git a/digital_asset_types/tests/json_parsing.rs b/digital_asset_types/tests/json_parsing.rs index 3660c41c3..e630c91ff 100644 --- a/digital_asset_types/tests/json_parsing.rs +++ b/digital_asset_types/tests/json_parsing.rs @@ -37,8 +37,6 @@ pub async fn parse_onchain_json(json: serde_json::Value) -> Content { raw_name: Some(String::from("Handalf").into_bytes().to_vec()), raw_symbol: Some(String::from("").into_bytes().to_vec()), base_info_seq: Some(0), - fetch_duration_in_ms: None, - last_requested_status_code: None, }; v1_content_from_json(&asset_data).unwrap() diff --git a/migration/src/lib.rs b/migration/src/lib.rs index e88290385..211501cd3 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -44,7 +44,6 @@ mod m20240319_120101_add_mpl_core_enum_vals; mod m20240320_120101_add_mpl_core_info_items; mod m20240520_120101_add_mpl_core_external_plugins_columns; mod m20240718_161232_change_supply_columns_to_numeric; -mod m20241104_093312_add_metadata_json_fetch_heuristics_columns; mod m20241119_060310_add_token_inscription_enum_variant; pub mod model; @@ -99,7 +98,6 @@ impl MigratorTrait for Migrator { Box::new(m20240320_120101_add_mpl_core_info_items::Migration), Box::new(m20240520_120101_add_mpl_core_external_plugins_columns::Migration), Box::new(m20240718_161232_change_supply_columns_to_numeric::Migration), - Box::new(m20241104_093312_add_metadata_json_fetch_heuristics_columns::Migration), Box::new(m20241119_060310_add_token_inscription_enum_variant::Migration), ] } diff --git a/migration/src/m20241104_093312_add_metadata_json_fetch_heuristics_columns.rs b/migration/src/m20241104_093312_add_metadata_json_fetch_heuristics_columns.rs deleted file mode 100644 index 2e8d4a405..000000000 --- a/migration/src/m20241104_093312_add_metadata_json_fetch_heuristics_columns.rs +++ /dev/null @@ -1,92 +0,0 @@ -use enum_iterator::{all, Sequence}; -use extension::postgres::Type; -use sea_orm_migration::prelude::*; - -use crate::model::table::AssetData; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .alter_table( - Table::alter() - .table(AssetData::Table) - .add_column( - ColumnDef::new(AssetData::FetchDurationInMs) - .integer() - .null(), - ) - .to_owned(), - ) - .await?; - - manager - .create_type( - Type::create() - .as_enum(AssetData::LastRequestedStatusCode) - .values(vec![ - LastRequestedStatusCode::Success, - LastRequestedStatusCode::Failure, - ]) - .to_owned(), - ) - .await?; - - manager - .alter_table( - Table::alter() - .table(AssetData::Table) - .add_column( - ColumnDef::new(AssetData::LastRequestedStatusCode) - .enumeration( - AssetData::LastRequestedStatusCode, - all::().collect::>(), - ) - .not_null(), - ) - .to_owned(), - ) - .await?; - - Ok(()) - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .alter_table( - Table::alter() - .table(AssetData::Table) - .drop_column(AssetData::FetchDurationInMs) - .to_owned(), - ) - .await?; - - manager - .alter_table( - Table::alter() - .table(AssetData::Table) - .drop_column(AssetData::LastRequestedStatusCode) - .to_owned(), - ) - .await?; - - manager - .drop_type( - Type::drop() - .name(AssetData::LastRequestedStatusCode) - .to_owned(), - ) - .await?; - - Ok(()) - } -} - -#[derive(Iden, Sequence)] -pub enum LastRequestedStatusCode { - Success, - Failure, -} diff --git a/migration/src/model/table.rs b/migration/src/model/table.rs index a53612dcb..eec2313b5 100644 --- a/migration/src/model/table.rs +++ b/migration/src/model/table.rs @@ -107,8 +107,6 @@ pub enum AssetData { RawName, RawSymbol, BaseInfoSeq, - FetchDurationInMs, - LastRequestedStatusCode, } #[derive(Copy, Clone, Iden)] diff --git a/program_transformers/src/bubblegum/db.rs b/program_transformers/src/bubblegum/db.rs index 507aca3fb..ef5c6c3c2 100644 --- a/program_transformers/src/bubblegum/db.rs +++ b/program_transformers/src/bubblegum/db.rs @@ -1,6 +1,6 @@ use { crate::error::{ProgramTransformerError, ProgramTransformerResult}, - das_core::DownloadMetadataInfo, + das_core::{skip_metadata_json_download, DownloadMetadataInfo}, digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, cl_audits_v2, cl_items, sea_orm_active_enums::{ @@ -378,36 +378,45 @@ pub async fn upsert_asset_data( where T: ConnectionTrait + TransactionTrait, { - let model = asset_data::ActiveModel { + let skip_metadata_json_download = skip_metadata_json_download(&id, &metadata_url, txn).await; + + let mut model = asset_data::ActiveModel { id: ActiveValue::Set(id.clone()), chain_data_mutability: ActiveValue::Set(chain_data_mutability), chain_data: ActiveValue::Set(chain_data), - metadata_url: ActiveValue::Set(metadata_url.clone()), metadata_mutability: ActiveValue::Set(metadata_mutability), - metadata: ActiveValue::Set(JsonValue::String("processing".to_string())), slot_updated: ActiveValue::Set(slot_updated), - reindex: ActiveValue::Set(Some(true)), raw_name: ActiveValue::Set(Some(raw_name)), raw_symbol: ActiveValue::Set(Some(raw_symbol)), base_info_seq: ActiveValue::Set(Some(seq)), ..Default::default() }; + let mut columns_to_update = vec![ + asset_data::Column::ChainDataMutability, + asset_data::Column::ChainData, + asset_data::Column::MetadataMutability, + asset_data::Column::SlotUpdated, + asset_data::Column::RawName, + asset_data::Column::RawSymbol, + asset_data::Column::BaseInfoSeq, + ]; + if !skip_metadata_json_download { + model.metadata_url = ActiveValue::Set(metadata_url.clone()); + model.metadata = ActiveValue::Set(JsonValue::String("processing".to_string())); + model.reindex = ActiveValue::Set(Some(true)); + + columns_to_update.extend_from_slice(&[ + asset_data::Column::MetadataUrl, + asset_data::Column::Metadata, + asset_data::Column::Reindex, + ]); + } + let mut query = asset_data::Entity::insert(model) .on_conflict( OnConflict::columns([asset_data::Column::Id]) - .update_columns([ - asset_data::Column::ChainDataMutability, - asset_data::Column::ChainData, - asset_data::Column::MetadataUrl, - asset_data::Column::MetadataMutability, - asset_data::Column::Metadata, - asset_data::Column::SlotUpdated, - asset_data::Column::Reindex, - asset_data::Column::RawName, - asset_data::Column::RawSymbol, - asset_data::Column::BaseInfoSeq, - ]) + .update_columns(columns_to_update) .to_owned(), ) .build(DbBackend::Postgres); @@ -421,20 +430,20 @@ where query.sql ); - let result = txn - .execute(query) + txn.execute(query) .await .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; - if result.rows_affected() > 0 { - Ok(Some(DownloadMetadataInfo::new( - id, - metadata_url, - slot_updated, - ))) - } else { - Ok(None) + // If the metadata JSON already exists, skip the download. + if skip_metadata_json_download { + return Ok(None); } + + Ok(Some(DownloadMetadataInfo::new( + id, + metadata_url, + slot_updated, + ))) } #[allow(clippy::too_many_arguments)] diff --git a/program_transformers/src/bubblegum/mod.rs b/program_transformers/src/bubblegum/mod.rs index af4266cf4..03a800858 100644 --- a/program_transformers/src/bubblegum/mod.rs +++ b/program_transformers/src/bubblegum/mod.rs @@ -1,7 +1,7 @@ use { crate::{ error::{ProgramTransformerError, ProgramTransformerResult}, - skip_metadata_json_download, DownloadMetadataNotifier, + DownloadMetadataNotifier, }, blockbuster::{ instruction::InstructionBundle, @@ -72,9 +72,6 @@ where } InstructionName::MintV1 | InstructionName::MintToCollectionV1 => { if let Some(info) = mint_v1::mint_v1(parsing_result, bundle, txn, ix_str).await? { - if skip_metadata_json_download(&info, txn).await { - return Ok(()); - } download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; @@ -102,9 +99,6 @@ where if let Some(info) = update_metadata::update_metadata(parsing_result, bundle, txn, ix_str).await? { - if skip_metadata_json_download(&info, txn).await { - return Ok(()); - } download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 2881a6ea6..ad0ddf35a 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -18,7 +18,6 @@ use { }, }, das_core::{DownloadMetadataInfo, DownloadMetadataNotifier}, - digital_asset_types::dao::asset_data, sea_orm::{ entity::EntityTrait, query::Select, ConnectionTrait, DatabaseConnection, DbErr, SqlxPostgresConnector, TransactionTrait, @@ -281,30 +280,6 @@ fn record_metric(metric_name: &str, success: bool, retries: u32) { } } -pub async fn skip_metadata_json_download( - download_metadata_info: &DownloadMetadataInfo, - conn: &T, -) -> bool -where - T: ConnectionTrait + TransactionTrait, -{ - let DownloadMetadataInfo { - asset_data_id, - slot: incoming_slot, - uri, - } = download_metadata_info; - - asset_data::Entity::find_by_id(asset_data_id.clone()) - .one(conn) - .await - .unwrap_or(None) - .is_some_and(|model| { - !model.reindex.unwrap_or(false) - && model.metadata_url.eq(uri) - && model.slot_updated >= *incoming_slot - }) -} - pub fn filter_non_null_fields(value: Value) -> Option { match value { Value::Null => None, diff --git a/program_transformers/src/mpl_core_program/mod.rs b/program_transformers/src/mpl_core_program/mod.rs index d610cdd0a..b01252d4b 100644 --- a/program_transformers/src/mpl_core_program/mod.rs +++ b/program_transformers/src/mpl_core_program/mod.rs @@ -2,7 +2,7 @@ use { crate::{ error::{ProgramTransformerError, ProgramTransformerResult}, mpl_core_program::v1_asset::{burn_v1_asset, save_v1_asset}, - skip_metadata_json_download, AccountInfo, DownloadMetadataNotifier, + AccountInfo, DownloadMetadataNotifier, }, blockbuster::programs::mpl_core_program::{MplCoreAccountData, MplCoreAccountState}, sea_orm::DatabaseConnection, @@ -30,9 +30,6 @@ pub async fn handle_mpl_core_account<'a, 'b, 'c>( ) .await? { - if skip_metadata_json_download(&info, db).await { - return Ok(()); - } download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; diff --git a/program_transformers/src/mpl_core_program/v1_asset.rs b/program_transformers/src/mpl_core_program/v1_asset.rs index df1d0ea07..6b60a281b 100644 --- a/program_transformers/src/mpl_core_program/v1_asset.rs +++ b/program_transformers/src/mpl_core_program/v1_asset.rs @@ -12,6 +12,7 @@ use { mpl_core::types::{Plugin, PluginAuthority, PluginType, UpdateAuthority}, programs::mpl_core_program::MplCoreAccountData, }, + das_core::skip_metadata_json_download, digital_asset_types::{ dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, @@ -26,8 +27,7 @@ use { entity::{ActiveValue, ColumnTrait, EntityTrait}, prelude::*, query::{JsonValue, QueryFilter, QueryTrait}, - sea_query::query::OnConflict, - sea_query::Expr, + sea_query::{query::OnConflict, Expr}, ConnectionTrait, CursorTrait, DbBackend, Statement, TransactionTrait, }, serde_json::{value::Value, Map}, @@ -183,14 +183,13 @@ pub async fn save_v1_asset( _ => ChainMutability::Mutable, }; - let asset_data_model = asset_data::ActiveModel { + let skip_metadata_json_download = skip_metadata_json_download(&id_vec, &uri, &txn).await; + + let mut asset_data_model = asset_data::ActiveModel { chain_data_mutability: ActiveValue::Set(chain_mutability), chain_data: ActiveValue::Set(chain_data_json), - metadata_url: ActiveValue::Set(uri.clone()), - metadata: ActiveValue::Set(JsonValue::String("processing".to_string())), metadata_mutability: ActiveValue::Set(Mutability::Mutable), slot_updated: ActiveValue::Set(slot_i), - reindex: ActiveValue::Set(Some(true)), id: ActiveValue::Set(id_vec.clone()), raw_name: ActiveValue::Set(Some(name.to_vec())), raw_symbol: ActiveValue::Set(None), @@ -198,20 +197,32 @@ pub async fn save_v1_asset( ..Default::default() }; + let mut columns_to_update = vec![ + asset_data::Column::ChainDataMutability, + asset_data::Column::ChainData, + asset_data::Column::MetadataMutability, + asset_data::Column::SlotUpdated, + asset_data::Column::RawName, + asset_data::Column::RawSymbol, + asset_data::Column::BaseInfoSeq, + ]; + + if !skip_metadata_json_download { + asset_data_model.metadata_url = ActiveValue::Set(uri.clone()); + asset_data_model.metadata = ActiveValue::Set(JsonValue::String("processing".to_string())); + asset_data_model.reindex = ActiveValue::Set(Some(true)); + + columns_to_update.extend_from_slice(&[ + asset_data::Column::MetadataUrl, + asset_data::Column::Metadata, + asset_data::Column::Reindex, + ]); + } + let mut query = asset_data::Entity::insert(asset_data_model) .on_conflict( OnConflict::columns([asset_data::Column::Id]) - .update_columns([ - asset_data::Column::ChainDataMutability, - asset_data::Column::ChainData, - asset_data::Column::MetadataUrl, - asset_data::Column::MetadataMutability, - asset_data::Column::SlotUpdated, - asset_data::Column::Reindex, - asset_data::Column::RawName, - asset_data::Column::RawSymbol, - asset_data::Column::BaseInfoSeq, - ]) + .update_columns(columns_to_update) .to_owned(), ) .build(DbBackend::Postgres); @@ -471,6 +482,11 @@ pub async fn save_v1_asset( return Ok(None); } + // If the metadata JSON exists, skip downloading it. + if skip_metadata_json_download { + return Ok(None); + } + // Otherwise return with info for background downloading. Ok(Some(DownloadMetadataInfo::new(id_vec.clone(), uri, slot_i))) } diff --git a/program_transformers/src/token_metadata/mod.rs b/program_transformers/src/token_metadata/mod.rs index adb9650e4..0080303ed 100644 --- a/program_transformers/src/token_metadata/mod.rs +++ b/program_transformers/src/token_metadata/mod.rs @@ -1,7 +1,6 @@ use { crate::{ error::{ProgramTransformerError, ProgramTransformerResult}, - skip_metadata_json_download, token_metadata::{ master_edition::{save_v1_master_edition, save_v2_master_edition}, v1_asset::{burn_v1_asset, save_v1_asset}, @@ -38,9 +37,6 @@ pub async fn handle_token_metadata_account<'a, 'b>( } TokenMetadataAccountData::MetadataV1(m) => { if let Some(info) = save_v1_asset(db, m, account_info.slot).await? { - if skip_metadata_json_download(&info, db).await { - return Ok(()); - } download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; diff --git a/program_transformers/src/token_metadata/v1_asset.rs b/program_transformers/src/token_metadata/v1_asset.rs index 00671f4d4..3fd6b4e57 100644 --- a/program_transformers/src/token_metadata/v1_asset.rs +++ b/program_transformers/src/token_metadata/v1_asset.rs @@ -13,6 +13,7 @@ use { accounts::{MasterEdition, Metadata}, types::TokenStandard, }, + das_core::skip_metadata_json_download, digital_asset_types::{ dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, @@ -230,20 +231,44 @@ pub async fn save_v1_asset( true => ChainMutability::Mutable, false => ChainMutability::Immutable, }; - let asset_data_model = asset_data::ActiveModel { + + let skip_metadata_json_download = + skip_metadata_json_download(&mint_pubkey_vec, &uri, conn).await; + + let mut asset_data_model = asset_data::ActiveModel { chain_data_mutability: ActiveValue::Set(chain_mutability), chain_data: ActiveValue::Set(chain_data_json), - metadata_url: ActiveValue::Set(uri.clone()), - metadata: ActiveValue::Set(JsonValue::String("processing".to_string())), metadata_mutability: ActiveValue::Set(Mutability::Mutable), slot_updated: ActiveValue::Set(slot_i), - reindex: ActiveValue::Set(Some(true)), id: ActiveValue::Set(mint_pubkey_vec.clone()), raw_name: ActiveValue::Set(Some(name.to_vec())), raw_symbol: ActiveValue::Set(Some(symbol.to_vec())), base_info_seq: ActiveValue::Set(Some(0)), ..Default::default() }; + + let mut columns_to_update = vec![ + asset_data::Column::ChainDataMutability, + asset_data::Column::ChainData, + asset_data::Column::MetadataMutability, + asset_data::Column::SlotUpdated, + asset_data::Column::RawName, + asset_data::Column::RawSymbol, + asset_data::Column::BaseInfoSeq, + ]; + + if !skip_metadata_json_download { + asset_data_model.reindex = ActiveValue::Set(Some(true)); + asset_data_model.metadata = ActiveValue::Set(JsonValue::String("processing".to_string())); + asset_data_model.metadata_url = ActiveValue::Set(uri.clone()); + + columns_to_update.extend_from_slice(&[ + asset_data::Column::Reindex, + asset_data::Column::Metadata, + asset_data::Column::MetadataUrl, + ]); + } + let txn = conn.begin().await?; let set_lock_timeout = "SET LOCAL lock_timeout = '5s';"; @@ -259,17 +284,7 @@ pub async fn save_v1_asset( let mut query = asset_data::Entity::insert(asset_data_model) .on_conflict( OnConflict::columns([asset_data::Column::Id]) - .update_columns([ - asset_data::Column::ChainDataMutability, - asset_data::Column::ChainData, - asset_data::Column::MetadataUrl, - asset_data::Column::MetadataMutability, - asset_data::Column::SlotUpdated, - asset_data::Column::Reindex, - asset_data::Column::RawName, - asset_data::Column::RawSymbol, - asset_data::Column::BaseInfoSeq, - ]) + .update_columns(columns_to_update) .to_owned(), ) .build(DbBackend::Postgres); @@ -435,6 +450,11 @@ pub async fn save_v1_asset( return Ok(None); } + // If the metadata JSON exists, skip downloading it. + if skip_metadata_json_download { + return Ok(None); + } + Ok(Some(DownloadMetadataInfo::new( mint_pubkey_vec, uri,