Package: prunerr
TL;DR: Perma-seeding of whole Servarr libraries optimized for per-tracker ratio.Delete torrents/itemsonly as disk space gets low.Don’t deletecurrently imported items.
IOW, only delete upgraded items.Don’t deleteprivate items that haven’t met seeding requirements.Deletepublic items first.Delete private items inan order to maximize tracker ratio and/or bonuses.Deletestalled items, anditems containing archives such as *.rar
releasesandblacklist them,
AKA mark them as failed, in Servarr.And more…Table of ContentsSummaryInstallationLocal InstallationDocker Container ImageUsageOrder of OperationsContributingMotivationReferencesSummarySeed Servarr download client torrents/items as long as possible only deleting them as
necessary as disk space gets low, hence the name based on “to prune”. Which download
items are considered eligible for deletion is configured by the user. The common case is
that download items that are currently imported are not considered for deletion.
Neither are items from private trackers/indexers that have been upgraded or otherwise
deleted from the library but haven’t met the indexers seeding requirements. The order in
which download items are deleted is determined according to rules configured by the
user. The common case is to delete items from public indexers first and among those to
delete the items with the highest ratio first to preserve the health of the community by
seeding less popular items longer. Next delete items from private indexers by configured
indexer priority and within the items for a given indexer to delete items in an order to
maximize ratio and/or seeding rewards.Other configured operations may be applied as well. For example:Verify and resume corrupt itemsIncrease bandwidth priority for items from private indexersDecrease bandwidth priority for items from public indexersRemove and blacklist download items containing archives (*.rar,*.zip,*.tar.gz, etc.) which can’t be perma-seededRemove and blacklist stalled download itemsetc.The$ prunerrcommand is intended to serve as a companion to theServarr[1]suite of
applications and services and theTransmission BitTorrent client[2]. It periodically
polls thedownload clients[3]ofSonarr[4],Radarr[5], etc. and applies the configured
operations to the download items in each of those download clients. It can also be run
independently of any Servarr instances to optimize seeding for download items added by
other means, e.g.FlexGet[6].See theUsagesection below for full details.InstallationInstall locally or use the Docker container image:Local InstallationInstall by using any tool for installing standard Python 3 distributions such aspip[7]:$ pip3 install --user prunerrOptional shell prompt tab completion is available by usingargcomplete[8].Docker Container ImageThe recommended way to use the container image is by usingDocker Compose[9]. Seethe
example ./docker-compose.yml file[10]. Write your configuration and run the container:$ docker compose upYou can also use the image directly. Pullthe Docker image[11]. Use it to create and run
a container:$ docker pull "registry.gitlab.com/rpatterson/prunerr"
$ docker run --rm -it "registry.gitlab.com/rpatterson/prunerr" ...Use image variant tags to control when the image updates. Releases publish tags for the
branch and for major and minor versions. For example, to keep up to date with a specific
branch, use a tag such asregistry.gitlab.com/rpatterson/prunerr:main. Releases fromdeveloppublish pre-releases. Releases frommainpublish final releases. Releases frommainalso publish tags without a branch, for exampleregistry.gitlab.com/rpatterson/prunerr. Releases frommainalso
publish tags for the major and minor version, for exampleregistry.gitlab.com/rpatterson/prunerr:v0.8.Releases publish multi-platform images for the following platforms:linux/amd64linux/arm64linux/arm/v7UsageStart by writing your~/.config/prunerr.ymlconfiguration file. See the comments inthe example configuration[12]for details.Once configured, you may run individual sub-commands once, run all operations once as
configured using the$ prunerr execsub-command, or run all operations in a polling
loop using the$ prunerr daemonsub-command. See theOrder of Operationssection
for a detailed description of the operations. Use the CLI help to list the other
sub-commands and to get help on the individual sub-commands:$ prunerr --help
$ prunerr exec --helpIf using the Docker container image, the container can be run from the command-line as
well:$ docker compose run "prunerr" prunerr --helpOrder of OperationsNote that polling is required because there is no event we can subscribe to that
reliably determines disk space marginasthe download clients are downloading. Every
run of the$ prunerr execsub-command or every loop of the$ prunerr daemonsub-command performs the following operations.Verify and resume corrupt items, same as:$ prunerr verify.Review download items, same as:$ prunerr review:Apply per-indexer review operations as configured underindexers/reviewsin the
configuration file to all download items.Move download items that have been acted on by Servarr to the*/seeding/*directory, same as:$ prunerr move.As Servarr acts on completed download items, be that importing files from them,
ignoring them, deleting them from the queue, etc., Prunerr moves those items from the
Servarr download client’sDirectoryto a parallel*/seeding/*directory.
Then when deleting download items to free space, Prunerr only considers items under
that directory. This has the added benefit of reflecting which items have been acted
on by Servarr in the download client.Delete download items if disk space is low, same as:$ prunerrfree-space.Consider items for deletion in different groups in this order:Download items no longer registered with tracker.IOW, items that can no longer be seeded at all first.Orphan files and directories not belonging to any download itemWalk all the top-level directories used by each download client and identify which
paths don’t correspond to a download client item.Imported/seeding download itemsIOW, download items that have been acted upon by Servarr and moved to the*/seeding/*directory by the$ prunerr movesub-command/operation
excluding those items filtered out according to theindexers/prioritiesoperations withfilter: true. For example, don’t delete currently imported
items (by hard link count) or items that haven’t met private indexer seeding
requirements.For each of these groups in order, loop through each item in the group and:Check disk space against the margin configured bydownload-clients/max-download-bandwidthanddownload-clients/min-download-time-marginIf there’s sufficient disk space, remove any bandwidth limits set previously and
continue to the next operation if any.Otherwise, delete the item.If there’s still not enough disk space after going through all the groups, then stop
downloading by setting the download bandwidth limit to0. IOW, keep seeding, but
no more downloading until a future$ prunerrfree-spacerun is able to free
sufficient space.For the orphans group, delete smaller items first to minimize the amount of
re-downloading needed should the user notice and correct any issues resulting in the
orphans.For the other groups delete items in the order determined by the configuredindexers/prioritiesindexer order then by the configured operations for that
item’s indexer.The Docker container image can run the command-line script as well:$ docker compose run "prunerr" prunerr --help
usage: prunerr [-h]

prunerr foundation or template, top-level package.

optional arguments:
  -h, --help  show this help message and exitContributingGitLab hosts this project[13]andmirrors it to GitHub[14]but use GitLab for reporting
issues, submitting pull or merge requests and any other development or maintenance
activity. Seethe contributing documentation[15]for more details on how to get started
with development.MotivationI didn’t like the available options I could find at the time for maximizing seeding from
a lovingly managed media library. Deleting by a ratio threshold doesn’t make sense to me
because that can delete items when there’s plenty of disk space. Also the ratio
threshold is a reverse indicator for items from private indexers vs items from public
indexers. Items from private indexers with high ratios should be kept around as long as
possible to build user total ratio whereas items from public indexers with low ratios
should be kept around as long as possible to preserve access in the community/ecosystem.
Finally, deleting any item still imported in the Servarr only because it hit the ratio
threshold is the biggest waste since it doesn’t free any space. So I wrote Prunerr to
prune download items in the correct order.The use case for Prunerr is not tracker ratio racing. It’s goal is to seed as long as
possible and to seed as much of your library as possible. This should have some
secondary benefits to ratio, but that’s not the main goal.Finally, there is a laundry list of other download client management tasks that can be
automated but aren’t by anything I could find. So I added them to Prunerr as well.References[1]https://wiki.servarr.com[2]https://transmissionbt.com/[3]https://wiki.servarr.com/radarr/settings#download-clients[4]https://wiki.servarr.com/en/sonarr[5]https://wiki.servarr.com/en/radarr[6]https://flexget.com/[7]https://pip.pypa.io/en/stable/installation/[8]https://kislyuk.github.io/argcomplete/#installation[9]https://docs.docker.com/compose/[10]https://gitlab.com/rpatterson/prunerr/-/blob/main/docker-compose.yml[11]https://hub.docker.com/r/merpatterson/prunerr[12]https://gitlab.com/rpatterson/prunerr/blob/main/src/prunerr/home/.config/prunerr.yml[13]https://gitlab.com/rpatterson/prunerr[14]https://github.com/rpatterson/prunerr[15]https://gitlab.com/rpatterson/prunerr/-/blob/main/docs/contributing.rst