private async Task LoadFromPeerAsync(string key, Stream sink, ICacheControl cacheControl, IGroupCacheClient peerClient, CancellationToken ct) { try { Stats.TracePeerLoads(_groupName); using (var validatingSink = CacheEntryValidator.ValidateEntryPassThrough(key, sink)) { await peerClient.GetAsync(_groupName, key, validatingSink, cacheControl, ct).ConfigureAwait(false); await validatingSink.ValidateAsync(ct).ConfigureAwait(false); } } catch (CircuitBreakerOpenException) { throw; // Dont log CircuitBreakerOpenException } catch (InternalServerErrorException internalErrorEx) { Logger.Error(String.Format("Call to LoadFromPeer to {0} for Cache {1} key: {2} failed on InternalServerErrorException {3}", peerClient.Endpoint.ToString(), _groupName, key, internalErrorEx.Message)); throw; } catch (Exception ex) { Logger.Error(ex, String.Format("Call to LoadFromPeer to {0} for Cache {1} key: {2} failed ", peerClient.Endpoint.ToString(), _groupName, key)); throw; } }
/// <summary> /// Handle request from Peers and forward to the correct local Group instance /// </summary> public async Task GetAsync(string groupName, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { SemaphoreHolder limiter; try { limiter = await _concurrencyLimiter.AcquireAsync(TimeSpan.Zero).ConfigureAwait(false); } catch (TimeoutException) { throw new ServerBusyException("Too many concurrent connection"); } using (limiter) { var groupKey = new GroupKey { GroupName = groupName, Endpoint = this.Endpoint }; var found = GroupCache.GroupCache.GetGroup(groupKey, out Group group); if (!found) { throw new GroupNotFoundException($"no such group: {groupName}"); } group.Stats.TraceConcurrentServerRequests(_concurrencyLimit - _concurrencyLimiter.CurrentCount); group.Stats.TraceServerRequests(groupName); // We received a request from a peer, we need to download it locally and not forward to peer // because forwarding to peer would cause infinite loop if using different peer list await group.GetAsyncLocallyAsync(key, sink, cacheControl, ct); } }
/// <summary> /// Get the row if it is an execution. /// </summary> /// <param name="icc"></param> /// <param name="row"></param> /// <param name="filterColumnName"></param> /// <param name="columnNames"></param> /// <param name="filterValue"></param> /// <returns></returns> internal static IDictionary <string, string> GetTableRow(ICacheControl icc, int row, string[] columnNames, string filterColumnName, string filterValue) { log.Debug("Retrieving row:" + row); var rowValues = new Dictionary <string, string>(); RediError error; // = RediError.None; if (filterColumnName != null) { var rowType = GetTableRowColumn(icc, row, filterColumnName, out error); if (filterValue.ToUpperInvariant().Equals(rowType.ToUpperInvariant())) { rowValues[filterColumnName] = rowType; } else { return(rowValues); } } foreach (var columnName in columnNames) { rowValues[columnName.ToUpperInvariant()] = GetTableRowColumn(icc, row, columnName, out error); } return(rowValues); }
public CallbackController(IMyLogger logger, ICacheControl cacheControl, IOptions <WeChatSettings> weChatSettings, IWeChatAPI weChatAPI) { _logger = logger; _cacheControl = cacheControl; _weChatSettings = weChatSettings; _weChatAPI = weChatAPI; }
private async Task LoadLocallyAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { async Task func(string cachekey, Stream factorySink, ICacheControl factoryCacheControl) { try { Stats.TraceLocalLoads(_groupName); await _getter.GetAsync(cachekey, factorySink, factoryCacheControl, ct).ConfigureAwait(false); } catch (Exception ex) { Logger.Error(ex, String.Format("Call to LoadLocally for Cache {0} key: {1} failed ", _groupName, key)); throw; } } Stats.TraceCacheHits(_groupName); var cacheEntry = await _localCache.GetOrAddAsync(key, func, cacheControl, ct).ConfigureAwait(false); try { Stream cacheEntryStream = cacheEntry.Value(); await cacheEntryStream.CopyToAsync(sink).ConfigureAwait(false); } finally { await cacheEntry.DisposeAsync().ConfigureAwait(false); } }
internal ApiResponse(string eTag, IEnumerable <string> response, DateTime expired, ICacheControl cacheControl) { ETag = eTag; Expired = expired; CacheControl = cacheControl; FirstPage = response.FirstOrDefault(); this.response = response; }
public async Task GetAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { Interlocked.Increment(ref callCount); using (var stream = key.StringToStream()) { await stream.CopyToAsync(sink); } }
public async Task GetAsync(string group, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { cacheControl.NoStore = true; using (var resultStream = "HelloWorld".StringToStream()) { await resultStream.CopyToAsync(sink); } }
internal ApiResponse(string eTag, IEnumerable <string> response, DateTime expired, ICacheControl cacheControl) { ETag = eTag; Expired = expired; CacheControl = cacheControl; this.response = response.Select(x => JsonSerializer.Deserialize <T>(x)); FirstPage = this.response.FirstOrDefault(); }
public FolderTable(Alias alias, bool enableChecksums, bool flatten = false) { Alias = alias; EnableChecksums = enableChecksums; Flattened = flatten; Data = new DataTable(Alias.Name); Data.Columns.AddRange(GetStructure()); Cache = new CacheControl(this); }
public ScheduledReloadCacheControl(ICacheControl <TReload, TReloaded> cacheControl, ITaskScheduler scheduler, Func <TReload> reloadEventFactory, int cacheTimeoutInMinutes) { _reloadEventFactory = reloadEventFactory; _scheduler = scheduler; _cacheControl = cacheControl; _cacheTimeout = TimeSpan.FromMinutes(cacheTimeoutInMinutes); ScheduleNextUpdate(); }
/// <summary> /// Read the data from Peer or local machine and dedup in flight call /// </summary> public async Task GetAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { if (cacheControl == null) { cacheControl = new CacheControl(); } Stats.TraceGets(_groupName); var watch = Stopwatch.StartNew(); await LoadFromGetterOrPeerAsync(key, sink, cacheControl, ct).ConfigureAwait(false); Stats.TraceRoundtripLatency(_groupName, watch.Elapsed); }
public async Task GetAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { Interlocked.Increment(ref callCount); try { long number = long.Parse(key); long result; if (number == 0) { result = 0; } else if (number == 1) { result = 1; } else { // Make to call to n-1 and n-2 in parallel using (var firstStream = new MemoryStream()) using (var secondStream = new MemoryStream()) { await getter.GetAsync((number - 1).ToString(), firstStream, new CacheControl(), CancellationToken.None).ConfigureAwait(false); await getter.GetAsync((number - 2).ToString(), secondStream, new CacheControl(), CancellationToken.None).ConfigureAwait(false); var firstStr = firstStream.StreamToString(); var secondStr = secondStream.StreamToString(); // return the sum var firstLong = long.Parse(firstStr); var secondLong = long.Parse(secondStr); result = firstLong + secondLong; } } var resultStream = result.ToString().StringToStream(); resultStream.Position = 0; await resultStream.CopyToAsync(sink); } catch (Exception ex) { Console.WriteLine(ex.ToString()); throw; } }
public async Task GetAsync(string group, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { try { TripIfNeeded(); await _client.GetAsync(group, key, sink, cacheControl, ct).ConfigureAwait(false); } catch (ServerBusyException) { // Dont count busy server as bad throw; } catch { CountFailure(); throw; } ResetCount(); }
/// <summary> /// Read the data from localMachine or from IGetter and dedup in flight call /// </summary> public async Task GetAsyncLocallyAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { Stats.TraceGets(_groupName); // Dipose validatingSink but leave sink open, to release validatingSink ressources using (var validatingSink = CacheEntryValidator.ValidateEntryPassThrough(key, sink)) { try { await LoadLocallyAsync(key, validatingSink, cacheControl, ct).ConfigureAwait(false); await validatingSink.ValidateAsync(ct).ConfigureAwait(false); } catch (CacheEntryValidationFailedException) { await RemoveAsync(key, ct).ConfigureAwait(false); throw; } } }
static string GetTableRowColumn(ICacheControl icc, int row, string columnName, out RediError errorCode) { try { object myValue = null; object myError = null; icc.GetCell(row, columnName, ref myValue, ref myError); errorCode = RediErrorFor(Convert.ToInt32(myError)); if (RediError.None != errorCode) { log.Error( "Received error: " + errorCode + ", when retrieving row (" + row + "), column '" + columnName + "'"); } return(myValue != null?myValue.ToString() : ""); } catch (Exception e) { errorCode = RediError.Exception; log.Error(e); } return(""); }
private async Task LoadFromGetterOrPeerAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { Stats.TraceLoadsDeduped(_groupName); var replicasForKey = _peers.PickPeers(key, _peers.Count); var retryCount = Math.Min(MaxRetry, replicasForKey.Count); var retryableException = new Type[] { typeof(InternalServerErrorException), typeof(ServerBusyException), typeof(GroupNotFoundException), typeof(ConnectFailureException) }; var retry = new Retry(new SimpleRetryPolicy(retryCount, TimeSpan.Zero, retryableException)); try { await retry.ExecuteAsync(async (RetryContext ctx) => { if (ctx.RetryCount > 0) { Stats.TraceRetry(_groupName); } var peerClient = replicasForKey[ctx.RetryCount]; if (peerClient.IsLocal) // we need to read from peer { Logger.Debug(String.Format("Call to LoadLocally for Cache {0} key: {1} retryCount: {2}", _groupName, key, ctx.RetryCount)); await LoadLocallyAsync(key, sink, cacheControl, ct).ConfigureAwait(false); } else { Logger.Debug(String.Format("Call to LoadFromPeer for Cache {0} key: {1} retryCount: {2}", _groupName, key, ctx.RetryCount)); await LoadFromPeerAsync(key, sink, cacheControl, peerClient, ct).ConfigureAwait(false); } } ).ConfigureAwait(false); } catch { Logger.Info($"{_groupName}:{key} failed to download from peer. trying to download locally from source directly."); await LoadLocallyAsync(key, sink, cacheControl, ct).ConfigureAwait(false); } }
async Task <IApiResponse> GetAllPages(IApiRequest request) { // Get response from api and check rate limit var httpResponse = await GetHttpRequest(request); await CheckRateLimit(httpResponse); // Get page info from header and save response as first page int pages = GetPages(httpResponse); string[] responseArr = new string[pages]; responseArr[0] = await httpResponse.Content.ReadAsStringAsync(); // Get headers to use later string eTag = TryGetHeaderValue(httpResponse.Headers, "etag"); string expireString = TryGetHeaderValue(httpResponse.Content.Headers, "Expires"); string nowString = TryGetHeaderValue(httpResponse.Headers, "Date"); string cacheControlString = TryGetHeaderValue(httpResponse.Content.Headers, "cache-control"); ICacheControl cacheControl = cacheControlFactory.Create(cacheControlString); // Return an error if the request failed DateTime expired = ParseDateTime(expireString, nowString); if (!httpResponse.IsSuccessStatusCode) { return(new ApiError(eTag, responseArr, expired, cacheControl, httpResponse.StatusCode)); } for (int i = 1; i < pages; i++) { responseArr[i] = await GetPage(request, i); } return(new ApiResponse(eTag, responseArr, expired, cacheControl)); }
/// <summary>valueFactory /// Get item from cache of call valueFactory if missing /// </summary> /// <param name="key">The key of the value that need to be filled in</param> /// <param name="valueFactory">valueFactory should write result to the stream but not close it</param> /// <param name="ct">Cancellation token</param> /// <returns></returns> public Task <ICacheEntry> GetOrAddAsync(string key, Func <string, Stream, ICacheControl, Task> valueFactory, ICacheControl cacheControl, CancellationToken ct) { return(createEntry.DoAsync(key, async() => { ICacheEntry found = await GetAsync(key, ct).ConfigureAwait(false); if (!(found is EmptyCacheEntry)) { return found; } ArraySegment <byte> buffer; using (var memStream = new MemoryStream()) { await valueFactory(key, memStream, cacheControl).ConfigureAwait(false); memStream.Position = 0; buffer = new ArraySegment <byte>(memStream.ToArray()); } if (!cacheControl.NoStore) { _cache.Add(key, buffer, (ulong)buffer.Count); } return new MemoryCacheEntry(buffer); })); }
internal ApiError(string eTag, IEnumerable <string> response, DateTime expired, ICacheControl cacheControl, HttpStatusCode statusCode) : base(eTag, response, expired, cacheControl) { if (response.First().Length > 0 && response.First()[0] == '{') { JsonElement jObj = JsonSerializer.Deserialize <JsonElement>(base.FirstPage); if (jObj.TryGetProperty("error", out JsonElement err)) { Error = err.GetString(); } } else { Error = response.First(); } StatusCode = statusCode; }
public async Task GetAsync(string group, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair <string, string>(OwinServer.GROUPNAME, group), new KeyValuePair <string, string>(OwinServer.KEY, key) }); HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, "Get") { Content = formContent, Version = HttpVersion.Version10 }; // GetAsync block until the response’s (headers + content) is fully downloaded/read to the memory // Unless we use HttpCompletionOption.ResponseHeadersRead HttpResponseMessage response; try { response = await _client.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); } catch (HttpRequestException ex) { throw new ConnectFailureException($"fail to send request to {Endpoint.ToString()}", ex); } using (response) { if (!response.IsSuccessStatusCode) { if (response.StatusCode == HttpStatusCode.InternalServerError) { throw new InternalServerErrorException(response.ReasonPhrase); } if (response.StatusCode == HttpStatusCode.ServiceUnavailable) { throw new ServerBusyException(response.ReasonPhrase); } if (response.StatusCode == HttpStatusCode.NotFound) { throw new GroupNotFoundException(response.ReasonPhrase); } response.EnsureSuccessStatusCode(); } // if we reach her we can safely read response.Content if (response.Content == null) { throw new InternalServerErrorException("response body is null"); } if (response.Headers.CacheControl != null && response.Headers.CacheControl.NoStore) { cacheControl.NoStore = true; } // using ct.Register to force CopyToAsync to return early and throw OperationCanceledException using (ct.Register(response.Dispose)) { try { await response.Content.CopyToAsync(sink).ConfigureAwait(false); } catch (ObjectDisposedException e) when(ct.IsCancellationRequested) { throw new OperationCanceledException(null, e, ct); } } } }
public async Task <ICacheEntry> GetOrAddAsync(string key, Func <string, Stream, ICacheControl, Task> valueFactory, ICacheControl cacheControl, CancellationToken ct) { using (await _rwLock.ReadLockAsync()) { ICacheEntry found = GetInternal(key); if (!(found is EmptyCacheEntry)) { found.Ref(); // this entry remain valid after releasing the lock return(found); } } using (await _rwLock.WriteLockAsync()) { ICacheEntry found = GetInternal(key); if (!(found is EmptyCacheEntry)) { found.Ref(); // this entry remain valid after releasing the lock return(found); } var randomPath = await _fs.WriteAtomicAsync((sink, cancel) => valueFactory(key, sink, cacheControl), _cacheTmpPath, ct).ConfigureAwait(false); var tmpEntry = new DiskCacheEntry(key, randomPath, this); if (!cacheControl.NoStore) { SetInternal(key, tmpEntry); } var entry = GetInternal(key); entry.Ref(); return(entry); } }
internal static IDictionary <string, string> GetTableRow(ICacheControl icc, int row, string[] columnNames) { return(GetTableRow(icc, row, columnNames, null, null)); }
public TestController(IMyLogger logger, IWeChatAPI weChatAPI, ICacheControl cacheControl) { _logger = logger; _weChatAPI = weChatAPI; _cacheControl = cacheControl; }
public Task GetAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { return(_func(key, sink, cacheControl, ct)); }
public Task <ICacheEntry> GetOrAddAsync(string key, Func <string, Stream, ICacheControl, Task> valueFactory, ICacheControl cacheControl, CancellationToken ct) { var newkey = _prefix + key; return(_decorated.GetOrAddAsync(newkey, (str, stream, cc) => valueFactory(key, stream, cc), cacheControl, ct)); }
public Task GetAsync(string group, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct) { return(Task.FromException <Stream>(new InvalidOperationException("test"))); }