private IEnumerable <ItemOrderStats> RetrieveItems(IEnumerable <int> typesToRequest, int regionId, string cacheKey) { var resultItems = new List <ItemOrderStats>(); if (!_isServiceAvailable) { return(resultItems); } var requestUri = new Uri($"https://market.fuzzwork.co.uk/aggregates/?region={regionId}&types={string.Join(",", typesToRequest)}"); var requestTask = _requestProvider.GetAsync(requestUri); requestTask.Wait(); // wait for the completion (we're in a background task anyways) if (!requestTask.Result.IsSuccessStatusCode || WebServiceExceptionHelper.IsServiceUnavailableError(requestTask.Exception)) { _isServiceAvailable = false; // TODO: postpone next check. return(resultItems); } if (!requestTask.IsTaskSuccessfullyCompleted()) { return(resultItems); } var contentStreamTask = requestTask.Result.Content.ReadAsStreamAsync(); contentStreamTask.Wait(); using (var reader = new StreamReader(contentStreamTask.Result)) { try { // process result var retrievedItems = ParseResult(reader.ReadToEnd()); // cache it. foreach (var item in retrievedItems) { _regionDataCache.Add( ItemKeyFormat.FormatInvariant(item.ItemTypeId, cacheKey), item, DateTimeOffset.Now.Add(_cacheTtl)); resultItems.Add(item); } } catch (Exception ex) { Trace.TraceError(ex.FormatException()); throw; } } return(resultItems); }
private Task <IEnumerable <ItemOrderStats> > GetOrderStats(int[] typeIds, int regionId) { return(Task <IEnumerable <ItemOrderStats> > .Factory.TryRun( () => { var cacheKey = regionId.ToInvariantString(); // Get all cached items for the selected region. var cachedItemStats = typeIds .Select(typeId => _regionDataCache.Get <ItemOrderStats>(ItemKeyFormat.FormatInvariant(typeId, cacheKey))).ToList(); // Add to the result set not expired items for quered types from cache. var result = cachedItemStats.Where(item => item?.Data != null && !item.IsDirty).Select(item => item.Data).ToList(); // Get only type IDs that not in the cache. var typesToRequest = typeIds.Except(result.Select(stats => stats.ItemTypeId)).ToArray(); if (!typesToRequest.Any()) { return result; } result.AddRange(RetrieveItems(typesToRequest, regionId, cacheKey)); // Dirty cached items is better than nothing in the end. Add them to dirty cache in case of no data/error. var fromDirtyCache = cachedItemStats .Where( item => item?.Data != null && item.IsDirty && result.Any(resultItem => item.Data.ItemTypeId == resultItem.ItemTypeId)) .Select(item => item.Data); result.AddRange(fromDirtyCache); return result; })); }