public AutoCompleteResourceV3(HttpSource client, ServiceIndexResourceV3 serviceIndex, RegistrationResourceV3 regResource) : base() { _regResource = regResource; _serviceIndex = serviceIndex; _client = client; }
public override async Task <Tuple <bool, INuGetResource> > TryCreate(SourceRepository source, CancellationToken token) { ServiceIndexResourceV3 index = null; ServiceIndexCacheInfo cacheInfo = null; var url = source.PackageSource.Source; // the file type can easily rule out if we need to request the url if (source.PackageSource.ProtocolVersion == 3 || (source.PackageSource.IsHttp && url.EndsWith(".json", StringComparison.OrdinalIgnoreCase))) { var utcNow = DateTime.UtcNow; var entryValidCutoff = utcNow.Subtract(MaxCacheDuration); // check the cache before downloading the file if (!_cache.TryGetValue(url, out cacheInfo) || entryValidCutoff > cacheInfo.CachedTime) { // Track if the semaphore needs to be released var release = false; try { await _semaphore.WaitAsync(token); release = true; token.ThrowIfCancellationRequested(); // check the cache again, another thread may have finished this one waited for the lock if (!_cache.TryGetValue(url, out cacheInfo) || entryValidCutoff > cacheInfo.CachedTime) { index = await GetServiceIndexResourceV3(source, utcNow, NullLogger.Instance, token); // cache the value even if it is null to avoid checking it again later var cacheEntry = new ServiceIndexCacheInfo { CachedTime = utcNow, Index = index }; // If the cache entry has expired it will already exist _cache.AddOrUpdate(url, cacheEntry, (key, value) => cacheEntry); } } finally { if (release) { _semaphore.Release(); } } } } if (index == null && cacheInfo != null) { index = cacheInfo.Index; } return(new Tuple <bool, INuGetResource>(index != null, index)); }