< Summary - NetSimpleLazyCache Coverage Report

Information
Class: SingleFactoryCaller<T>
Assembly: SimpleLazyCache
File(s): /home/runner/work/NetSimpleLazyCache/NetSimpleLazyCache/src/SimpleLazyCache/SingleFactoryCaller.cs
Line coverage
100%
Covered lines: 21
Uncovered lines: 0
Coverable lines: 21
Total lines: 51
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
GetOrAddAsync()100%1010100%
Invoke()100%22100%

File(s)

/home/runner/work/NetSimpleLazyCache/NetSimpleLazyCache/src/SimpleLazyCache/SingleFactoryCaller.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Threading;
 4using System.Threading.Tasks;
 5
 6public sealed class SingleFactoryCaller<T> where T : class
 7{
 298    private readonly Dictionary<string, Lazy<Task<T>>> _pending =
 299        new Dictionary<string, Lazy<Task<T>>>();
 10
 2911    private readonly object _gate = new object();
 12
 13    // cancellationToken is not applied: one waiter must not cancel the shared factory.
 14    public async Task<T> GetOrAddAsync(string key, Func<Task<T>> valueFactory, CancellationToken cancellationToken = def
 15    {
 17816        if (string.IsNullOrEmpty(key))
 417            throw new ArgumentException("Key cannot be null or empty.", nameof(key));
 17418        if (valueFactory == null)
 219            throw new ArgumentNullException(nameof(valueFactory));
 20
 21        Lazy<Task<T>> lazy;
 17222        lock (_gate)
 23        {
 17224            if (!_pending.TryGetValue(key, out lazy))
 25            {
 11826                lazy = new Lazy<Task<T>>(() => Invoke(valueFactory), LazyThreadSafetyMode.ExecutionAndPublication);
 5927                _pending.Add(key, lazy);
 28            }
 17229        }
 30
 31        try
 32        {
 17233            return await lazy.Value.ConfigureAwait(false);
 34        }
 35        finally
 36        {
 17237            lock (_gate)
 38            {
 39                // A finishing caller must leave a newer entry alone.
 17240                if (_pending.TryGetValue(key, out var current) && ReferenceEquals(current, lazy))
 5941                    _pending.Remove(key);
 17242            }
 43        }
 13044    }
 45
 46    private static async Task<T> Invoke(Func<Task<T>> valueFactory)
 47    {
 5948        var task = valueFactory() ?? throw new InvalidOperationException("Value factory returned null task.");
 5649        return await task.ConfigureAwait(false);
 4950    }
 51}

Methods/Properties

.ctor()
GetOrAddAsync()
Invoke()