/// <summary> /// Gets a valid <see cref="Response"/> or requests and caches a <see cref="CachedResponse"/>. /// </summary> /// <param name="isAsync">Whether certain operations should be performed asynchronously.</param> /// <param name="uri">The URI sans query parameters to cache.</param> /// <param name="action">The action to request a response.</param> /// <returns>A new <see cref="Response"/>.</returns> internal async ValueTask <Response> GetOrAddAsync(bool isAsync, string uri, TimeSpan ttl, Func <ValueTask <Response> > action) { if (isAsync) { await _lock.WaitAsync().ConfigureAwait(false); } else { _lock.Wait(); } try { // Try to get a valid cached response inside the lock before fetching. if (_cache.TryGetValue(uri, out CachedResponse cachedResponse) && cachedResponse.IsValid) { return(await cachedResponse.CloneAsync(isAsync).ConfigureAwait(false)); } Response response = await action().ConfigureAwait(false); if (response.Status == 200 && response.ContentStream is { }) { cachedResponse = await CachedResponse.CreateAsync(isAsync, response, ttl).ConfigureAwait(false); _cache[uri] = cachedResponse; } return(response); }
private static async ValueTask <CachedResponse> CloneAsync(bool isAsync, Response response) { CachedResponse cachedResponse = new CachedResponse(response.Status, response.ReasonPhrase, response.Headers) { ClientRequestId = response.ClientRequestId, }; if (response.ContentStream is { })
internal static async ValueTask <CachedResponse> CreateAsync(bool isAsync, Response response, TimeSpan ttl) { CachedResponse cachedResponse = await CloneAsync(isAsync, response).ConfigureAwait(false); cachedResponse._expires = DateTimeOffset.Now + ttl; return(cachedResponse); }