< Summary - SonghayCore

Information
Class: Songhay.Net.TimeoutHandler
Assembly: SonghayCore
File(s): /home/rasx/sourceRoot/SonghayCore/SonghayCore/Net/TimeoutHandler.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 21
Coverable lines: 21
Total lines: 65
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 4
Branch coverage: 0%
Method coverage

Method coverage is only available for sponsors.

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_DefaultTimeout()100%10%
get_RequestTimeout()100%10%
SendAsync()0%20%
GetCancellationTokenSource(...)0%20%

File(s)

/home/rasx/sourceRoot/SonghayCore/SonghayCore/Net/TimeoutHandler.cs

#LineLine coverage
 1namespace Songhay.Net;
 2
 3/// <summary>
 4/// Defines timeout and cancellation support
 5/// for <see cref="HttpClient"/>.
 6/// </summary>
 7/// <seealso cref="DelegatingHandler" />
 8/// <remarks>
 9/// 📖 see “Better timeout handling with HttpClient”
 10/// by @thomaslevesque [ https://github.com/thomaslevesque ]
 11/// [ https://thomaslevesque.com/2018/02/25/better-timeout-handling-with-httpclient/ ]
 12///
 13/// </remarks>
 14public class TimeoutHandler : DelegatingHandler
 15{
 16    /// <summary>
 17    /// Gets or sets the default timeout.
 18    /// </summary>
 019    public static TimeSpan DefaultTimeout { get; } = TimeSpan.FromSeconds(100);
 20
 21    /// <summary>
 22    /// Gets or sets the request timeout.
 23    /// </summary>
 024    public TimeSpan RequestTimeout { get; init; } = DefaultTimeout;
 25
 26    /// <summary>
 27    /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
 28    /// </summary>
 29    /// <param name="request">The HTTP request message to send to the server.</param>
 30    /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
 31    /// <returns>
 32    /// The task object representing the asynchronous operation.
 33    /// </returns>
 34    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
 35        CancellationToken cancellationToken)
 036    {
 037        using var cts = GetCancellationTokenSource(cancellationToken);
 38        try
 039        {
 040            return await base
 041                .SendAsync(request, cts?.Token ?? cancellationToken)
 042                .ConfigureAwait(continueOnCapturedContext: false);
 43        }
 044        catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
 045        {
 046            throw new TimeoutException();
 47        }
 048    }
 49
 50    CancellationTokenSource? GetCancellationTokenSource(CancellationToken cancellationToken)
 051    {
 052        if (RequestTimeout == Timeout.InfiniteTimeSpan)
 053        {
 54            // No need to create a CTS if there's no timeout
 055            return null;
 56        }
 57        else
 058        {
 059            var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
 060            cts.CancelAfter(RequestTimeout);
 61
 062            return cts;
 63        }
 064    }
 65}