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);
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
 /// <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]]);
     }
 }
Пример #5
0
        /// <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)));
        }
Пример #6
0
        /// <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);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
 /// <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));
        }
Пример #11
0
 internal static bool IsIdempotent(this MutateRowsRequest request) =>
 request.Entries.All(IsIdempotent);
Пример #12
0
 /// <inheritdoc/>
 public override MutateRowsResponse MutateRows(
     MutateRowsRequest request,
     gaxgrpc::CallSettings callSettings = null) => stt::Task.Run(() => MutateRowsAsync(request, callSettings)).ResultWithUnwrappedExceptions();
Пример #13
0
 /// <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));
Пример #14
0
 /// <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();
 }
Пример #15
0
 /// <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();
 }
Пример #16
0
 /// <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();
 }
Пример #17
0
 /// <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.");
Пример #19
0
 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);
 }