Enhance proxy handling and error reporting in collection process
- Introduced a `Via` field in `ParseError` to indicate the proxy address used during requests, improving clarity on error contexts. - Updated `ProxyPool` to prioritize confirmed live proxies while available, ensuring more reliable proxy selection and reducing connection timeouts. - Implemented fallback logic to allow the use of unconfirmed proxies when no confirmed ones are available, preventing collection stalls. - Adjusted logging in `CollectLogEntryViewModel` to include proxy details, enhancing error visibility for users. - Added unit tests to verify new proxy selection logic and ensure correct behavior under various conditions. These changes improve the robustness of the proxy management system and enhance the overall user experience by providing clearer error messages and more efficient proxy usage.
This commit is contained in:
@@ -341,6 +341,59 @@ public class ProxyPoolTests
|
||||
lease!.Endpoint.Host.ShouldBe("fast");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Only_confirmed_proxies_are_handed_out_while_any_are_confirmed()
|
||||
{
|
||||
// Ordering was not enough: round-robin and weighted-random draw from the whole list, so on a
|
||||
// feed of a few thousand unchecked addresses nearly every pick was a stranger.
|
||||
var pool = Build(
|
||||
out _,
|
||||
out _,
|
||||
out var clock,
|
||||
new ProxyOptions { Rotation = ProxyRotation.RoundRobin },
|
||||
hosts: ["unchecked-a", "known-good", "unchecked-b", "unchecked-c"]
|
||||
);
|
||||
await pool.RefreshAsync(TestContext.Current.CancellationToken);
|
||||
|
||||
pool.Entries.Single(entry => entry.Endpoint.Host == "known-good")
|
||||
.RecordProbe(clock.GetUtcNow(), alive: true, TimeSpan.FromMilliseconds(30), null);
|
||||
|
||||
for (var attempt = 0; attempt < 8; attempt++)
|
||||
{
|
||||
var lease = await pool.AcquireAsync(TestContext.Current.CancellationToken);
|
||||
lease.ShouldNotBeNull().Endpoint.Host.ShouldBe("known-good");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task With_nothing_confirmed_the_pool_still_hands_something_out()
|
||||
{
|
||||
// Unknown is not dead. A strict filter on a cold pool would stop the collector rather than
|
||||
// let it try, and a proxy that answers on this path marks itself live by succeeding.
|
||||
var pool = Build(out _, out _, out _, hosts: ["a", "b"]);
|
||||
await pool.RefreshAsync(TestContext.Current.CancellationToken);
|
||||
|
||||
pool.LiveCount.ShouldBe(0);
|
||||
(await pool.AcquireAsync(TestContext.Current.CancellationToken)).ShouldNotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_proxy_that_has_just_failed_is_not_preferred_over_a_confirmed_one()
|
||||
{
|
||||
var pool = Build(out _, out _, out var clock, hosts: ["failed", "known-good"]);
|
||||
await pool.RefreshAsync(TestContext.Current.CancellationToken);
|
||||
|
||||
// Dead but not yet quarantined: it used to stay in the draw at full weight.
|
||||
pool.Entries.Single(entry => entry.Endpoint.Host == "failed")
|
||||
.RecordProbe(clock.GetUtcNow(), alive: false, null, "no route");
|
||||
pool.Entries.Single(entry => entry.Endpoint.Host == "known-good")
|
||||
.RecordProbe(clock.GetUtcNow(), alive: true, TimeSpan.FromMilliseconds(50), null);
|
||||
|
||||
var lease = await pool.AcquireAsync(TestContext.Current.CancellationToken);
|
||||
|
||||
lease.ShouldNotBeNull().Endpoint.Host.ShouldBe("known-good");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Changed_fires_when_the_pool_moves()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user