Esempio n. 1
0
        /// <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);
        }