-
Notifications
You must be signed in to change notification settings - Fork 44
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
Cleanup Announce Response #563
Conversation
ac3004c
to
afaee77
Compare
Codecov ReportAttention:
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. |
afaee77
to
f667eac
Compare
f667eac
to
3bc13dd
Compare
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.
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.
/// 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>; | ||
} |
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.
Hi @da2ce7 I like this trait. A response is something that can bi built from the AnnounceData
and converted into an Axum response.
I used pub struct Announce<E, P>
where
E: Encoding<P>,
P: PeerEncoding, An 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: This is where some of the trait complexity comes from in my implementation. |
b480b0e
to
f57e7dd
Compare
f57e7dd
to
05e11e3
Compare
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. |
05e11e3
to
ab77ced
Compare
ab77ced
to
7bf84f2
Compare
I have reworked the code to try and better take into account you concerns. Now there is are It is possible to add new forms of serialization, or to remove or add fields without modifying the other structures. |
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.
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>; |
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.
Hi @da2ce7 I see you have renamed stats fields.
SwarmMetadata
: https://github.com/torrust/torrust-tracker/blob/develop/src/core/torrent/mod.rs#L55-L67SwarmStats
: https://github.com/torrust/torrust-tracker/blob/develop/src/core/torrent/mod.rs#L76-L87
SwarmMetadata
contains the names defined in the BRP 48. And SwarmStats
the names we were using in the Tracker.
pub stats: SwarmStats, | ||
pub policy: AnnouncePolicy, |
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.
👍🏼
src/core/torrent/mod.rs
Outdated
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.
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).
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.
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.
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.
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.
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.
Awesome! @da2ce7 I really like this version.
ACK 7bf84f2 |
(da2ce7): Merge `SwarmStats` into `SwarmMetadata`.
7bf84f2
to
0e6fe33
Compare
@josecelano Ready for Merge |
ACK 0e6fe33 |
Ready For Review.