private async Task <MutateRowsResponse> MutateRowsImpl(MutateRowsRequest request, CallSettings callSettings) { var defaultSettings = _client.DefaultSettings ?? new BigtableServiceApiSettings(); var effectiveCallSettings = defaultSettings.MutateRowsSettings.MergedWith(callSettings); var effectiveRetrySettings = defaultSettings.MutateRowsRetrySettings; // TODO: Should the request manager be using the retry filter? We would need to fabricate RpcExceptions StatusCode[] retryStatuses = { StatusCode.DeadlineExceeded, StatusCode.Unavailable }; var requestManager = new BigtableMutateRowsRequestManager(retryStatuses, request); await Utilities.RetryOperationUntilCompleted( async() => { var currentStream = _client.MutateRows(requestManager.NextRequest, callSettings); return(await ProcessCurrentStream(currentStream).ConfigureAwait(false) != ProcessingStatus.Retryable); }, Clock, Scheduler, effectiveCallSettings, effectiveRetrySettings).ConfigureAwait(false); return(requestManager.BuildResponse()); async Task <ProcessingStatus> ProcessCurrentStream(BigtableServiceApiClient.MutateRowsStream stream) { var cancellationToken = effectiveCallSettings.CancellationToken ?? default; var responseStream = stream.ResponseStream; while (await responseStream.MoveNext(cancellationToken).ConfigureAwait(false)) { requestManager.SetStatus(responseStream.Current); } return(requestManager.OnOk()); } }
partial void Modify_MutateRowsRequest(ref MutateRowsRequest request, ref CallSettings settings) { GaxPreconditions.CheckState( request.IsIdempotent(), "Non-idempotent MutateRows requests are not allowed. Specify a version with all SetCell mutations."); TryApplyAppProfileId(request, r => r.AppProfileId, (r, a) => r.AppProfileId = a); }
/// <summary> /// Constructor for <see cref="BigtableMutateRowsRequestManager"/>. /// </summary> /// <param name="retryStatuses"> /// Collection of Grpc status codes to retry on.</param> /// <param name="mutateRowsRequest"> /// <see cref="MutateRowsRequest"/> that was received from the user.</param> internal BigtableMutateRowsRequestManager(IEnumerable <StatusCode> retryStatuses, MutateRowsRequest mutateRowsRequest) { _originalRequest = mutateRowsRequest; _results = new Rpc.Status[_originalRequest.Entries.Count]; _retryableCodes = new HashSet <int>(retryStatuses.Select(status => (int)status)); }
/// <summary> /// Creates a new MutateRowsRequest that's a subset of the original request that /// corresponds to a set of indices. /// </summary> /// <param name="indiciesToRetry"> /// List of ints that represents indicies of entries that failed. /// </param> private void CreateRetryRequest(List <int> indiciesToRetry) { RetryRequest = new MutateRowsRequest(); _mapToOriginalIndex = new int[indiciesToRetry.Count]; for (int i = 0; i < _mapToOriginalIndex.Length; i++) { _mapToOriginalIndex[i] = indiciesToRetry[i]; RetryRequest.Entries.Add(_originalRequest.Entries[indiciesToRetry[i]]); } }
/// <inheritdoc/> public override stt::Task <MutateRowsResponse> MutateRowsAsync( MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) { if (request.AppProfileId == null) { request.AppProfileId = _appProfileId; } return(ConvertResult(request, callSettings, GetUnderlyingClient().MutateRows(request, callSettings))); }
/// <inheritdoc/> public override stt::Task <MutateRowsResponse> MutateRowsAsync( MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) { if (request.AppProfileId == null) { request.AppProfileId = _appProfileId; } return(MutateRowsImpl(request, callSettings)); }
private static MutateRowsRequest CreateMutateRowRequest(TableName tableName, IEnumerable <MutateRowsRequest.Types.Entry> entries) { var request = new MutateRowsRequest { TableNameAsTableName = GaxPreconditions.CheckNotNull(tableName, nameof(tableName)), Entries = { Utilities.ValidateCollection(entries, nameof(entries)) } }; GaxPreconditions.CheckArgument( request.Entries.Count != 0, nameof(entries), "There must be at least one entry."); return(request); }
/// <summary> /// This method is called when all calls to <see cref="SetStatus(MutateRowsResponse)"/> are complete. /// </summary> /// <returns> /// ProcessingStatus of the accumulated responses - invalid, retryable, non-retryable. /// </returns> internal ProcessingStatus OnOk() { // Sanity check to make sure that every mutation received a response. _messageIsInvalid = _messageIsInvalid || _results.Any(result => result == null); // There was a problem in the data found in SetStatus(), so fail the RPC. if (_messageIsInvalid) { return(ProcessingStatus.Invalid); } // This list hold indices of entries to be included in retry request List <int> toRetry = null; ProcessingStatus processingStatus = ProcessingStatus.NotRetryable; // Check the current state to determine the state of the results. // There are three states: OK, Fail, or Partial Retry. for (int i = 0; i < _results.Length; i++) { Rpc.Status status = _results[i]; if (status.Code == (int)StatusCode.OK) { continue; } if (_retryableCodes.Contains(status.Code)) { if (toRetry == null) { toRetry = new List <int>(); } // An individual mutation failed with a retryable code, usually DEADLINE_EXCEEDED. toRetry.Add(i); processingStatus = ProcessingStatus.Retryable; } else { // Don't retry if even a single response is not retryable. processingStatus = ProcessingStatus.NotRetryable; break; } } if (processingStatus == ProcessingStatus.Retryable) { CreateRetryRequest(toRetry); } else { RetryRequest = null; } return(processingStatus); }
/// <summary> /// Creates a new MutateRowsRequest that's a subset of the original request that /// corresponds to a set of indices. /// </summary> /// <param name="indiciesToRetry"> /// List of ints that represents indicies of entries that failed. /// </param> private void CreateRetryRequest(List <int> indiciesToRetry) { NextRequest = new MutateRowsRequest { TableName = _originalRequest.TableName, AppProfileId = _originalRequest.AppProfileId }; _mapToOriginalIndex = new int[indiciesToRetry.Count]; for (int i = 0; i < _mapToOriginalIndex.Length; i++) { _mapToOriginalIndex[i] = indiciesToRetry[i]; NextRequest.Entries.Add(_originalRequest.Entries[indiciesToRetry[i]]); } }
/// <summary> /// Mutates multiple rows in a batch. Each individual row is mutated /// atomically as in <see cref="MutateRow(MutateRowRequest, CallSettings)"/>, /// but the entire batch is not executed atomically. /// </summary> /// <remarks> /// <para> /// Note this method executes a server streaming RPC. It is not a synchronous call. The caller must process the responses from /// stream as they are returned from the server. Each response will indicate the status for one or more entry of mutations. /// </para> /// <para> /// This method simply delegates to <see cref="MutateRows(MutateRowsRequest, CallSettings)"/>. /// </para> /// </remarks> /// <param name="tableName"> /// The unique name of the table to which the mutations should be applied. Must not be null. /// </param> /// <param name="entries"> /// The row keys and corresponding mutations to be applied in bulk. /// Each entry is applied as an atomic mutation, but the entries may be /// applied in arbitrary order (even between entries for the same row). /// At least one entry must be specified, and in total the entries can /// contain at most 100000 mutations. Must not be null, or contain null /// elements. /// </param> /// <param name="callSettings"> /// If not null, applies overrides to this RPC call. /// </param> /// <returns> /// The server stream. /// </returns> public virtual MutateRowsStream MutateRows( TableName tableName, IEnumerable <MutateRowsRequest.Types.Entry> entries, CallSettings callSettings = null) { var request = new MutateRowsRequest { TableNameAsTableName = GaxPreconditions.CheckNotNull(tableName, nameof(tableName)), Entries = { Utilities.ValidateCollection(entries, nameof(entries)) } }; GaxPreconditions.CheckArgument( request.Entries.Count != 0, nameof(entries), "There must be at least one entry."); return(MutateRows(request, callSettings)); }
internal static bool IsIdempotent(this MutateRowsRequest request) => request.Entries.All(IsIdempotent);
/// <inheritdoc/> public override MutateRowsResponse MutateRows( MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) => stt::Task.Run(() => MutateRowsAsync(request, callSettings)).ResultWithUnwrappedExceptions();
/// <summary> /// Mutates multiple rows in a batch. Each individual row is mutated /// atomically as in MutateRow, but the entire batch is not executed /// atomically. /// </summary> /// <param name="request"> /// The request object containing all of the parameters for the API call. /// If the <see cref="MutateRowsRequest.AppProfileId"/> has not been specified, it will be initialized from the value stored in the client. /// </param> /// <param name="cancellationToken">A <see cref="st::CancellationToken"/> to use for this RPC.</param> /// <returns>The RPC response.</returns> public virtual stt::Task <MutateRowsResponse> MutateRowsAsync( MutateRowsRequest request, st::CancellationToken cancellationToken) => MutateRowsAsync(request, gaxgrpc::CallSettings.FromCancellationToken(cancellationToken));
/// <summary> /// Mutates multiple rows in a batch. Each individual row is mutated /// atomically as in MutateRow, but the entire batch is not executed /// atomically. /// </summary> /// <param name="request"> /// The request object containing all of the parameters for the API call. /// If the <see cref="MutateRowsRequest.AppProfileId"/> has not been specified, it will be initialized from the value stored in the client. /// </param> /// <param name="callSettings"> /// If not null, applies overrides to this RPC call. /// </param> /// <returns>The RPC response.</returns> public virtual stt::Task <MutateRowsResponse> MutateRowsAsync( MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) { throw new sys::NotImplementedException(); }
/// <summary> /// Mutates multiple rows in a batch. Each individual row is mutated /// atomically as in MutateRow, but the entire batch is not executed /// atomically. /// </summary> /// <param name="request"> /// The request object containing all of the parameters for the API call. /// If the <see cref="MutateRowsRequest.AppProfileId"/> has not been specified, it will be initialized from the value stored in the client. /// </param> /// <param name="callSettings"> /// If not null, applies overrides to this RPC call. /// </param> /// <returns>The RPC response.</returns> public virtual MutateRowsResponse MutateRows( MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) { throw new sys::NotImplementedException(); }
/// <summary> /// Mutates multiple rows in a batch. Each individual row is mutated /// atomically as in MutateRow, but the entire batch is not executed /// atomically. /// </summary> /// <param name="request"> /// The request object containing all of the parameters for the API call. /// If the <see cref="MutateRowsRequest.AppProfileId"/> has not been specified, it will be initialized from the value stored in the client. /// </param> /// <param name="callSettings"> /// If not null, applies overrides to this RPC call. /// </param> /// <returns>The RPC response.</returns> public virtual Task <MutateRowsResponse> MutateRowsAsync( MutateRowsRequest request, CallSettings callSettings = null) { throw new NotImplementedException(); }
/// <inheritdoc/> public override stt::Task <MutateRowsResponse> MutateRowsAsync(MutateRowsRequest request, gaxgrpc::CallSettings callSettings = null) => MutateRowsImpl(request, callSettings);
partial void Modify_MutateRowsRequest(ref MutateRowsRequest request, ref CallSettings settings) => GaxPreconditions.CheckState( request.IsIdempotent(), "Non-idempotent MutateRows requests are not allowed. Specify a version with all SetCell mutations.");
partial void Modify_MutateRowsRequest(ref MutateRowsRequest request, ref CallSettings settings) => ApplyResourcePrefixHeader(ref settings, request.TableName);
partial void Modify_MutateRowsRequest(ref MutateRowsRequest request, ref CallSettings settings) { GaxPreconditions.CheckState(request.IsIdempotent(), "Non-idempotent MutateRows requests are not allowed. Specify a version with all SetCell mutations."); ApplyResourcePrefixHeader(ref settings, request.TableName); }