fix: Missing terms when using term filters

When using filters like `exclude`, it was possible for terms to not get
synced when they should have. This was due to a misunderstanding of how
`ExceptBy()` and `IntersectBy()` work. According to [an issue][1] on the
dotnet runtime repo, this is by design. The fix is to just avoid those
in favor of `Where()`.

Fixes #69.

[1]: https://github.com/dotnet/dotnet-api-docs/issues/7656
pull/76/head
Robert Dailey 2 years ago
parent 3653c2aea1
commit d84b5c5093

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed
- Sonarr: Fix unexpected missing terms when using filters. (#69)
## [2.0.1] - 2022-05-19 ## [2.0.1] - 2022-05-19
### Fixed ### Fixed

@ -18,7 +18,9 @@ public class ReleaseProfileDataFiltererTest
{ {
new() {TrashId = "1", Term = "term1"}, new() {TrashId = "1", Term = "term1"},
new() {TrashId = "2", Term = "term2"}, new() {TrashId = "2", Term = "term2"},
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
}; };
var result = sut.IncludeTerms(terms, filter); var result = sut.IncludeTerms(terms, filter);
@ -42,7 +44,9 @@ public class ReleaseProfileDataFiltererTest
{ {
new() {TrashId = "1", Term = "term1"}, new() {TrashId = "1", Term = "term1"},
new() {TrashId = "2", Term = "term2"}, new() {TrashId = "2", Term = "term2"},
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
} }
}, },
new() new()
@ -77,14 +81,18 @@ public class ReleaseProfileDataFiltererTest
{ {
new() {TrashId = "1", Term = "term1"}, new() {TrashId = "1", Term = "term1"},
new() {TrashId = "2", Term = "term2"}, new() {TrashId = "2", Term = "term2"},
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
}; };
var result = sut.ExcludeTerms(terms, filter); var result = sut.ExcludeTerms(terms, filter);
result.Should().BeEquivalentTo(new TermData[] result.Should().BeEquivalentTo(new TermData[]
{ {
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
}); });
} }
@ -101,7 +109,9 @@ public class ReleaseProfileDataFiltererTest
{ {
new() {TrashId = "1", Term = "term1"}, new() {TrashId = "1", Term = "term1"},
new() {TrashId = "2", Term = "term2"}, new() {TrashId = "2", Term = "term2"},
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
} }
}, },
new() new()
@ -109,7 +119,9 @@ public class ReleaseProfileDataFiltererTest
Score = 20, Score = 20,
Terms = new TermData[] Terms = new TermData[]
{ {
new() {TrashId = "4", Term = "term4"} new() {TrashId = "4", Term = "term4"},
new() {Term = "term6"},
new() {Term = "term7"}
} }
} }
}; };
@ -123,7 +135,9 @@ public class ReleaseProfileDataFiltererTest
Score = 10, Score = 10,
Terms = new TermData[] Terms = new TermData[]
{ {
new() {TrashId = "3", Term = "term3"} new() {TrashId = "3", Term = "term3"},
new() {Term = "term4"},
new() {Term = "term5"}
} }
}, },
new() new()
@ -131,7 +145,9 @@ public class ReleaseProfileDataFiltererTest
Score = 20, Score = 20,
Terms = new TermData[] Terms = new TermData[]
{ {
new() {TrashId = "4", Term = "term4"} new() {TrashId = "4", Term = "term4"},
new() {Term = "term6"},
new() {Term = "term7"}
} }
} }
}); });

@ -21,22 +21,22 @@ public class ReleaseProfileDataFilterer
} }
public ReadOnlyCollection<TermData> ExcludeTerms(IEnumerable<TermData> terms, public ReadOnlyCollection<TermData> ExcludeTerms(IEnumerable<TermData> terms,
IEnumerable<string> includeFilter) IEnumerable<string> excludeFilter)
{ {
return terms return terms
.ExceptBy(includeFilter, x => x.TrashId, StringComparer.InvariantCultureIgnoreCase) .Where(x => !excludeFilter.Contains(x.TrashId, StringComparer.InvariantCultureIgnoreCase))
.IsValid(new TermDataValidator(), (e, x) => LogInvalidTerm(e, $"Exclude: {x}")) .IsValid(new TermDataValidator(), (e, x) => LogInvalidTerm(e, $"Exclude: {x}"))
.ToList().AsReadOnly(); .ToList().AsReadOnly();
} }
public ReadOnlyCollection<PreferredTermData> ExcludeTerms(IEnumerable<PreferredTermData> terms, public ReadOnlyCollection<PreferredTermData> ExcludeTerms(IEnumerable<PreferredTermData> terms,
IReadOnlyCollection<string> includeFilter) IReadOnlyCollection<string> excludeFilter)
{ {
return terms return terms
.Select(x => new PreferredTermData .Select(x => new PreferredTermData
{ {
Score = x.Score, Score = x.Score,
Terms = ExcludeTerms(x.Terms, includeFilter) Terms = ExcludeTerms(x.Terms, excludeFilter)
}) })
.IsValid(new PreferredTermDataValidator(), (e, x) => LogInvalidTerm(e, $"Exclude Preferred: {x}")) .IsValid(new PreferredTermDataValidator(), (e, x) => LogInvalidTerm(e, $"Exclude Preferred: {x}"))
.ToList() .ToList()
@ -47,9 +47,8 @@ public class ReleaseProfileDataFilterer
IEnumerable<string> includeFilter) IEnumerable<string> includeFilter)
{ {
return terms return terms
.IntersectBy(includeFilter, x => x.TrashId, StringComparer.InvariantCultureIgnoreCase) .Where(x => includeFilter.Contains(x.TrashId, StringComparer.InvariantCultureIgnoreCase))
.IsValid(new TermDataValidator(), .IsValid(new TermDataValidator(), (e, x) => LogInvalidTerm(e, $"Include: {x}"))
(e, x) => LogInvalidTerm(e, $"Include: {x}"))
.ToList().AsReadOnly(); .ToList().AsReadOnly();
} }

Loading…
Cancel
Save