< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.BackoffTimeoutHelper
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Runtime/BackoffTimeoutHelper.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 50
Coverable lines: 50
Total lines: 133
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)100%110%
Reset(...)0%220%
IsExpired()0%220%
WaitAndBackoff(...)0%660%
WaitAndBackoff()100%110%
WaitTimeWithDrift()100%110%
Backoff()0%880%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Runtime/BackoffTimeoutHelper.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Threading;
 6
 7namespace CoreWCF.Runtime
 8{
 9    internal sealed class BackoffTimeoutHelper
 10    {
 011        private static readonly int s_maxSkewMilliseconds = 15;
 012        private static readonly long s_maxDriftTicks = s_maxSkewMilliseconds * 2 * TimeSpan.TicksPerMillisecond;
 013        private static readonly TimeSpan s_defaultInitialWaitTime = TimeSpan.FromMilliseconds(1);
 014        private static readonly TimeSpan s_defaultMaxWaitTime = TimeSpan.FromMinutes(1);
 15        private DateTime _deadline;
 16        private TimeSpan _maxWaitTime;
 17        private TimeSpan _waitTime;
 18        private IOThreadTimer _backoffTimer;
 19        private Action<object> _backoffCallback;
 20        private object _backoffState;
 21        private readonly Random _random;
 22        private TimeSpan _originalTimeout;
 23
 24        internal BackoffTimeoutHelper(TimeSpan timeout)
 025            : this(timeout, s_defaultMaxWaitTime)
 26        {
 027        }
 28
 29        internal BackoffTimeoutHelper(TimeSpan timeout, TimeSpan maxWaitTime)
 030            : this(timeout, maxWaitTime, s_defaultInitialWaitTime)
 31        {
 032        }
 33
 034        internal BackoffTimeoutHelper(TimeSpan timeout, TimeSpan maxWaitTime, TimeSpan initialWaitTime)
 35        {
 036            _random = new Random(GetHashCode());
 037            _maxWaitTime = maxWaitTime;
 038            _originalTimeout = timeout;
 039            Reset(timeout, initialWaitTime);
 040        }
 41
 42        public TimeSpan OriginalTimeout
 43        {
 44            get
 45            {
 046                return _originalTimeout;
 47            }
 48        }
 49
 50        private void Reset(TimeSpan timeout, TimeSpan initialWaitTime)
 51        {
 052            if (timeout == TimeSpan.MaxValue)
 53            {
 054                _deadline = DateTime.MaxValue;
 55            }
 56            else
 57            {
 058                _deadline = DateTime.UtcNow + timeout;
 59            }
 060            _waitTime = initialWaitTime;
 061        }
 62
 63        public bool IsExpired()
 64        {
 065            if (_deadline == DateTime.MaxValue)
 66            {
 067                return false;
 68            }
 69            else
 70            {
 071                return (DateTime.UtcNow >= _deadline);
 72            }
 73        }
 74
 75        public void WaitAndBackoff(Action<object> callback, object state)
 76        {
 077            if (_backoffCallback != callback || _backoffState != state)
 78            {
 079                if (_backoffTimer != null)
 80                {
 081                    _backoffTimer.Cancel();
 82                }
 083                _backoffCallback = callback;
 084                _backoffState = state;
 085                _backoffTimer = new IOThreadTimer(callback, state, false, s_maxSkewMilliseconds);
 86            }
 87
 088            TimeSpan backoffTime = WaitTimeWithDrift();
 089            Backoff();
 090            _backoffTimer.Set(backoffTime);
 091        }
 92
 93        // TODO: Consider making Async
 94        public void WaitAndBackoff()
 95        {
 096            Thread.Sleep(WaitTimeWithDrift());
 097            Backoff();
 098        }
 99
 100        private TimeSpan WaitTimeWithDrift()
 101        {
 0102            return Ticks.ToTimeSpan(Math.Max(
 0103                Ticks.FromTimeSpan(s_defaultInitialWaitTime),
 0104                Ticks.Add(Ticks.FromTimeSpan(_waitTime),
 0105                    (long)(uint)_random.Next() % (2 * s_maxDriftTicks + 1) - s_maxDriftTicks)));
 106        }
 107
 108        private void Backoff()
 109        {
 0110            if (_waitTime.Ticks >= (_maxWaitTime.Ticks / 2))
 111            {
 0112                _waitTime = _maxWaitTime;
 113            }
 114            else
 115            {
 0116                _waitTime = TimeSpan.FromTicks(_waitTime.Ticks * 2);
 117            }
 118
 0119            if (_deadline != DateTime.MaxValue)
 120            {
 0121                TimeSpan remainingTime = _deadline - DateTime.UtcNow;
 0122                if (_waitTime > remainingTime)
 123                {
 0124                    _waitTime = remainingTime;
 0125                    if (_waitTime < TimeSpan.Zero)
 126                    {
 0127                        _waitTime = TimeSpan.Zero;
 128                    }
 129                }
 130            }
 0131        }
 132    }
 133}