public RetryOnFailureAzureTableStorageDecorator(INoSQLTableStorage <TEntity> impl, int onModificationsRetryCount = 10, int onGettingRetryCount = 1, TimeSpan?retryDelay = null) { _impl = impl ?? throw new ArgumentNullException(nameof(impl)); if (onModificationsRetryCount < 1) { throw new ArgumentOutOfRangeException(nameof(onModificationsRetryCount), onModificationsRetryCount, "Value should be greater than 0"); } if (onGettingRetryCount < 1) { throw new ArgumentOutOfRangeException(nameof(onGettingRetryCount), onGettingRetryCount, "Value should be greater than 0"); } _onModificationsRetryCount = onModificationsRetryCount; _onGettingRetryCount = onGettingRetryCount; _retryService = new RetryService( retryDelay: retryDelay ?? TimeSpan.Zero, exceptionFilter: e => { var storageException = e as StorageException; var noRetryStatusCodes = new[] { HttpStatusCode.Conflict, HttpStatusCode.BadRequest }; return(storageException != null && noRetryStatusCodes.Contains((HttpStatusCode)storageException.RequestInformation.HttpStatusCode) ? RetryService.ExceptionFilterResult.ThrowImmediately : RetryService.ExceptionFilterResult.ThrowAfterRetries); }); }
protected void CommitUncommittedItems() { List <IListBlockItem <TItem> > listToCommit = null; lock (_uncommittedListSyncRoot) { if (_uncommittedItems != null && _uncommittedItems.Any()) { listToCommit = new List <IListBlockItem <TItem> >(_uncommittedItems); _uncommittedItems.Clear(); } } if (listToCommit != null && listToCommit.Any()) { var batchUpdateRequest = new BatchUpdateRequest() { TaskId = new TaskId(_applicationName, _taskName), ListBlockId = ListBlockId, ListBlockItems = Convert(listToCommit) }; Action <BatchUpdateRequest> actionRequest = _listBlockRepository.BatchUpdateListBlockItems; RetryService.InvokeWithRetry(actionRequest, batchUpdateRequest); } }
public async Task CompleteAsync() { ValidateBlockIsActive(); await _uncommittedListSemaphore.WaitAsync().ConfigureAwait(false); try { await CommitUncommittedItemsAsync().ConfigureAwait(false); } finally { _uncommittedListSemaphore.Release(); } var status = BlockExecutionStatus.Completed; if ((await GetItemsAsync(ItemStatus.Failed, ItemStatus.Pending).ConfigureAwait(false)).Any()) { status = BlockExecutionStatus.Failed; } var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.List, BlockExecutionId, status); Func <BlockExecutionChangeStatusRequest, Task> actionRequest = _listBlockRepository.ChangeStatusAsync; await RetryService.InvokeWithRetryAsync(actionRequest, request).ConfigureAwait(false); }
/// <summary> /// Metodo per invocare dinamicamente un metodo di servizio su un client tra quelli caricati a runtime in base alle configurazioni all'interno del BaseProxy.json /// </summary> /// <param name="_callConfig">definisce il nome del client sul quale invocare il metodo di servizio e il metodo di servizio da invocare /// { /// "ServiceClientName" : "Nome del client", /// "ServiceMethodName" : "Nome del metodo da invocare" /// } /// se 'ServiceClientName' nullo o vuoto la classe si occupa di fare una ricerca del metodo su tutti i client definiti nel config /// 'ServiceMethodName' non può essere ne nullo ne vuoto /// </param> /// <param name="_datasource">Il datasource con il quale fare il binding sull'oggetto che riceve in input il metodo di servizio, se non si conosce la struttura che deve avere /// invocare il metodo BaseProxy.GetDataSourceInfo(_callConfig) per avere un esempio della struttura /// </param> /// <param name="_configuration">Non obbligatorio, necessario solo nel caso in cui nel datasource sono presenti delle proprietà con nome diverso rispetto a quello dell'oggetto /// sul quel fare il binding. In quel caso va definito in questo modo: /// { /// "NomeProprietàOggettoDestinazione" : "NomeProprietàOggettoJson" /// } /// ES. /// { /// "Name" = "ragsoc", /// "InboundShipmentPlanRequestItems" = "tt-provoci-parent", /// "member" = "tt-provoci" /// } /// </param> /// <returns>Risultato della chiamata al servizio in formato JSON</returns> public string CallServiceDynamically(string _callConfig, string _datasource, string _configuration = "{}") { string _result = string.Empty; logger.Debug(this.GetType().Name + ".CallServiceDynamically -> CallConfig: " + _callConfig); logger.Debug(this.GetType().Name + ".CallServiceDynamically -> DataSource: " + _datasource); logger.Debug(this.GetType().Name + ".CallServiceDynamically -> DataSourceColumnDefinition: " + _configuration); try { //Recupero la configurazione della chiamata al servizio (nome del client e metodo da chiamare) var callConfig = _callConfig.DeserilizeJson <DynamicInvokeConfig>(); //Recupero l'instanza del client del servizio var service = GetServiceInstance(callConfig); //Recupero le informazioni del metodo da invocare var methodInfo = service?.GetType()?.GetMethod(callConfig.ServiceMethodName); //Creo l'istanza della request tramite l'automapper bindando le proprietà con stessa nomenclatura (o come configurazione) tra datasource e instanza var request = AutoMapperService.Map(methodInfo.GetParameters(), _datasource.DeserilizeJson(), _configuration.DeserilizeJson()); logger.Info(GetType().Name + ".CallServiceDynamically -> Calling Service: " + service.GetType().Name + "." + methodInfo.Name); //invoco il metodo RetryService.Excecute(Config.MaxRetry, Config.RetryDelay, () => _result = methodInfo.Invoke(service, request).SerializeObject()); } catch (Exception ex) { logger.Error(GetType().Name + ".CallServiceDynamically -> Deserialization | Reflection | Invoking Error", ex); throw; } logger.Debug(GetType().Name + ".CallServiceDynamically -> result: " + _result); return(_result); }
public async Task FailedAsync() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, _block.RangeType, BlockExecutionId, BlockExecutionStatus.Failed); Func <BlockExecutionChangeStatusRequest, Task> actionRequest = _rangeBlockRepository.ChangeStatusAsync; await RetryService.InvokeWithRetryAsync(actionRequest, request).ConfigureAwait(false); }
public async Task StartAsync() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.Object, BlockExecutionId, BlockExecutionStatus.Started); Func <BlockExecutionChangeStatusRequest, Task> actionRequest = _objectBlockRepository.ChangeStatusAsync; await RetryService.InvokeWithRetryAsync(actionRequest, request).ConfigureAwait(false); }
protected async Task SetStatusAsFailedAsync() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.List, BlockExecutionId, BlockExecutionStatus.Failed); Func <BlockExecutionChangeStatusRequest, Task> actionRequest = _listBlockRepository.ChangeStatusAsync; await RetryService.InvokeWithRetryAsync(actionRequest, request).ConfigureAwait(false); }
public void Failed() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, _block.RangeType, BlockExecutionId, BlockExecutionStatus.Failed); Action <BlockExecutionChangeStatusRequest> actionRequest = _rangeBlockRepository.ChangeStatus; RetryService.InvokeWithRetry(actionRequest, request); }
protected async Task CommitAsync(string listBlockId, IListBlockItem <TItem> item) { var singleUpdateRequest = new SingleUpdateRequest() { TaskId = new TaskId(_applicationName, _taskName), ListBlockId = listBlockId, ListBlockItem = Convert(item) }; Func <SingleUpdateRequest, Task> actionRequest = _listBlockRepository.UpdateListBlockItemAsync; await RetryService.InvokeWithRetryAsync(actionRequest, singleUpdateRequest).ConfigureAwait(false); }
protected void SetStatusAsFailed() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.List, BlockExecutionId, BlockExecutionStatus.Failed); Action <BlockExecutionChangeStatusRequest> actionRequest = _listBlockRepository.ChangeStatus; RetryService.InvokeWithRetry(actionRequest, request); }
public void Start() { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.Object, BlockExecutionId, BlockExecutionStatus.Started); Action <BlockExecutionChangeStatusRequest> actionRequest = _objectBlockRepository.ChangeStatus; RetryService.InvokeWithRetry(actionRequest, request); }
public void Test_that_Retry_executes_action_once_when_it_success() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act retryService.Retry(() => ++ executionsCount, 10); // Assert Assert.AreEqual(1, executionsCount); }
protected void Commit(string listBlockId, IListBlockItem <TItem> item) { var singleUpdateRequest = new SingleUpdateRequest() { TaskId = new TaskId(_applicationName, _taskName), ListBlockId = listBlockId, ListBlockItem = Convert(item) }; Action <SingleUpdateRequest> actionRequest = _listBlockRepository.UpdateListBlockItem; RetryService.InvokeWithRetry(actionRequest, singleUpdateRequest); }
public async Task CompleteAsync(int itemsProcessed) { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, _block.RangeType, BlockExecutionId, BlockExecutionStatus.Completed); request.ItemsProcessed = itemsProcessed; Func <BlockExecutionChangeStatusRequest, Task> actionRequest = _rangeBlockRepository.ChangeStatusAsync; await RetryService.InvokeWithRetryAsync(actionRequest, request).ConfigureAwait(false); }
public void Complete(int itemsProcessed) { var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, _block.RangeType, BlockExecutionId, BlockExecutionStatus.Completed); request.ItemsProcessed = itemsProcessed; Action <BlockExecutionChangeStatusRequest> actionRequest = _rangeBlockRepository.ChangeStatus; RetryService.InvokeWithRetry(actionRequest, request); }
public void Test_that_Retry_executes_action_retryCount_and_throws_when_it_fails() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act/Assert Assert.ThrowsException <InvalidOperationException>(() => retryService.Retry <int>(() => { ++executionsCount; throw new InvalidOperationException(); }, 10)); Assert.AreEqual(10, executionsCount); }
public async Task Test_that_RetryAsyncWithResult_executes_action_once_when_it_success() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act await retryService.RetryAsync(async() => { ++executionsCount; return(await Task.FromResult(0)); }, 10); // Assert Assert.AreEqual(1, executionsCount); }
/// <summary> /// Creates decorator, which adds retries functionality to atomic operations of <see cref="INoSQLTableStorage{T}"/> implementation /// </summary> /// <remarks> /// Methods without retries: /// - GetDataByChunksAsync /// - ScanDataAsync /// - FirstOrNullViaScanAsync /// - GetDataRowKeysOnlyAsync /// - ExecuteAsync /// </remarks> /// <param name="impl"><see cref="INoSQLTableStorage{T}"/> instance to which actual work will be delegated</param> /// <param name="onModificationsRetryCount">Retries count for write operations</param> /// <param name="onGettingRetryCount">Retries count for read operations</param> /// <param name="retryDelay">Delay before next retry. Default value is 200 milliseconds</param> public RetryOnFailureAzureTableStorageDecorator( INoSQLTableStorage <TEntity> impl, int onModificationsRetryCount = 10, int onGettingRetryCount = 10, TimeSpan?retryDelay = null) { _impl = impl ?? throw new ArgumentNullException(nameof(impl)); if (onModificationsRetryCount < 1) { throw new ArgumentOutOfRangeException(nameof(onModificationsRetryCount), onModificationsRetryCount, "Value should be greater than 0"); } if (onGettingRetryCount < 1) { throw new ArgumentOutOfRangeException(nameof(onGettingRetryCount), onGettingRetryCount, "Value should be greater than 0"); } _onModificationsRetryCount = onModificationsRetryCount; _onGettingRetryCount = onGettingRetryCount; _retryService = new RetryService( retryDelay: retryDelay ?? TimeSpan.FromMilliseconds(200), exceptionFilter: e => { switch (e) { case OptimisticConcurrencyException _: return(RetryService.ExceptionFilterResult.ThrowImmediately); case StorageException storageException: { var noRetryStatusCodes = new[] { HttpStatusCode.Conflict, HttpStatusCode.BadRequest, HttpStatusCode.PreconditionFailed }; return(noRetryStatusCodes.Contains((HttpStatusCode)storageException.RequestInformation.HttpStatusCode) ? RetryService.ExceptionFilterResult.ThrowImmediately : RetryService.ExceptionFilterResult.ThrowAfterRetries); } } return(RetryService.ExceptionFilterResult.ThrowAfterRetries); }); }
public IoTHubService(StatefulServiceContext context, Settings settings) : base(context) { _settings = settings; _offsetInterval = settings.OffsetInterval; _serviceBackupFrequentSeconds = settings.IotHubServiceBackupFrequentSeconds; _servicePartitionId = context.PartitionId; ServiceUriBuilder routerServiceNameUriBuilder = new ServiceUriBuilder(Names.RouterServiceName); _routerServiceUri = routerServiceNameUriBuilder.Build(); _retryService = new RetryService(TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), TimeSpan.FromMilliseconds(30)); _microServiceProcessor = new MicroServiceProcessor(context, ServiceEventSource.Current); _longServiceProcessor = new LongServiceProcessor(ServiceEventSource.Current, context); _partitionServiceFinder = new PartitionServiceFinder(); }
public async Task Test_that_RetryAsyncWithResult_executes_action_once_and_throws_when_it_fails_and_filterreturns_ThrowImmediately() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowImmediately); // Act var retryTask = retryService.RetryAsync(async() => { ++executionsCount; return(await Task.FromException <int>(new InvalidOperationException())); }, 1); // Assert await Assert.ThrowsExceptionAsync <InvalidOperationException>(() => retryTask); Assert.AreEqual(1, executionsCount); }
public async Task Test_that_RetryAsync_executes_action_retryCount_and_throws_when_it_fails() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act var retryTask = retryService.RetryAsync(async() => { ++executionsCount; await Task.FromResult(0); throw new InvalidOperationException(); }, 10); // Assert await Assert.ThrowsExceptionAsync <InvalidOperationException>(() => retryTask); Assert.AreEqual(10, executionsCount); }
public void Test_that_Retry_executes_action_until_it_restores_after_failure() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act/Assert var result = retryService.Retry(() => { ++executionsCount; if (executionsCount < 5) { throw new InvalidOperationException(); } return(4); }, 10); Assert.AreEqual(5, executionsCount); Assert.AreEqual(4, result); }
public void Complete() { ValidateBlockIsActive(); CommitUncommittedItems(); var status = BlockExecutionStatus.Completed; if (GetItems(ItemStatus.Failed, ItemStatus.Pending).Any()) { status = BlockExecutionStatus.Failed; } var request = new BlockExecutionChangeStatusRequest(new TaskId(_applicationName, _taskName), _taskExecutionId, BlockType.List, BlockExecutionId, status); Action <BlockExecutionChangeStatusRequest> actionRequest = _listBlockRepository.ChangeStatus; RetryService.InvokeWithRetry(actionRequest, request); }
private static async Task MainAsync() { var settings = new RetrySettings(3, 2000); var retry = new RetryService(settings); IFileCopyService service = new StreamCopyService(retry); var source = FileItem.Create(SourceFilePath); var destination = FileItem.Create(DestinationFilePath); void PrintProgress(long bytesWritten) { var remainingBytes = source.SizeInBytes - bytesWritten; Console.WriteLine( $"Total: {source.SizeInBytes} - Written: {bytesWritten} - Remaining: {remainingBytes}"); } var progressIndicator = new Progress <long>(PrintProgress); var cst = new CancellationTokenSource(5000); var stopwatch = Stopwatch.StartNew(); try { await service.CopyAsync(source, destination, progressIndicator, cst.Token) .ContinueWith(task => Console.WriteLine("Copy file completed!"), cst.Token); } catch (Exception exception) { Console.WriteLine(exception.Message); } finally { stopwatch.Stop(); } Console.WriteLine($"Elapsed Milliseconds: {stopwatch.ElapsedMilliseconds}"); }
public async Task Test_that_RetryAsync_executes_action_until_it_restores_after_failure() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act await retryService.RetryAsync(async() => { ++executionsCount; await Task.FromResult(0); if (executionsCount < 5) { throw new InvalidOperationException(); } }, 10); // Assert Assert.AreEqual(5, executionsCount); }
protected async Task CommitUncommittedItemsAsync() { List <IListBlockItem <TItem> > listToCommit = null; if (_uncommittedItems != null && _uncommittedItems.Any()) { listToCommit = new List <IListBlockItem <TItem> >(_uncommittedItems); _uncommittedItems.Clear(); } if (listToCommit != null && listToCommit.Any()) { var batchUpdateRequest = new BatchUpdateRequest() { TaskId = new TaskId(_applicationName, _taskName), ListBlockId = ListBlockId, ListBlockItems = Convert(listToCommit) }; Func <BatchUpdateRequest, Task> actionRequest = _listBlockRepository.BatchUpdateListBlockItemsAsync; await RetryService.InvokeWithRetryAsync(actionRequest, batchUpdateRequest).ConfigureAwait(false); } }
public async Task Test_that_RetryAsyncWithResult_executes_action_until_it_restores_after_failure() { // Arrange var executionsCount = 0; var retryService = new RetryService(e => RetryService.ExceptionFilterResult.ThrowAfterRetries); // Act var result = await retryService.RetryAsync(async() => { ++executionsCount; if (executionsCount < 5) { return(await Task.FromException <int>(new InvalidOperationException())); } return(await Task.FromResult(4)); }, 10); // Assert Assert.AreEqual(5, executionsCount); Assert.AreEqual(4, result); }
public ConvertingServerServiceFactory(Func <IServiceConsumer <IFileConvertingServerService> > getConvertingService, RetryService retryService) : base(getConvertingService, retryService) { }
public SignatureServerServiceFactory(Func <IServiceConsumer <ISignatureServerService> > getSignatureService, RetryService retryService) : base(getSignatureService, retryService) { }