Tracker: make announce lifecycle explicit (started/completed/stopped), fix retries and startup race#540
Tracker: make announce lifecycle explicit (started/completed/stopped), fix retries and startup race#540ivoviz wants to merge 3 commits into
Conversation
|
Is the code AI generated? |
The commit messages are, yes. Rust is definitely not my first language though, so if anything looks off I'm happy to revise it. |
|
I can't merge as-is for a bunch of reasons It complicates the code and state with a bunch of variables. It's already complex enough, so we should be mindful of making it worse. It spawns a lot of tokio tasks, and the pattern I use now is to not spawn unless necessary, i.e. reduce the number of spawns. It doesn't use spawn_with_cancel. So I'm not sure it cleans up successfully at the end and doesn't leave lingering tasks around. if I were to do it, I'd first think how do do it right without creating a hacky solution on top. That's why I thought it's LLMs who wrote this - it's just solving the immediate task at hand without thinking about the larger codebase and its health. If I were to do it, I'd try creating some sort of event bus - for torrents, and for sessions, while keeping the tracker loop a Stream that consumes those events. Then the torrent_state/ components emit events like started/paused and whatever else might be useful. The tracker_comms task would subscribe to those events and do whatever needs to be done. There are a few problems to resolve also related to this:
I understand it's more complex than just hacking it to work, but these were the reasons I haven't done this yet myself. |
|
Yeah, I get the concerns and I agree. I ran into the same pause -> cancel issues you mentioned while testing, which is why the solution ended up a bit workaroundish. I did try to be careful about cleaning up spawned tasks, but I agree that something closer to the approach you described would be much cleaner long term. I’ve since spent some more time digging into the codebase, but I’m still not sure what the right way to handle the stop/pause case is without introducing new hacks. If you have any guidance on how you’d approach that part, I’m happy to give it another shot. Also, down the line it would be nice to support manual per tracker announces and tracker tiers, but that’s probably a separate discussion. |
|
Thanks for your understanding. I'll think about how to approach it, need to refresh my memory of how all this works first. Will update here once I have an update |
|
Wrote some thoughts on this, formatted with Claude Event bus per torrentThe core idea is to have an event bus per torrent. Things can emit events into it, subscribers can subscribe. Can use a This assumes events are relatively infrequent. If the channel fills up (it shouldn't), can use Events
In the future we might want more granularity like "resolving magnet" or whatever. On a side note, some time ago I tried adding Wiring it upCreate the event bus at the moment the torrent is added and just keep it around. Pass it into Each tracker can subscribe to it and do its thing: Notice, no new Handling pause/cancelWhile torrent is live, peer rx is driven by
This can be some extension to Open issue: DHTEnsuring peer_rx dies by itself on |
|
Thanks for the detailed write-up, I’ll try to rework this along these lines in the next couple of days. AFAIK the protocol, the The |
|
I think that's how I wrote it, but you are right, I didn't look at the protocol details while writing this, the challenge is not there, but in the refactoring itself.
Here are my raw notes for what it's worth :) prerequisite: event bus per torrent. Things can emit events into it, subscribers can subscribe. That assumes events are relatively infrequent. If the channel fills up (it shouldn't) can use PeerRxTorrentInfo that is already passed into TrackerComms to understand what state the torrent is in. Started/Paused/Completed are obvious events to start off with. Create the event bus at the moment the torrent is added and just keep it around. Each tracker can subscribe to it and do its thing - select {if live => loop forever, on paused => pause and quit, on completed => notify if needed (don't rememeber the protocol), and keep looping} Notice, no new tokio::spawns are needed anywhere here. While torrent is live, peer rx is driven by
Ensuring peer_rx dies by itself on TorrentEvent::Paused would be awesome too. DHT implementation will get in the way though as it has no clue about cancellations today. Might need to wrap DHT stream in some way to stop itself (by dropping) on cancel. |
|
I'm not familiar with the tracker protocol as it exists in real production use cases, but it seems excessive to have room for multiple (128) "current states" in memory in the event channel when only the most recent state should matter for announces. From Bep 003:
It seems like TrackerComms already handles sending I agree that Maybe Your project seems very nice so far, but I'm just getting started looking at the internals, so forgive me if I'm way off base with my take here. |
|
I’m actually coming from the other side here (meaning I wrote the tracker part). To be fair, most of these events only really matter on private trackers.
|
|
I guess I'll be that guy and post my Claude chat on this subject: https://claude.ai/share/27539cc4-627d-40e4-9859-7d0766e7be7b Basically:
|
|
@teohhanhui do you have something constructive to add to the discussion? I understand some people have negativity toward LLM usage, but I don't think I'm going against the policy of the project. I am an experienced rust developer (been using is since shortly after version 1.0) and I have already vetted the chatbot's output and used my own brain to think through things. I'm also upfront with exactly how I used AI and exactly where my experience is lacking. For everyone else in the thread, I don't want to be seen as blocking a PR unnecessarily. I just want to help find a precise and efficient solution. The bittorrent protocol has interested me for a long time, and this project more recently. If there's a better place to have the design discussion let me know! |
|
Thanks @ivoviz @evanrichter for your input and expertise on the matter, it seems that you guys can figure out the best way to approach this.
this is reasonable
I was thinking to reuse the tracker bus in other parts to decouple things / decrease spaghetti. The one use-case I had at first was when I launched rqbit on Android through C bindings (none of this is merged), and I needed to let C know about state changes and other things like progress. sync::watch may work here too. I'm not bound to event bus approach, as long as the PR doesn't make things worse. The current unidirectional design "tracker comms is a stream" doesn't work for this feature, so it needs to be refactored somehow. |
|
@iPLAYCAFE
|
Fixes #539 (may also address related tracker announce edge cases).
started,completed,stopped) -pausedis still missing but should be straightforward to add in a follow-upstartedonly after the torrent is fully initialized and live (previously it could announce before hash checking finished, resulting in an incorrectleftvalue)intervalinstead ofmin_intervalEdit: also made
peersandpeers6Optionas announce parsing would otherwise fail when using IPv6.