示例#1
0
        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;
            }
        }
示例#2
0
        /// <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);
            }
        }
示例#3
0
        /// <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);
        }
示例#4
0
 public CallbackController(IMyLogger logger, ICacheControl cacheControl, IOptions <WeChatSettings> weChatSettings, IWeChatAPI weChatAPI)
 {
     _logger         = logger;
     _cacheControl   = cacheControl;
     _weChatSettings = weChatSettings;
     _weChatAPI      = weChatAPI;
 }
示例#5
0
        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);
            }
        }
示例#6
0
 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);
     }
 }
示例#8
0
 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);
     }
 }
示例#9
0
        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();
        }
示例#10
0
 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);
 }
示例#11
0
 public ScheduledReloadCacheControl(ICacheControl <TReload, TReloaded> cacheControl,
                                    ITaskScheduler scheduler,
                                    Func <TReload> reloadEventFactory, int cacheTimeoutInMinutes)
 {
     _reloadEventFactory = reloadEventFactory;
     _scheduler          = scheduler;
     _cacheControl       = cacheControl;
     _cacheTimeout       = TimeSpan.FromMinutes(cacheTimeoutInMinutes);
     ScheduleNextUpdate();
 }
示例#12
0
        /// <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();
 }
示例#15
0
        /// <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;
                }
            }
        }
示例#16
0
        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("");
        }
示例#17
0
        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);
            }
        }
示例#18
0
        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));
        }
示例#19
0
 /// <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);
     }));
 }
示例#20
0
        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;
        }
示例#21
0
        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);
                    }
                }
            }
        }
示例#22
0
        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);
            }
        }
示例#23
0
 internal static IDictionary <string, string> GetTableRow(ICacheControl icc, int row, string[] columnNames)
 {
     return(GetTableRow(icc, row, columnNames, null, null));
 }
示例#24
0
 public TestController(IMyLogger logger, IWeChatAPI weChatAPI, ICacheControl cacheControl)
 {
     _logger       = logger;
     _weChatAPI    = weChatAPI;
     _cacheControl = cacheControl;
 }
示例#25
0
 public Task GetAsync(string key, Stream sink, ICacheControl cacheControl, CancellationToken ct)
 {
     return(_func(key, sink, cacheControl, ct));
 }
示例#26
0
        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));
        }
示例#27
0
 public Task GetAsync(string group, string key, Stream sink, ICacheControl cacheControl, CancellationToken ct)
 {
     return(Task.FromException <Stream>(new InvalidOperationException("test")));
 }