Add paused and queued Deluge states for Download Cleaner#596
Conversation
|
@sourcery-ai review |
|
@greptileai review |
Reviewer's GuideIntroduces a strongly-typed DelugeState enum and JSON converter, wires it into DownloadStatus deserialization and Deluge client field selection, and updates seeding/ downloading logic and tests so that finished paused/queued torrents are treated as seeding while null/invalid hashes and unknown states are handled safely. Sequence diagram for GetSeedingDownloads with new DelugeState handlingsequenceDiagram
actor Cleaner
participant DelugeServiceDC
participant DelugeClientWrapper as ClientWrapper
participant DownloadStatus
participant DelugeItemWrapper
Cleaner->>DelugeServiceDC: GetSeedingDownloads()
DelugeServiceDC->>ClientWrapper: GetStatusForAllTorrents()
ClientWrapper-->>DelugeServiceDC: List<DownloadStatus> downloads or null
alt downloads is null
DelugeServiceDC-->>Cleaner: empty List<ITorrentItemWrapper>
else downloads not null
loop for each DownloadStatus x in downloads
alt x.Hash is null or empty
DelugeServiceDC-->>DelugeServiceDC: skip x
else if x.State == DelugeState.Seeding
DelugeServiceDC->>DelugeItemWrapper: new DelugeItemWrapper(x)
DelugeItemWrapper-->>DelugeServiceDC: wrapper
else if x.IsFinished == true and (x.State == DelugeState.Paused or x.State == DelugeState.Queued)
DelugeServiceDC->>DelugeItemWrapper: new DelugeItemWrapper(x)
DelugeItemWrapper-->>DelugeServiceDC: wrapper
else
DelugeServiceDC-->>DelugeServiceDC: skip x
end
end
DelugeServiceDC-->>Cleaner: List<ITorrentItemWrapper> seedingWrappers
end
Class diagram for DelugeState enum and related download status handlingclassDiagram
class DownloadStatus {
string Hash
DelugeState State
string Name
ulong Eta
long DownloadSpeed
bool Private
long Size
long TotalDone
bool IsFinished
string Label
}
class DelugeItemWrapper {
+DownloadStatus Info
+bool IsDownloading()
+bool IsStalled()
}
class DelugeServiceDC {
+Task~List~<ITorrentItemWrapper> GetSeedingDownloads()
}
class DelugeStateConverter {
+DelugeState ReadJson(JsonReader reader, Type objectType, DelugeState existingValue, bool hasExistingValue, JsonSerializer serializer)
+void WriteJson(JsonWriter writer, DelugeState value, JsonSerializer serializer)
}
class DelugeState {
<<enumeration>>
Unknown
Allocating
Checking
Downloading
Seeding
Paused
Error
Queued
Moving
}
DownloadStatus --> DelugeState : uses
DelugeStateConverter ..> DelugeState : converts
DownloadStatus ..> DelugeStateConverter : JsonConverter
DelugeItemWrapper --> DownloadStatus : wraps
DelugeServiceDC --> DownloadStatus : filters
DelugeServiceDC --> DelugeItemWrapper : creates
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="code/backend/Cleanuparr.Domain/Entities/Deluge/Response/DownloadStatus.cs" line_range="10" />
<code_context>
- public string? State { get; init; }
-
+
+ public DelugeState State { get; init; }
+
public string? Name { get; init; }
</code_context>
<issue_to_address>
**issue (bug_risk):** Enum-based State with StringEnumConverter may throw on unexpected Deluge values instead of defaulting to Unknown.
Changing from a nullable string to a non-nullable enum improves the model, but with `StringEnumConverter` any new/invalid state value from Deluge will now cause deserialization to fail instead of flowing through. To keep behavior resilient to unexpected/protocol-changed states, consider a custom `JsonConverter` (or handler) for `DelugeState` that maps unknown strings to `DelugeState.Unknown` instead of throwing.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Greptile SummaryThis PR adds support for Confidence Score: 5/5Safe to merge — focused, well-tested change with no logic defects. All changed files are covered by tests; no P0/P1 issues found. The enum replaces fragile string comparisons cleanly, the IsFinished guard correctly scopes Paused/Queued inclusion, and the existing JSON error-suppression in DelugeClient handles any unknown future state values safely. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[GetSeedingDownloads] --> B[GetStatusForAllTorrents]
B --> C{downloads is null?}
C -- Yes --> D[Return empty list]
C -- No --> E[Filter empty hashes]
E --> F{State?}
F -- Seeding --> G[Include torrent]
F -- Paused --> H{IsFinished?}
F -- Queued --> H
F -- Other --> I[Exclude torrent]
H -- true --> G
H -- false --> I
G --> J[Wrap in DelugeItemWrapper]
J --> K[Return list]
Reviews (1): Last reviewed commit: "added paused and queued Deluge statuses ..." | Re-trigger Greptile |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
@sourcery-ai review |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
DelugeStateConverter.WriteJson, consider emitting the exact wire format Deluge expects (e.g., lowercase strings and possiblynull/omitted forUnknown) instead ofvalue.ToString()in PascalCase, to avoid subtle integration issues if these states are ever sent back to Deluge or logged for debugging. - The seeding filter in
DelugeServiceDC.GetSeedingDownloadshas become a bit dense with the combinedStateandIsFinishedchecks; extracting this into a small helper (e.g.,IsConsideredSeeding(DownloadStatus x)) would make the business rules around seeding/finished/paused/queued states easier to understand and maintain.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `DelugeStateConverter.WriteJson`, consider emitting the exact wire format Deluge expects (e.g., lowercase strings and possibly `null`/omitted for `Unknown`) instead of `value.ToString()` in PascalCase, to avoid subtle integration issues if these states are ever sent back to Deluge or logged for debugging.
- The seeding filter in `DelugeServiceDC.GetSeedingDownloads` has become a bit dense with the combined `State` and `IsFinished` checks; extracting this into a small helper (e.g., `IsConsideredSeeding(DownloadStatus x)`) would make the business rules around seeding/finished/paused/queued states easier to understand and maintain.
## Individual Comments
### Comment 1
<location path="code/backend/Cleanuparr.Infrastructure/Features/DownloadClient/Deluge/DelugeServiceDC.cs" line_range="24" />
<code_context>
return downloads
.Where(x => !string.IsNullOrEmpty(x.Hash))
- .Where(x => x.State?.Equals("seeding", StringComparison.InvariantCultureIgnoreCase) is true)
+ .Where(x => x.State is DelugeState.Seeding || x is { IsFinished: true, State: DelugeState.Paused or DelugeState.Queued })
.Select(ITorrentItemWrapper (x) => new DelugeItemWrapper(x))
.ToList();
</code_context>
<issue_to_address>
**suggestion:** The seeding filter mixes `State` and `IsFinished` in a single pattern; extracting this into a named predicate would reduce the risk of subtle logic mistakes.
This line now encodes three rules at once: always include `Seeding`, include `Paused` when finished, and include `Queued` when finished. While correct per the tests, it’s dense and likely to become fragile as states evolve (e.g., new states or `Unknown`). Extracting a named predicate such as `bool IsConsideredSeeding(DownloadStatus x)` (or an equivalent method on `DownloadStatus`) would make the intent clearer and centralize seeding semantics in one place.
Suggested implementation:
```csharp
.Where(x => !string.IsNullOrEmpty(x.Hash))
.Where(IsConsideredSeeding)
.Select(ITorrentItemWrapper (x) => new DelugeItemWrapper(x))
```
To fully implement the suggestion, you should also introduce a dedicated predicate method that encapsulates the seeding semantics. For example, inside the `DelugeServiceDC` class (or wherever this query lives), add:
```csharp
private static bool IsConsideredSeeding(DownloadStatus x)
{
if (x is null)
{
return false;
}
return x.State is DelugeState.Seeding ||
x is { IsFinished: true, State: DelugeState.Paused or DelugeState.Queued };
}
```
Adjust `DownloadStatus` to the actual type of `downloads`’ elements if it differs. If nulls cannot appear in `downloads`, you can omit the null check. Centralizing the logic in this method makes the intent clearer and future changes to seeding semantics easier and safer.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Relates to #594
Summary by Sourcery
Handle Deluge torrent states via a strongly typed enum and extend seeding detection to include finished paused/queued torrents while hardening null/edge-case handling.
Enhancements:
Tests: