-
Notifications
You must be signed in to change notification settings - Fork 10
fix(backend): cleanups part 1 #517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
refactor: use raw fingerprint bytes for file info internally refactor: get_file_info authenticates user, no need for bucket id docs: document missing auth for download
fix(test:download): initialize test db
refactor(handler:file): authenticate user before download
This is to allow the /health endpoint to potentially trigger a reconnect if the connection has errors
chore: cleanup after merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some preliminar comments
| let payment_stream_data = self | ||
| .postgres | ||
| .get_payment_streams_for_user(user_address) | ||
| .get_payment_streams_for_user(&user_address.to_string()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing user_address downstream to also be Address instead String was a PITA?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean in the DB itself? Or the internal traits?
In the DB we keep string because technically speaking it could be a SS58 address, which was the case before the solochain runtime
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second pass
| /// | ||
| /// This method caches the MSP data to avoid repeated database hits. | ||
| /// The cache is automatically refreshed after the configured TTL expires. | ||
| pub async fn get_msp(&self, msp_onchain_id: &OnchainMspId) -> Result<Msp> { | ||
| debug!(target: "indexer_db::client::get_msp", onchain_id = %msp_onchain_id, "Fetching MSP"); | ||
|
|
||
| // TODO: should we cache this? | ||
| // since we always reference the same msp | ||
| self.repository | ||
| // Check if we have a valid cached entry | ||
| { | ||
| let cache = self.msp_cache.read().await; | ||
| if let Some(entry) = &*cache { | ||
| // Check if the cache entry matches the requested MSP and is still valid | ||
| if entry.msp.onchain_msp_id == *msp_onchain_id | ||
| && entry.last_refreshed.elapsed() < Duration::from_secs(MSP_CACHE_TTL_SECS) | ||
| { | ||
| return Ok(entry.msp.clone()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Cache miss or expired, fetch from database | ||
| let msp = self | ||
| .repository | ||
| .get_msp_by_onchain_id(msp_onchain_id) | ||
| .await | ||
| .map_err(Into::into) | ||
| .map_err(Into::<crate::error::Error>::into)?; | ||
|
|
||
| // Update cache with the new value | ||
| { | ||
| let mut cache = self.msp_cache.write().await; | ||
| *cache = Some(MspCacheEntry { | ||
| msp: msp.clone(), | ||
| last_refreshed: Instant::now(), | ||
| }); | ||
| } | ||
|
|
||
| Ok(msp) | ||
| } | ||
|
|
||
| /// Invalidate the MSP cache if it matches the given MSP | ||
| /// | ||
| /// # Arguments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the motivation of having this cache?
Also, can't this cause having out of date info?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have the cache because realistically speaking the MSP that we make query for will be only 1, so this way we save a few redudant calls to the db...
Not necessary tbh but not bad to have. Yeah we might be out of date but not meaningfully so
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client/indexer-db/migrations/2025-10-09-161554_add_bucket_value_prop_size_count/up.sql
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GigaBrain work! Lets just discuss all my comments and we are good to go
| pub updated_at: NaiveDateTime, | ||
| pub merkle_root: Vec<u8>, | ||
| pub value_prop_id: String, | ||
| pub total_size: BigDecimal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need a BigInt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most likely no, but this gives us flexibility to not have to depend on the runtime unit typing (technically file should change too)
| diesel::delete(file::table) | ||
| .filter(file::file_key.eq(file_key)) | ||
| .execute(conn) | ||
| .await?; | ||
|
|
||
| // Update bucket counts if file was found | ||
| if let Some((bucket_id, file_size)) = file_info { | ||
| Bucket::decrement_file_count_and_size(conn, bucket_id, file_size).await?; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, is this happening atomically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's all in one transaction at the start of the block processing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How the db transaction is initiated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from handle_finality_notification -> index_block which then trickles the data to everything else
storage-hub/client/indexer-service/src/handler.rs
Lines 121 to 134 in a651b50
| conn.transaction::<(), IndexBlockError, _>(move |conn| { | |
| Box::pin(async move { | |
| let block_number_u64: u64 = block_number.saturated_into(); | |
| let block_number_i64: i64 = block_number_u64 as i64; | |
| ServiceState::update(conn, block_number_i64).await?; | |
| for ev in block_events { | |
| self.route_event(conn, &ev.event.into(), block_hash).await?; | |
| } | |
| Ok(()) | |
| }) | |
| }) | |
| .await?; |
This PR addresses part of the TODOs remaining in the backend code
Configuration BREAKING changes:
API BREAKING changes:
treefield at the root and folder items do not have achildrenfield/distributeendpoint as the backend is not in charge of this anymoreDB Migrations:
API changes:
/filesand/bucketsendpointslimit(the number of items to reply with) andpage(which 'page' the endpoint should return)Performance improvements: