public virtual async Task <T?> LoadAsync <T>(string key) where T : class { CheckKeyValid(key); var filePath = GetFilePathForKey(key); if (!File.Exists(filePath)) { throw new Exception($"Load called on Yaml file that doesnt exist: {filePath}"); } RegisterKnownKey(key); // see SaveAsync for why this is commented //using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 4096, useAsync: true); //var encodedData = new byte[stream.Length]; //await stream.ReadAsync(encodedData, 0, (int)stream.Length); // Retry fixes stupid IOException ("File being used by another process") // when reading from a FileSystemWatcher's event. // // Similar: https://stackoverflow.com/q/49551278 var encodedData = await Retry.DoAsync(() => File.ReadAllBytes((filePath)), TimeSpan.FromMilliseconds(1), 5); using var sha = new SHA256Managed(); var contentHash = BitConverter.ToString(sha.ComputeHash(encodedData)); m_ContentHash[key] = contentHash; var serializedYaml = Encoding.UTF8.GetString(encodedData); return(m_Deserializer.Deserialize <T>(serializedYaml)); }
public override async Task <IExecutionResult <bool> > HandleAsync(CartCheckoutCommand command, CancellationToken cancellationToken) { if (!command.IsValid()) { return(ValidationErrors(command)); } var cart = await _cartRepository.GetById(command.Id.ToString()); if (cart == null) { return(ExecutionError(command, ErrorMessages.Cart.DoesNotExistsById)); } var items = cart.Items.Select(x => new CartItem(x.Id) { Price = x.Price, Scale = x.Scale, CurrencyCode = x.CurrencyCode, Product = _productRepository.GetById(x.Id.ToString()).Result }).ToList(); cart.Items = items; var invoice = new Invoice(command.XTeamControl, command.CurrencyCode); var invoiceAggregate = new InvoiceAggregate(invoice, cart); await Retry.DoAsync(async() => await _queueService.SendToSqsAsync(invoiceAggregate)); var result = await _cartRepository.Checkout(command.Id.ToString()); return(new SuccessExecutionResult <bool>(GetType(), result)); }
public void RetryAsync_CancellationToken_ShouldCancelUsingAsynchronousAction() { var retriesPerformed = 0; const int expectedRetries = 2; const int maxRetries = 5; var cancellationToken = new CancellationTokenSource(); // fail on all retries, but cancel on the second failure Assert.ThrowsAsync <RetryTimeoutException>(async() => { await Retry.DoAsync(async() => { await Task.Delay(10); retriesPerformed++; throw new RetryTestException(); }, TimeSpan.FromMilliseconds(10), maxRetries, cancellationToken.Token, async(ex, iteration, max) => { // await something await Task.Delay(1); if (iteration == expectedRetries - 1) { // cancel cancellationToken.Cancel(); } }); }); // ensure we only retried twice and not the full maxRetries Assert.AreEqual(expectedRetries, retriesPerformed); }
public void RetryAsync_Static_ShouldRetryUntilEvaluatesToTrue() { // fail on all retries // this will ignore the maxRetries limit, if the evaluation parameters return false var timeBetweenRetries = TimeSpan.FromMilliseconds(150); const int maxRetries = 1; var i = 0; Assert.ThrowsAsync <RetryTimeoutException>(async() => { await Retry.DoAsync(async(iteration, max) => { await Task.Delay(10); i++; throw new RetryTestException(); }, timeBetweenRetries, maxRetries, RetryPolicy.StaticDelay, RetryPolicyOptions.None, // don't need cancellation token null, // don't need an error handler null, // retry forever unless this evaluates to true (advanced usage) () => { return(i != 10); } ); }); Assert.AreEqual(10, i); }
public async Task Retry_Ok_Async() { object o1 = new object(); async Task <object> act() => await Retry.DoAsync(async() => { return(await Task.FromResult(o1)); }); Assert.Same(await act(), o1); }
public Task <T> ExecuteAsync <T>(IAsyncCommand <T> command, CancellationToken cancellationToken = default) { if (command.RequiresTransaction && _transaction == null) { throw new Exception($"The command {command.GetType()} requires a transaction"); } return(Retry.DoAsync(() => command.ExecuteAsync(_connection, _transaction, cancellationToken), _retryOptions)); }
public async Task RetrySucceedsOnSubsequentTryAsync() { _retries = 0; var completedDelegate = await Retry.DoAsync( async() => await SuccessOnSubsequentTry(1) , TimeSpan.FromSeconds(1)); Debug.WriteLine(_retries.ToString()); _retries.Should().BeGreaterThan(1); }
public async Task RetrySucceedsOnSubsequentTryAsync() { _retries = 0; var completedDelegate = await Retry.DoAsync( async() => await SuccessOnSubsequentTry(1) , TimeSpan.FromSeconds(1)); Debug.WriteLine(_retries.ToString()); Assert.IsTrue(_retries > 1); }
public async Task RetrySucceedsOnFirstTryAsync() { _retries = 0; var completedDelegate = await Retry.DoAsync( async() => await SucceedAlways(1) , TimeSpan.FromSeconds(1)); Debug.WriteLine(_retries.ToString()); _retries.Should().Be(1); }
public virtual async Task <CacheStream> DownloadAndCacheIfNeededAsync(string url, TaskParameter parameters, Configuration configuration, CancellationToken token) { var allowCustomKey = !string.IsNullOrWhiteSpace(parameters.CustomCacheKey) && (string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) || parameters.LoadingPlaceholderPath != url) && (string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) || parameters.ErrorPlaceholderPath != url); string filename = (allowCustomKey ? MD5Helper.MD5(parameters.CustomCacheKey) : MD5Helper.MD5(url))?.ToSanitizedKey(); var allowDiskCaching = AllowDiskCaching(parameters.CacheType); var duration = parameters.CacheDuration.HasValue ? parameters.CacheDuration.Value : configuration.DiskCacheDuration; string filePath = null; if (allowDiskCaching) { var diskStream = await configuration.DiskCache.TryGetStreamAsync(filename).ConfigureAwait(false); if (diskStream != null) { token.ThrowIfCancellationRequested(); filePath = await configuration.DiskCache.GetFilePathAsync(filename).ConfigureAwait(false); return(new CacheStream(diskStream, true, filePath)); } } token.ThrowIfCancellationRequested(); var downloadInfo = new DownloadInformation(url, parameters.CustomCacheKey, filename, allowDiskCaching, duration); parameters.OnDownloadStarted?.Invoke(downloadInfo); var responseBytes = await Retry.DoAsync( async() => await DownloadAsync(url, token, configuration.HttpClient).ConfigureAwait(false), DelayBetweenRetry, parameters.RetryCount, () => configuration.Logger.Debug(string.Format("Retry download: {0}", url))); if (responseBytes == null) { throw new HttpRequestException("No Content"); } if (allowDiskCaching) { await configuration.DiskCache.AddToSavingQueueIfNotExistsAsync(filename, responseBytes, duration).ConfigureAwait(false); } token.ThrowIfCancellationRequested(); filePath = await configuration.DiskCache.GetFilePathAsync(filename).ConfigureAwait(false); token.ThrowIfCancellationRequested(); var memoryStream = new MemoryStream(responseBytes, false); return(new CacheStream(memoryStream, false, filePath)); }
public async Task RetryFail() { _retries = 0; bool completedDelegate = await Retry.DoAsync( async() => await FailAlways() , TimeSpan.FromSeconds(1) , 3); Debug.WriteLine(_retries.ToString()); Assert.IsTrue(_retries == 3); }
public async Task MakeAllFollowingsFollowersFollowRequestAsync(int top = 1000, IFilter <UserInfo> filter = null) { List <UserInfo> currentUserFollowingList = await instaService.GetCurrentUserFollowings(); List <UserInfo> requestList = new List <UserInfo>(); RandomGenerator random = new RandomGenerator(currentUserFollowingList.Count); for (int i = 0; i < currentUserFollowingList.Count; i++) { int index = random.Different(); var following = currentUserFollowingList[index]; logger.Write($"Random UserName : {following.UserName}, Index Order {i}"); List <UserInfo> userInfoList = await instaService.GetUserFollowers(following.UserName, 10); filter = filter ?? FollowerFilter.DefaultFilter(); var filtered = filter.Apply(userInfoList); filtered.RemoveAll(u => currentUserFollowingList.Exists(c => c.Id == u.Id)); if (filtered != null && filtered.Count > 0) { requestList.AddRange(filtered); } if (requestList.Count >= top) { requestList = requestList.Take(top).ToList(); break; } } int requestIndex = 0; try { for (requestIndex = 0; requestIndex < requestList.Count; requestIndex++) { logger.Write($"Requested UserName : {requestList[requestIndex].UserName}, Remaining User {requestList.Count - requestIndex - 1}"); await Retry.DoAsync(() => instaService.FollowUserAsync(requestList[requestIndex].Id), TimeSpan.FromSeconds(3)); } } catch (Exception ex) { logger.Write(ex.ToString()); } finally { if (requestIndex > 0) { FileUtils.WriteAllToRequestedFile(requestList.Take(requestIndex).ToList()); } } }
public async Task RetryFail() { _retries = 0; Func <Task <bool> > act = async() => await Retry.DoAsync( async() => await FailAlways() , TimeSpan.FromSeconds(1)); await Assert.ThrowsAsync <AggregateException>(act); Debug.WriteLine(_retries.ToString()); _retries.Should().Be(3); }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ctsToken) { using (await Util.AsyncLock.LockAsync().ConfigureAwait(false)) { SocksConnection connection = null; try { await Retry.DoAsync(() => { connection = ConnectToDestinationIfNotConnected(request.RequestUri); }, RetryInterval, MaxRetry).ConfigureAwait(false); } catch (Exception ex) { throw new TorException("Failed to connect to the destination", ex); } ctsToken.ThrowIfCancellationRequested(); // https://tools.ietf.org/html/rfc7230#section-2.7.1 // A sender MUST NOT generate an "http" URI with an empty host identifier. if (request.RequestUri.DnsSafeHost == "") { throw new HttpRequestException("Host identifier is empty"); } // https://tools.ietf.org/html/rfc7230#section-2.6 // Intermediaries that process HTTP messages (i.e., all intermediaries // other than those acting as tunnels) MUST send their own HTTP - version // in forwarded messages. request.Version = Protocol.Version; try { return(await connection.SendRequestAsync(request, ctsToken).ConfigureAwait(false)); } catch (Exception ex) { if (ex is OperationCanceledException) { throw; } else { throw new TorException("Failed to send the request", ex); } } } }
public void RetryAsync_Static_ShouldRetryIntervalElapsed() { // fail on all retries var startTime = DateTime.Now; var timeBetweenRetries = TimeSpan.FromMilliseconds(150); Assert.ThrowsAsync <RetryTimeoutException>(async() => { await Retry.DoAsync(async() => { await Task.Delay(10); throw new RetryTestException(); }, timeBetweenRetries, 1, RetryPolicy.StaticDelay); }); Assert.Greater(DateTime.Now.Subtract(startTime), timeBetweenRetries); }
private async Task <ImageAnalysisResult> GetImageAnalysisAsync(byte[] bytes) { ImageAnalysisResult result = null; try { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", CoreConstants.ComputerVisionApiSubscriptionKey); var payload = new ByteArrayContent(bytes); payload.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); var analysisFeatures = "Color,ImageType,Tags,Categories,Description,Adult,Faces"; var uri = new Uri($"{CoreConstants.CognitiveServicesBaseUrl}/vision/v1.0/analyze?visualFeatures={analysisFeatures}"); using (var results = await Retry.DoAsync(() => client.PostAsync(uri, payload), new TimeSpan(0, 0, 3), 10)) { var analysisResults = await results.Content.ReadAsStringAsync(); var imageAnalysisResult = JsonConvert.DeserializeObject <ImageAnalysisInfo>(analysisResults); result = new ImageAnalysisResult { id = Guid.NewGuid().ToString(), details = imageAnalysisResult, caption = imageAnalysisResult.description.captions.FirstOrDefault()?.text, tags = imageAnalysisResult.description.tags.ToList() }; if (string.IsNullOrEmpty(result.caption)) { result.caption = "No caption"; } } } } catch (Exception ex) { Console.WriteLine($"ComputerVisionService.GetImageAnalysisAsync Exception: {ex}"); } return(result); }
public void RetryAsync_Static_ShouldRetryUntilMax() { var retriesPerformed = 0; const int maxRetries = 5; // fail on all retries Assert.ThrowsAsync <RetryTimeoutException>(async() => { await Retry.DoAsync(async() => { await Task.Delay(10); retriesPerformed++; throw new RetryTestException(); }, TimeSpan.FromMilliseconds(10), maxRetries); } ); Assert.AreEqual(5, retriesPerformed); }
public virtual async Task <Stream> DownloadAndCacheIfNeededAsync(string url, ILoadableImageSource imageSource, CancellationToken token) { string filename = MD5Helper.MD5(url); bool allowDiskCaching = AllowDiskCaching(_imageLoader.CacheType); IDiskCache?diskCache = _imageLoader.DiskCache; TimeSpan duration = _imageLoader.DiskCacheDuration; if (allowDiskCaching) { Stream?diskStream = await diskCache !.TryGetStreamAsync(filename).ConfigureAwait(false); token.ThrowIfCancellationRequested(); if (diskStream != null) { return(diskStream); } } var downloadInfo = new DownloadInformation(duration); #if LATER parameters.OnDownloadStarted?.Invoke(downloadInfo); #endif byte[] responseBytes = await Retry.DoAsync( async() => await DownloadAsync(url, token, _imageLoader.HttpClient, imageSource, downloadInfo).ConfigureAwait(false), TimeSpan.FromMilliseconds(_imageLoader.RetryDelayInMs), _imageLoader.RetryCount, () => _imageLoader.Logger?.Debug($"Retry download: {url}")).ConfigureAwait(false); if (responseBytes == null) { throw new HttpRequestException("No Content"); } if (allowDiskCaching) { await diskCache !.AddToSavingQueueIfNotExistsAsync(filename, responseBytes, downloadInfo.CacheValidity).ConfigureAwait(false); } token.ThrowIfCancellationRequested(); return(new MemoryStream(responseBytes, false)); }
private async Task ChangeEventHandler(FileSystemEventArgs a) { if (a.ChangeType == WatcherChangeTypes.Renamed || a.ChangeType == WatcherChangeTypes.Deleted) { return; } foreach (var key in m_KnownKeys) { var filePath = GetFilePathForKey(key); if (!a.FullPath.Equals(Path.GetFullPath(filePath), StringComparison.Ordinal)) { continue; } using var sha = new SHA256Managed(); var encodedData = await Retry.DoAsync( () => File.ReadAllBytes(filePath), retryInterval : TimeSpan.FromMilliseconds(1), maxAttempts : 5); var fileHash = BitConverter.ToString(sha.ComputeHash(encodedData)); if (string.Equals(m_ContentHash[key], fileHash, StringComparison.Ordinal)) { // Nothing changed return; } lock (GetLock(key)) { if (DecrementWriteCounter(key)) { m_Logger?.LogDebug($"File changed: {a.FullPath} ({a.ChangeType:X})"); OnFileChange(key); } } return; } }
public void RetryAsync_Static_ShouldRetryOnlyOnSpecifiedExceptions() { var timeBetweenRetries = TimeSpan.FromMilliseconds(150); const int maxRetries = 1; // we are only listening for RetryTestExceptions // if any other type of exception is thrown, it will be rethrown and no retry is performed Assert.ThrowsAsync <InvalidOperationException>(async() => { await Retry.DoAsync(async(iteration, max) => { await Task.Delay(10); throw new InvalidOperationException(); }, timeBetweenRetries, maxRetries, // indicate we only want to catch RetryTestExceptions typeof(RetryTestException) ); }); }
public async Task Retry_Attempts_Zero_Throws_Async() { async Task act() => await Retry.DoAsync(async() => { await Task.Run(() => { }); }, null, 0); await Assert.ThrowsAsync <ArgumentOutOfRangeException>(act); }
public async Task Retry_Interval_Zero_Throws_Async() { async Task act() => await Retry.DoAsync(async() => { await Task.Run(() => { }); }, TimeSpan.FromSeconds(0)); await Assert.ThrowsAsync <ArgumentOutOfRangeException>(act); }
public Task <T> QueryAsync <T>(IAsyncQuery <T> query, CancellationToken cancellationToken = default) => Retry.DoAsync(() => query.ExecuteAsync(_connection, _transaction, cancellationToken), _retryOptions);