public override async Task AuthenticateAsync(IConnection connection, CancellationToken cancellationToken = default) { using var rootSpan = Tracer.RequestSpan(OuterRequestSpans.Attributes.Service, OuterRequestSpans.ServiceSpan.Internal.AuthenticatePlain); using var op = new SaslStart { Key = MechanismType.GetDescription() !, Content = GetAuthData(_username, _password), Opaque = SequenceGenerator.GetNext(), Span = rootSpan, Timeout = Timeout }; OperationConfigurator.Configure(op, SaslOptions.Instance); using var ctp = CancellationTokenPairSource.FromTimeout(Timeout, cancellationToken); await SendAsync(op, connection, cancellationToken).ConfigureAwait(false); }
public async Task ExternalCancellation_ReadOnlyOperation_Cancels(bool isSent) { // Arrange var operation = new Get <dynamic> { IsSent = isSent }; using var cts = new CancellationTokenSource(100); using var tokenPair = CancellationTokenPairSource.FromExternalToken(cts.Token); // Act using var registration = new OperationCancellationRegistration(operation, tokenPair.TokenPair); // Assert await Assert.ThrowsAnyAsync <OperationCanceledException>(() => operation.Completed.AsTask()); }
public async Task ExternalCancellation_MutationOperationNotSent_Cancels() { // Arrange var operation = new Set <dynamic>("fake", "fakeKey") { IsSent = false }; using var cts = new CancellationTokenSource(100); using var tokenPair = CancellationTokenPairSource.FromExternalToken(cts.Token); // Act using var registration = new OperationCancellationRegistration(operation, tokenPair.TokenPair); // Assert await Assert.ThrowsAnyAsync <OperationCanceledException>(() => operation.Completed.AsTask()); }
protected async Task <T> SendAsync <T>(IOperation <T> op, IConnection connection, CancellationToken cancellationToken) { await op.SendAsync(connection, cancellationToken).ConfigureAwait(false); ResponseStatus status; using var ctp = CancellationTokenPairSource.FromTimeout(Timeout, cancellationToken); using (new OperationCancellationRegistration(op, ctp.TokenPair)) { status = await op.Completed.ConfigureAwait(false); } if (status != ResponseStatus.Success && status != ResponseStatus.AuthenticationContinue) { throw new AuthenticationFailureException( $"Cannot authenticate the user. Reason: {status}"); } return(op.GetValue() !); }
private async Task AssertRetryThenSuccessAsync(OperationBase op, Exception exp) { var retryOrchestrator = CreateRetryOrchestrator(); var bucketMock = new Mock <BucketBase>("fake", new ClusterContext(), new Mock <Couchbase.Core.DI.IScopeFactory>().Object, retryOrchestrator, new Mock <ILogger>().Object, new TypedRedactor(RedactionLevel.None), new Mock <IBootstrapperFactory>().Object, NoopRequestTracer.Instance, new Mock <IOperationConfigurator>().Object, new BestEffortRetryStrategy(), new BucketConfig()); bucketMock.Setup(x => x.SendAsync(op, It.IsAny <CancellationTokenPair>())).Callback((IOperation op1, CancellationTokenPair ct) => { if (op1.Completed.IsCompleted) { Assert.True(false, "operation result should be reset before retry"); } // complete the operation if circuit breaker is not open (ResponseStatus does not matter for this test) if (exp.GetType() != typeof(CircuitBreakerException) || op.Attempts != 0) { op.HandleOperationCompleted(AsyncState.BuildErrorResponse(op.Opaque, ResponseStatus.TemporaryFailure)); } if (op1.Attempts == 0) { throw exp; } }).Returns(op.Completed.AsTask()); using var tokenPair = CancellationTokenPairSource.FromTimeout(TimeSpan.FromMilliseconds(2500)); try { await retryOrchestrator.RetryAsync(bucketMock.Object, op, tokenPair.TokenPair).ConfigureAwait(false); } catch (Exception ex) { var msg = ex.Message; Assert.True(false, "Expected operation to succeed after retry"); } Assert.True(op.Attempts > 0); }
public void Dispose_CancelsRegistration() { // Arrange var operation = new Get <dynamic>(); var cts = new CancellationTokenSource(); using var tokenPair = CancellationTokenPairSource.FromInternalToken(cts.Token); // Act var registration = new OperationCancellationRegistration(operation, tokenPair.TokenPair); registration.Dispose(); // Assert cts.Cancel(); Assert.False(operation.Completed.IsCompleted); }
private static async Task <ConcurrentDictionary <string, IEnumerable <IEndpointDiagnostics> > > GetEndpointDiagnosticsAsync(ClusterContext context, IEnumerable <IClusterNode> clusterNodes, bool ping, ICollection <ServiceType> serviceTypes, CancellationToken token) { var endpoints = new ConcurrentDictionary <string, IEnumerable <IEndpointDiagnostics> >(); IOperationConfigurator operationConfigurator = ping ? context.ServiceProvider.GetRequiredService <IOperationConfigurator>() : null; foreach (var clusterNode in clusterNodes) { if (serviceTypes.Contains(ServiceType.KeyValue) && clusterNode.HasKv) { var kvEndpoints = (List <IEndpointDiagnostics>)endpoints.GetOrAdd("kv", new List <IEndpointDiagnostics>()); foreach (var connection in clusterNode.ConnectionPool.GetConnections()) { var endPointDiagnostics = CreateEndpointHealth(clusterNode.Owner?.Name, DateTime.UtcNow, connection, ping); if (ping) { await RecordLatencyAsync(endPointDiagnostics, async() => { try { using var op = new Noop(); operationConfigurator.Configure(op); using var ctp = token == CancellationToken.None ? CancellationTokenPairSource.FromTimeout(context.ClusterOptions.KvTimeout) : CancellationTokenPairSource.FromExternalToken(token); await clusterNode.ExecuteOp(connection, op, ctp.TokenPair).ConfigureAwait(false); } catch (ObjectDisposedException) { //Ignore as the ping is on a timer is a race condition when the connection is closed } }).ConfigureAwait(false);
public async Task Operation_Succeeds_Without_Retry() { var retryOrchestrator = CreateRetryOrchestrator(); var op = new Get <dynamic> { RetryStrategy = new BestEffortRetryStrategy() }; var bucketMock = new Mock <BucketBase>("fake", new ClusterContext(), new Mock <Couchbase.Core.DI.IScopeFactory>().Object, retryOrchestrator, new Mock <ILogger>().Object, new TypedRedactor(RedactionLevel.None), new Mock <IBootstrapperFactory>().Object, NoopRequestTracer.Instance, new Mock <IOperationConfigurator>().Object, new BestEffortRetryStrategy(), new BucketConfig()); bucketMock.Setup(x => x.SendAsync(op, It.IsAny <CancellationTokenPair>())) .Returns(Task.CompletedTask); using var tokenPair = CancellationTokenPairSource.FromTimeout(TimeSpan.FromMilliseconds(2500)); await retryOrchestrator.RetryAsync(bucketMock.Object, op, tokenPair.TokenPair).ConfigureAwait(false); Assert.Equal(0u, op.Attempts); }
private static async Task AssertDoesNotRetryAsync(IOperation op, Exception exp) { var retryOrchestrator = CreateRetryOrchestrator(); var bucketMock = new Mock <BucketBase>("name", new ClusterContext(), new Mock <Couchbase.Core.DI.IScopeFactory>().Object, retryOrchestrator, new Mock <ILogger>().Object, new TypedRedactor(RedactionLevel.None), new Mock <IBootstrapperFactory>().Object, NoopRequestTracer.Instance, new Mock <IOperationConfigurator>().Object, new BestEffortRetryStrategy(), new BucketConfig()) { CallBase = true }; bucketMock.Setup(x => x.SendAsync(op, It.IsAny <CancellationTokenPair>())).Throws(exp); using var tokenPair = CancellationTokenPairSource.FromTimeout(TimeSpan.FromMilliseconds(2500)); try { await bucketMock.Object.RetryAsync(op, tokenPair.TokenPair).ConfigureAwait(false); } catch (Exception e) { if (e.GetType() == exp.GetType()) { //expected } else { throw; } } Assert.True(op.Attempts == 0); }
private CancellationTokenPairSource CreateRetryTimeoutCancellationTokenSource(FunctionOptionsBase options) => CancellationTokenPairSource.FromTimeout(options.Timeout, options.Token);
private CancellationTokenPairSource CreateRetryTimeoutCancellationTokenSource( ITimeoutOptions options, IOperation op) => CancellationTokenPairSource.FromTimeout(GetTimeout(options.Timeout, op), options.Token);