/// <summary> /// Creates and initializes a retryable read operation context. /// </summary> /// <param name="binding">The binding.</param> /// <param name="retryRequested">if set to <c>true</c> [retry requested].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A retryable read context.</returns> public static async Task <RetryableReadContext> CreateAsync(IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableReadContext(binding, retryRequested); try { await context.InitializeAsync(cancellationToken).ConfigureAwait(false); if (ChannelPinningHelper.PinChannelSourceAndChannelIfRequired( context.ChannelSource, context.Channel, context.Binding.Session, out var pinnedChannelSource, out var pinnedChannel)) { context.ReplaceChannelSource(pinnedChannelSource); context.ReplaceChannel(pinnedChannel); } return(context); } catch { context.Dispose(); throw; } }
public static bool ShouldConnectionAcquireBeRetried(RetryableReadContext context, Exception ex) { // According the spec error during handshake should be handle according to RetryableReads logic var innerException = ex is MongoAuthenticationException mongoAuthenticationException ? mongoAuthenticationException.InnerException : ex; return(context.RetryRequested && !context.Binding.Session.IsInTransaction && RetryabilityHelper.IsRetryableReadException(innerException)); }
public static async Task <TResult> ExecuteAsync <TResult>(IRetryableReadOperation <TResult> operation, IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { using (var context = await RetryableReadContext.CreateAsync(binding, retryRequested, cancellationToken).ConfigureAwait(false)) { return(await ExecuteAsync(operation, context, cancellationToken).ConfigureAwait(false)); } }
// public static methods public static TResult Execute <TResult>(IRetryableReadOperation <TResult> operation, IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { using (var context = RetryableReadContext.Create(binding, retryRequested, cancellationToken)) { return(Execute(operation, context, cancellationToken)); } }
/// <inheritdoc/> public IAsyncCursor <BsonDocument> Execute(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); var operation = CreateOperation(); return(operation.Execute(context, cancellationToken)); }
/// <inheritdoc/> public async Task <IAsyncCursor <BsonDocument> > ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); var operation = CreateOperation(); return(await operation.ExecuteAsync(context, cancellationToken).ConfigureAwait(false)); }
/// <inheritdoc/> public async Task <IAsyncCursor <TDocument> > ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); var operation = CreateOperation(context.Channel.ConnectionDescription.ServerVersion); return(await operation.ExecuteAsync(context, cancellationToken).ConfigureAwait(false)); }
/// <inheritdoc/> public IAsyncCursor <TDocument> Execute(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); var operation = CreateOperation(context.Channel.ConnectionDescription.ServerVersion); return(operation.Execute(context, cancellationToken)); }
/// <inheritdoc/> public async Task <IAsyncCursor <TDocument> > ExecuteAsync(IReadBinding binding, CancellationToken cancellationToken) { Ensure.IsNotNull(binding, nameof(binding)); using (var context = await RetryableReadContext.CreateAsync(binding, retryRequested: false, cancellationToken).ConfigureAwait(false)) { return(await ExecuteAsync(context, cancellationToken).ConfigureAwait(false)); } }
/// <inheritdoc/> public IAsyncCursor <TDocument> Execute(IReadBinding binding, CancellationToken cancellationToken) { Ensure.IsNotNull(binding, nameof(binding)); using (var context = RetryableReadContext.Create(binding, retryRequested: false, cancellationToken)) { return(Execute(context, cancellationToken)); } }
/// <inheritdoc/> public IAsyncCursor <BsonDocument> Execute(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); using (EventContext.BeginOperation()) { var operation = CreateOperation(); var result = operation.Execute(context, cancellationToken); return(CreateCursor(context.ChannelSource, operation.Command, result)); } }
/// <inheritdoc/> public IAsyncCursor <BsonDocument> Execute(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); using (EventContext.BeginOperation()) { var operation = CreateOperation(); var cursor = operation.Execute(context, cancellationToken); return(new BatchTransformingAsyncCursor <BsonDocument, BsonDocument>(cursor, NormalizeQueryResponse)); } }
// public static methods /// <summary> /// Creates and initializes a retryable read operation context. /// </summary> /// <param name="binding">The binding.</param> /// <param name="retryRequested">if set to <c>true</c> [retry requested].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A retryable read context.</returns> public static RetryableReadContext Create(IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableReadContext(binding, retryRequested); try { context.Initialize(cancellationToken); return(context); } catch { context.Dispose(); throw; } }
/// <inheritdoc/> public IAsyncCursor <TDocument> Execute(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); using (EventContext.BeginOperation()) using (EventContext.BeginFind(_batchSize, _limit)) { var readPreference = context.Binding.ReadPreference; var serverDescription = context.ChannelSource.ServerDescription; var wrappedQuery = CreateWrappedQuery(serverDescription.Type, readPreference, out var secondaryOk); var batch = ExecuteProtocol(context.Channel, wrappedQuery, secondaryOk, cancellationToken); return(CreateCursor(context.ChannelSource, wrappedQuery, batch)); } }
/// <summary> /// Creates and initializes a retryable read operation context. /// </summary> /// <param name="binding">The binding.</param> /// <param name="retryRequested">if set to <c>true</c> [retry requested].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A retryable read context.</returns> public static async Task <RetryableReadContext> CreateAsync(IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableReadContext(binding, retryRequested); try { await context.InitializeAsync(cancellationToken).ConfigureAwait(false); return(context); } catch { context.Dispose(); throw; } }
/// <inheritdoc/> public async Task <IAsyncCursor <TDocument> > ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken) { Ensure.IsNotNull(context, nameof(context)); using (EventContext.BeginOperation()) using (EventContext.BeginFind(_batchSize, _limit)) { var readPreference = context.Binding.ReadPreference; var serverDescription = context.ChannelSource.ServerDescription; var wrappedQuery = CreateWrappedQuery(serverDescription.Type, readPreference); var slaveOk = readPreference != null && readPreference.ReadPreferenceMode != ReadPreferenceMode.Primary; var batch = await ExecuteProtocolAsync(context.Channel, wrappedQuery, slaveOk, cancellationToken).ConfigureAwait(false); return(CreateCursor(context.ChannelSource, wrappedQuery, batch)); } }
// public static methods /// <summary> /// Creates and initializes a retryable read operation context. /// </summary> /// <param name="binding">The binding.</param> /// <param name="retryRequested">if set to <c>true</c> [retry requested].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A retryable read context.</returns> public static RetryableReadContext Create(IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableReadContext(binding, retryRequested); try { context.Initialize(cancellationToken); ChannelPinningHelper.PinChannellIfRequired( context.ChannelSource, context.Channel, context.Binding.Session); return(context); } catch { context.Dispose(); throw; } }
public static async Task <TResult> ExecuteAsync <TResult>(IRetryableReadOperation <TResult> operation, RetryableReadContext context, CancellationToken cancellationToken) { if (!ShouldReadBeRetried(context)) { return(await operation.ExecuteAttemptAsync(context, attempt : 1, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } var initialServerVersion = context.Channel.ConnectionDescription.ServerVersion; Exception originalException; try { return(await operation.ExecuteAttemptAsync(context, attempt : 1, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(RetryabilityHelper.IsRetryableReadException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(context.Binding.GetReadChannelSource(cancellationToken)); context.ReplaceChannel(context.ChannelSource.GetChannel(cancellationToken)); } catch { throw originalException; } if (context.Channel.ConnectionDescription.ServerVersion < initialServerVersion) { throw originalException; } if (!AreRetryableReadsSupported(context)) { throw originalException; } try { return(await operation.ExecuteAttemptAsync(context, attempt : 2, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }
public static TResult Execute <TResult>(IRetryableReadOperation <TResult> operation, RetryableReadContext context, CancellationToken cancellationToken) { if (!ShouldReadBeRetried(context)) { return(operation.ExecuteAttempt(context, attempt: 1, transactionNumber: null, cancellationToken)); } Exception originalException; try { return(operation.ExecuteAttempt(context, attempt: 1, transactionNumber: null, cancellationToken)); } catch (Exception ex) when(RetryabilityHelper.IsRetryableReadException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(context.Binding.GetReadChannelSource(cancellationToken)); context.ReplaceChannel(context.ChannelSource.GetChannel(cancellationToken)); } catch { throw originalException; } try { return(operation.ExecuteAttempt(context, attempt: 2, transactionNumber: null, cancellationToken)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }
private static bool ShouldReadBeRetried(RetryableReadContext context) { return(context.RetryRequested && AreRetryableReadsSupported(context) && !context.Binding.Session.IsInTransaction); }
public static bool ShouldConnectionAcquireBeRetried(RetryableReadContext context, ServerDescription serverDescription) { return(context.RetryRequested && Feature.RetryableReads.IsSupported(serverDescription.Version) && !context.Binding.Session.IsInTransaction); }
// private static methods private static bool AreRetryableReadsSupported(RetryableReadContext context) { return(Feature.RetryableReads.IsSupported(context.Channel.ConnectionDescription.ServerVersion)); }