public async Task GivenNoDeletedInstances_WhenCleanupCalled_ThenNotCallStoresAndReturnsCorrectTuple() { _indexDataStore .RetrieveDeletedInstancesAsync(Arg.Any <int>(), Arg.Any <int>(), Arg.Any <CancellationToken>()) .ReturnsForAnyArgs(Enumerable.Empty <VersionedInstanceIdentifier>()); (bool success, int retrievedInstanceCount) = await _deleteService.CleanupDeletedInstancesAsync(CancellationToken.None); Assert.True(success); Assert.Equal(0, retrievedInstanceCount); await _indexDataStore .ReceivedWithAnyArgs(1) .RetrieveDeletedInstancesAsync(batchSize: default, maxRetries: default, CancellationToken.None);
/// <inheritdoc /> public async Task <IEnumerable <VersionedInstanceIdentifier> > RetrieveDeletedInstancesAsync(int batchSize, int maxRetries, CancellationToken cancellationToken) { LogRetrieveDeletedInstancesAsyncDelegate(_logger, batchSize, maxRetries, null); try { IEnumerable <VersionedInstanceIdentifier> deletedInstances = await _indexDataStore.RetrieveDeletedInstancesAsync(batchSize, maxRetries, cancellationToken); LogOperationSucceededDelegate(_logger, null); return(deletedInstances); } catch (Exception ex) { LogOperationFailedDelegate(_logger, ex); throw; } }
public async Task <(bool success, int retrievedInstanceCount)> CleanupDeletedInstancesAsync(CancellationToken cancellationToken) { bool success = true; int retrievedInstanceCount = 0; using (ITransactionScope transactionScope = _transactionHandler.BeginTransaction()) { try { var deletedInstanceIdentifiers = (await _indexDataStore .RetrieveDeletedInstancesAsync( _deletedInstanceCleanupConfiguration.BatchSize, _deletedInstanceCleanupConfiguration.MaxRetries, cancellationToken)) .ToList(); retrievedInstanceCount = deletedInstanceIdentifiers.Count; foreach (VersionedInstanceIdentifier deletedInstanceIdentifier in deletedInstanceIdentifiers) { try { Task[] tasks = new[] { _fileStore.DeleteFileIfExistsAsync(deletedInstanceIdentifier, cancellationToken), _metadataStore.DeleteInstanceMetadataIfExistsAsync(deletedInstanceIdentifier, cancellationToken), }; await Task.WhenAll(tasks); await _indexDataStore.DeleteDeletedInstanceAsync(deletedInstanceIdentifier, cancellationToken); } catch (Exception cleanupException) { try { int newRetryCount = await _indexDataStore.IncrementDeletedInstanceRetryAsync(deletedInstanceIdentifier, GenerateCleanupAfter(_deletedInstanceCleanupConfiguration.RetryBackOff), cancellationToken); if (newRetryCount > _deletedInstanceCleanupConfiguration.MaxRetries) { _logger.LogCritical(cleanupException, "Failed to cleanup instance {deletedInstanceIdentifier}. Retry count is now {newRetryCount} and retry will not be re-attempted.", deletedInstanceIdentifier, newRetryCount); } else { _logger.LogError(cleanupException, "Failed to cleanup instance {deletedInstanceIdentifier}. Retry count is now {newRetryCount}.", deletedInstanceIdentifier, newRetryCount); } } catch (Exception incrementException) { _logger.LogCritical(incrementException, "Failed to increment cleanup retry for instance {deletedInstanceIdentifier}.", deletedInstanceIdentifier); success = false; } } } transactionScope.Complete(); } catch (Exception retrieveException) { _logger.LogCritical(retrieveException, "Failed to retrieve instances to cleanup."); success = false; } } return(success, retrievedInstanceCount); }