Skip to content

Overhaul stats: fix bug in downloads counter#1503

Merged
josecelano merged 1 commit into
torrust:developfrom
josecelano:1502-overhaul-stats-fix-bug-in-downloads-counter-reverting-change
May 7, 2025
Merged

Overhaul stats: fix bug in downloads counter#1503
josecelano merged 1 commit into
torrust:developfrom
josecelano:1502-overhaul-stats-fix-bug-in-downloads-counter-reverting-change

Conversation

@josecelano
Copy link
Copy Markdown
Member

Relates to: #1502

Revert the change that introduced a bug in this commit.

Issue #1502 has been partially implemented.

  • Bug fixed.
  • Unit tests added to avoid regression.

In a future PR, I will implement a change to avoid keeping the swarms in memory just to track the number of downloads for that torrent.

… metric

Relates to: torrust@34c159a

A couple of days ago, I made a change in [this commit](torrust@34c159a).

I changed the `Swarm::meets_retaining_policy` method from:

```
/// Returns true if the torrents meets the retention policy, meaning that
/// it should be kept in the tracker.
pub fn meets_retaining_policy(&self, policy: &TrackerPolicy) -> bool {
    if policy.persistent_torrent_completed_stat && self.metadata().downloaded > 0 {
        return true;
    }

    if policy.remove_peerless_torrents && self.is_empty() {
        return false;
    }

    true
}
```

To:

```
pub fn meets_retaining_policy(&self, policy: &TrackerPolicy) -> bool {
    !(policy.remove_peerless_torrents && self.is_empty())
}
```

I thought this code was not needed:

```rust
if policy.persistent_torrent_completed_stat && self.metadata().downloaded > 0 {
    return true;
}
```

However, it's needed.

One of the metrics returned by the tracker API is the **total number of downloads for all torrents**.

```json
{
  "torrents": 320961,
  "seeders": 189885,
  "completed": 975119, <- this
  "leechers": 231044,
  ...
}
```

That metric is always stored in memory but can optionally persist into the database.

It's important to highlight that the metric represents:

- The total number of downloads for **ALL** torrents ever, when the metric is persisted.
- The total number of downloads for **ALL** torrents since the tracker started, when the metric is not persisted.

It could be mixed up with another internal metric (not exposed via the API), which is the same counter but only for ONE swarm (one torrent).

- The total number of downloads for **ONE** concrete torrent ever, when the metric is persisted.
- The total number of downloads for **ONE** concrete torrent since the tracker started, when the metric is not persisted.

The bug affects the first metric. The exposed via the API.

The problem is that this feature conflicts with removing the peerless torrents.

When removing the peerless torrents config option is enabled, the counter is lost unless it is persisted. Becuase the counter values are stored in the "Swarm" together with the list of peers.

If statistics persistence is enabled, that's not a problem. When the torrent is removed from the tracker (from the swarms or swarm collection), the counter is initialised again if the torrent is added. In other words, if a new peer starts the swarm again, the number of downloads is loaded from the database.

However, that works for the counter of each torrent (swarm) but not for the overall counter (the sum of downloads for all torrents). That metric is not stored anywhere. It's calculated on demand by iterating all the swarms and summing up the total for each torrent, giving the total amount of downloads for **ALL** torrents.

When the torrent is removed, the downloads for that torrent don't count in the total. That is the reason we have to keep the torrent (swarm) in memory, even if it does not have any peer (and it should be removed according to the other config flag).

The removed line:

```rust
if policy.persistent_torrent_completed_stat && self.metadata().downloaded > 0 {
    return true;
}
```

does that.

**When the stats persistence is disabled**, that's one way to store the value.

Alternatively, we could add another cache for the data and never remove that value.

The current solution has a problem: It can make the tracker consume a lot of memory because peerless torrents are not removed in practice (even if it's configured to be).

**When the stats persistence is enabled,** we can simply return the value from the database.

**NOTICE:** that the value is used in the scrape response, so it might be convenient to have a cache in memory anyway.

- [x] Revert the change to fix the bug asap.
- [x] Write a unit test. This behaviour was not covered by any test (or documented).
- [ ] Add an in-memory cache value in `Swarms` type to store the total for all torrents, regardless of which are the current active swarms.
@josecelano josecelano self-assigned this May 7, 2025
@josecelano josecelano requested a review from da2ce7 May 7, 2025 16:10
@josecelano
Copy link
Copy Markdown
Member Author

ACK 32a37d1

@josecelano josecelano added the Bug Incorrect Behavior label May 7, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 83.84%. Comparing base (3adbb89) to head (32a37d1).
Report is 2 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1503      +/-   ##
===========================================
+ Coverage    83.81%   83.84%   +0.03%     
===========================================
  Files          257      257              
  Lines        17837    17876      +39     
  Branches     17837    17876      +39     
===========================================
+ Hits         14950    14989      +39     
  Misses        2616     2616              
  Partials       271      271              

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@josecelano josecelano merged commit 5ee9efb into torrust:develop May 7, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Incorrect Behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant