Skip to content
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

Cleanup Announce Response #563

Merged
merged 4 commits into from
Jan 12, 2024

Conversation

da2ce7
Copy link
Contributor

@da2ce7 da2ce7 commented Jan 1, 2024

Ready For Review.

@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from ac3004c to afaee77 Compare January 3, 2024 13:30
@da2ce7 da2ce7 mentioned this pull request Jan 3, 2024
5 tasks
Copy link

codecov bot commented Jan 3, 2024

Codecov Report

Attention: 30 lines in your changes are missing coverage. Please review.

Comparison is base (3dd1402) 80.57% compared to head (0e6fe33) 80.75%.

Files Patch % Lines
src/servers/http/v1/responses/announce.rs 89.81% 11 Missing ⚠️
src/core/peer.rs 70.58% 10 Missing ⚠️
src/core/torrent/repository.rs 25.00% 9 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #563      +/-   ##
===========================================
+ Coverage    80.57%   80.75%   +0.18%     
===========================================
  Files          117      117              
  Lines         7854     7873      +19     
===========================================
+ Hits          6328     6358      +30     
+ Misses        1526     1515      -11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from afaee77 to f667eac Compare January 3, 2024 14:30
@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from f667eac to 3bc13dd Compare January 4, 2024 02:23
@da2ce7 da2ce7 requested a review from josecelano January 4, 2024 02:26
Copy link
Member

@josecelano josecelano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @da2ce7, in general I'm OK with this PR because there was a duplication which had to be removed, however, I have the feeling that empty traits and structs should be avoided (if possible).

For me, traits should represent behavior, although I've seen this pattern: Marker Trait.

Same for structs. Empty implementations look like inheritance.

In general, it seems there is a "hidden" enum in this implementation.

If the goal was just to remove duplication I think we could do it without adding empty traits and empty implementations. I've explored that path a little bit here.

Additionally, I think both responses are the same except for the peer list. I think we should take advantage of that property. I think we don't need to mark the parent struct as normal or compact with a different type than the one we use for the peer list. What makes the response compact is the peer list, if I'm not wrong.

The alternative I've proposed It's also aligned with other structs that already exist like AnnouncePolicy and SwarmStats. So we could simplify it even more.

Comment on lines 16 to 26
/// Trait that defines the Announce Response Format
pub trait Response: From<AnnounceData> + axum::response::IntoResponse {
/// Returns the Body of the Announce Response
///
/// # Errors
///
/// If unable to generate the response, it will return an error.
fn body(&self) -> Result<Vec<u8>, responses::error::Error>;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @da2ce7 I like this trait. A response is something that can bi built from the AnnounceData and converted into an Axum response.

@da2ce7
Copy link
Contributor Author

da2ce7 commented Jan 8, 2024

@josecelano

I used

pub struct Announce<E, P>
where
    E: Encoding<P>,
    P: PeerEncoding,

An Announce is not typed based upon the PeerEncoding, but a general Encoding.

I would have liked to have the signature something like:

pub struct Announce<E>
where
    E: Encoding,

However, I wanted to have the types being auto-detected based upon supplying form of the Encoding of the peers:
https://github.com/torrust/torrust-tracker/pull/563/files#diff-a73aff059d2186689d35963b70948e4c9e98739953692f7d3d817ecc7e2884c4R481-R494

This is where some of the trait complexity comes from in my implementation.

@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from b480b0e to f57e7dd Compare January 9, 2024 00:53
@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from f57e7dd to 05e11e3 Compare January 9, 2024 00:59
@josecelano
Copy link
Member

Hi @da2ce7, there is something I don't like about this PR and mine. When I wrote part of that code I wanted to have a clear representation of what an announce encoded response contains (normal and compact) so the Rust structs have the same structure as the bencoded format.

Notice that we already have an AnnounceData struct which is a generic struct holding the data needed by any announce response format.

My idea was to have DTOs that could be the exact representation of the encoded data. After removing the duplicity it's not clear anymore what the response contains. You have to read the serialization function.

I thought it was a good idea to have a direct mapping between:

Rust struct <-> Bencoded response <-> Json representation of the bencoded format (like in here)

In fact, maybe we have the need to remove duplication because of the comments. If we consider these structures just DTOs the duplication would not be bad, in fact, it could be good, since those structures (even having the same fields) represent different concepts defined in different BEPs. For example, if in the future, a new BEP is introduced and they add a new field to the compact response but not to the normal response we would need to undo a lot of what it's done here.

And regarding my implementation there is still some duplicity, but I think it could be removed making some functions generic. I just wanted to explore a little bit that option. But as I mentioned I've started feeling I'm removing duplication but introducing "domain" entities and making less clear what the encoded response contains.

@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from 05e11e3 to ab77ced Compare January 10, 2024 04:57
@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from ab77ced to 7bf84f2 Compare January 10, 2024 05:06
@da2ce7
Copy link
Contributor Author

da2ce7 commented Jan 10, 2024

@josecelano

I have reworked the code to try and better take into account you concerns. Now there is are Normal and Compact structs that contain their own prepared data that is ready for serialization.

It is possible to add new forms of serialization, or to remove or add fields without modifying the other structures.

josecelano
josecelano previously approved these changes Jan 10, 2024
Copy link
Member

@josecelano josecelano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @da2ce7 I like this version. I think it's self-explanatory and a good documentation for BEPs. It would be very easy to see what the response is returning and also make changes if needed.

There is only one more thing that I could do. Maybe I would convert the announce.rs into a folder with three files:

  • mod.rs
  • normal.rs
  • compact.rs

That would make even easier to read only one response type, I guess.

@@ -134,7 +134,7 @@ pub trait Database: Sync + Send {
/// # Errors
///
/// Will return `Err` if unable to save.
async fn save_persistent_torrent(&self, info_hash: &InfoHash, completed: u32) -> Result<(), Error>;
async fn save_persistent_torrent(&self, info_hash: &InfoHash, downloaded: u32) -> Result<(), Error>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @da2ce7 I see you have renamed stats fields.

SwarmMetadata contains the names defined in the BRP 48. And SwarmStats the names we were using in the Tracker.

Comment on lines +510 to +511
pub stats: SwarmStats,
pub policy: AnnouncePolicy,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like removing this duplication but we are using the other names in many places. Maybe we could use methods with the other names instead of the comment.

pub struct SwarmMetadata {
    /// The number of peers that have ever completed downloading
    pub downloaded: u32,
    /// The number of active peers that have completed downloading (seeders)
    pub complete: u32,
    /// The number of active peers that have not completed downloading (leechers)
    pub incomplete: u32,
}

impl SwarmMetadata {
    /// Alias for the
    fn seeders(&self) -> u32 {
       self.complete
    }
}

But I don't like how similar are complete (seeders) and completed (downloaded).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this. I would remove the SwarmStats, and rename all the variables to match the SwarmMetadata format... but that can happen another time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @WarmBeer I'm not sure. I think it's a good thing to follow BEP names but on the other hand "seeders" and "leechers" are also widely adopted, but apparently not in BEPs.

And "downloaded" and "complete" could be confusing, you do not know by the name which one is still active.

When I was thinking about this I decided that maybe the best option would be to use "seeders/leechers" wording in the whole app except for the scrape response.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! @da2ce7 I really like this version.

@josecelano
Copy link
Member

ACK 7bf84f2

@da2ce7 da2ce7 added the Needs Rebase Base Branch has Incompatibilities label Jan 11, 2024
josecelano and others added 2 commits January 12, 2024 12:13
(da2ce7): Merge `SwarmStats` into `SwarmMetadata`.
@da2ce7 da2ce7 force-pushed the 20240101_cleanup_response_announce branch from 7bf84f2 to 0e6fe33 Compare January 12, 2024 04:14
@da2ce7 da2ce7 removed the Needs Rebase Base Branch has Incompatibilities label Jan 12, 2024
@da2ce7
Copy link
Contributor Author

da2ce7 commented Jan 12, 2024

@josecelano Ready for Merge

@josecelano
Copy link
Member

ACK 0e6fe33

@josecelano josecelano merged commit 1d9d4f3 into torrust:develop Jan 12, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants