rqbit icon indicating copy to clipboard operation
rqbit copied to clipboard

Example with resumable torrent

Open latot opened this issue 10 months ago • 4 comments

Hi! thx for the project :D

I'm looking how to use librqbit, I suppose the cli resumes the torrents (do not check them all again!), seems AddTorrentOptions has some params for example preferred_id which says is to resume the torrent, but I don't really get what needs to be implemented to do that works.

In libtorrent-rasterbar we get some data, save it (some apps do it in a database) and we can use the same data to start again the torrent, here we only need preferred_id to do it?

Which leads to a new question, the word says preferred which I think implies the lib needs to that id be free, but if not the torrent will not be resumable?

Well, I think a example and improve some docs could help a lot to this.

The closest think I found I don't know if they are even related (to start again a torrent) is https://github.com/ikatson/rqbit/blob/main/crates/librqbit/examples/custom_storage.rs

The issue with that example is the lack of documentation to the Traits and some functions which uses the structs that implements them.

Thx!

latot avatar Feb 17 '25 00:02 latot

Hi,

In the options you need to enable session persistence. And then choose a folder to store it (if using JSON backend). There's also a postgres backend

ikatson avatar Feb 17 '25 01:02 ikatson

Let me also expand on that a bit more to ensure I answer your question better

  • As long as the session is running, resuming (unpause) and pausing can happen at any time
  • If session persistence is enabled, it stores state in a file or DB. Then when you initialize a session with the same persistence backend, it will pick up where it left from.
  • If not using persistence, if you create a new session, and add a torrent into the same output folder as it was before, it will re-check it and then resume from where it left off. You need to set "overwrite: true" for that to work, otherwise it'll complain that it doesn't want to touch already existing files.
  • To increase the speed with which it checks, you can also enable fastresume. It's not default as relatively new, but I haven't ever had any issues with it, so probably we can make that default soon.

ikatson avatar Feb 17 '25 01:02 ikatson

is possible to use fastresume per torrent and not being handled from the session?

I'm looking to try port a project I have in libtorrent-rasterbar, I wrote it with several things in mind, you load a folder where will look for all torrent files (recursively in folders), and then will add as download path the folder "data" where is the torrent, also will save there the fastresume information of the torrent.

So, any torrent, magnet that is added this folder, or moved will be handled by the app, this also makes this folder portable so I can start the torrents in anytime, which is nice when you have a lot of TB of info (I also use torrents as backup).

Do you think this could be dine with actual librqbit? usually while I can get/set the fast resume information per torrent should not be a problem.

latot avatar Feb 17 '25 12:02 latot

It is certainly possible, but its not how it's done right now. It should be easy to add though, just need to pass it through.

trait BitVFactory (name stands for bitvector factory) is what creates them now. Today when persistence is disabled it's a noop, otherwise it gets stored in session persistence (folder with mmaped files or postgres byte field).

I can accept a PR if you expose BitVFactory and let you override it per torrent. Here's where it's used right now. It gets the factory from the session, but if the user passed it in you can store it per torrent in e.g. ManagedTorrentShared

ikatson avatar Feb 17 '25 14:02 ikatson

Hi! has been long time, and now I tried to implement this!

@ikatson I worked on this today, but has not been as easy as I thought, actually add an option to store BitVFactory is easy, update the code, where is needed, a custom function to get it from the torrent and if not exists from the session, all that fine.

The challange part seems to be add this to AddTorrentOptions, to make this works, we would need to use a Arc<dyn BitVFactory> inside the options to set the custom bitv_factory, and the options needs the Deserialze which requires Size, so we can't add this option easily from AddTorrentOptions.

There a few options about this, I have not used Tauri, so no idea why AddTorrentOptions requires Deserialize.

Options I can think:

  1. Use generics, this would force to all bitv_factory be the same, I don't like this idea, is like a hard limit specially if someone wants to use the lib.
  2. Do not init the bitv_factory with the options, start it as None and make a function which allow us to set a new one. This have several issues, one is that the feature will be hidden (we can't found it in the new function), also is like an anti-pattern, is not clear.

From both options I like more the second one, just because it keeps flexibility, would be ideal be able to init this using the right type, but how I don't know why Deserialize is needed nor how is used, I don't know how to make a different builder which has the right needed options.

latot avatar May 11 '25 21:05 latot

Deserialize is used in HTTP API, it deserializes from JSON.

Can you try to use serde skip https://serde.rs/field-attrs.html#skip with a default None?

ikatson avatar May 12 '25 03:05 ikatson

I have mixed feeling, I know that should works, but is like too awful for other crates and http api..., is like we should use a generic with an enum and request a trait in each variant, or something like that, but the actual solution also could works, maybe I'm over thinking this.

latot avatar May 13 '25 23:05 latot