/** * Add mutation for a particular row. The changes in the mutation will be applied atomic. However * there is no guarantees about the relative ordering between mutations affecting different rows. */ public BulkMutation add(@Nonnull ByteString rowKey, @Nonnull Mutation mutation) { Preconditions.checkNotNull(rowKey); Preconditions.checkNotNull(mutation); builder.addEntries( MutateRowsRequest.Entry.newBuilder() .setRowKey(rowKey) .addAllMutations(mutation.getMutations()) .build()); return this; }
/** * Handle an RPC level failure by generating a {@link FailedMutation} for each expected entry. The * newly generated {@link FailedMutation}s will be combined with the permanentFailures to give the * caller the whole picture since the first call. This method will always throw a {@link * MutateRowsException}. */ private void handleAttemptError(Throwable rpcError) { ApiException entryError = createSyntheticErrorForRpcFailure(rpcError); ImmutableList.Builder<FailedMutation> allFailures = ImmutableList.builder(); MutateRowsRequest lastRequest = currentRequest; allFailures.addAll(permanentFailures); Builder builder = lastRequest.toBuilder().clearEntries(); List<Integer> newOriginalIndexes = Lists.newArrayList(); for (int i = 0; i < currentRequest.getEntriesCount(); i++) { int origIndex = getOriginalIndex(i); FailedMutation failedMutation = FailedMutation.create(origIndex, entryError); allFailures.add(failedMutation); if (!failedMutation.getError().isRetryable()) { permanentFailures.add(failedMutation); } else { // Schedule the mutation entry for the next RPC by adding it to the request builder and // recording its original index newOriginalIndexes.add(origIndex); builder.addEntries(lastRequest.getEntries(i)); } } currentRequest = builder.build(); originalIndexes = newOriginalIndexes; throw new MutateRowsException(rpcError, allFailures.build(), entryError.isRetryable()); }
builder.addEntries(lastRequest.getEntries((int) entry.getIndex()));
builder.addEntries(lastRequest.getEntries((int) entry.getIndex()));
/** * Handle an RPC level failure by generating a {@link FailedMutation} for each expected entry. The * newly generated {@link FailedMutation}s will be combined with the permanentFailures to give the * caller the whole picture since the first call. This method will always throw a {@link * MutateRowsException}. */ private void handleAttemptError(Throwable rpcError) { ApiException entryError = createSyntheticErrorForRpcFailure(rpcError); ImmutableList.Builder<FailedMutation> allFailures = ImmutableList.builder(); MutateRowsRequest lastRequest = currentRequest; allFailures.addAll(permanentFailures); Builder builder = lastRequest.toBuilder().clearEntries(); List<Integer> newOriginalIndexes = Lists.newArrayList(); for (int i = 0; i < currentRequest.getEntriesCount(); i++) { int origIndex = getOriginalIndex(i); FailedMutation failedMutation = FailedMutation.create(origIndex, entryError); allFailures.add(failedMutation); if (!failedMutation.getError().isRetryable()) { permanentFailures.add(failedMutation); } else { // Schedule the mutation entry for the next RPC by adding it to the request builder and // recording its original index newOriginalIndexes.add(origIndex); builder.addEntries(lastRequest.getEntries(i)); } } currentRequest = builder.build(); originalIndexes = newOriginalIndexes; throw new MutateRowsException(rpcError, allFailures.build(), entryError.isRetryable()); }
/** * Adds a {@link com.google.bigtable.v2.MutateRowsRequest.Entry} to the {@link * com.google.bigtable.v2.MutateRowsRequest.Builder}. NOTE: Users have to make sure that this * gets called in a thread safe way. * * @param entry The {@link com.google.bigtable.v2.MutateRowsRequest.Entry} to add * @return a {@link SettableFuture} that will be populated when the {@link MutateRowsResponse} * returns from the server. See {@link #addCallback(ListenableFuture)} for more * information about how the SettableFuture is set. */ private ListenableFuture<MutateRowResponse> add(MutateRowsRequest.Entry entry) { Preconditions.checkNotNull(entry); SettableFuture<MutateRowResponse> future = SettableFuture.create(); mutationMeter.mark(); futures.add(future); builder.addEntries(entry); approximateByteSize += entry.getSerializedSize(); numberOfMutations += entry.getMutationsCount(); return future; }
/** * Creates a single entry bulk {@link com.google.bigtable.v2.MutateRowsRequest}, which will be * merged by the batching logic in the callable chain. */ @InternalApi public MutateRowsRequest toBulkProto(RequestContext requestContext) { String tableName = NameUtil.formatTableName( requestContext.getProjectId(), requestContext.getInstanceId(), tableId); return MutateRowsRequest.newBuilder() .setAppProfileId(requestContext.getAppProfileId()) .setTableName(tableName) .addEntries( Entry.newBuilder().setRowKey(key).addAllMutations(mutation.getMutations()).build()) .build(); } }
/** * Creates a new {@link MutateRowsRequest} that's a subset of the original request that * corresponds to a set of indices. * * @param indiciesToRetry * @return the new {@link MutateRowsRequest}. */ private MutateRowsRequest createRetryRequest(List<Integer> indiciesToRetry) { MutateRowsRequest.Builder updatedRequest = MutateRowsRequest.newBuilder() .setTableName(originalRequest.getTableName()); mapToOriginalIndex = new int[indiciesToRetry.size()]; for (int i = 0; i < indiciesToRetry.size(); i++) { mapToOriginalIndex[i] = indiciesToRetry.get(i); updatedRequest.addEntries(originalRequest.getEntries(indiciesToRetry.get(i))); } return updatedRequest.build(); }
/** * Add mutation for a particular row. The changes in the mutation will be applied atomic. However * there is no guarantees about the relative ordering between mutations affecting different rows. */ public BulkMutation add(@Nonnull ByteString rowKey, @Nonnull Mutation mutation) { Preconditions.checkNotNull(rowKey); Preconditions.checkNotNull(mutation); builder.addEntries( MutateRowsRequest.Entry.newBuilder() .setRowKey(rowKey) .addAllMutations(mutation.getMutations()) .build()); return this; }
.addEntries(Entry.newBuilder().setRowKey(ByteString.copyFromUtf8("0-ok"))) .addEntries(Entry.newBuilder().setRowKey(ByteString.copyFromUtf8("1-unavailable"))) .addEntries(Entry.newBuilder().setRowKey(ByteString.copyFromUtf8("2-invalid"))) .build();
.addEntries(Entry.getDefaultInstance()) .addEntries(Entry.getDefaultInstance()) .addEntries(Entry.getDefaultInstance()) .build();
.addEntries(Entry.getDefaultInstance()) .addEntries(Entry.getDefaultInstance()) .build();
.addEntries(Entry.getDefaultInstance()) .addEntries(Entry.getDefaultInstance()) .build();
private static MutateRowsRequest createRequest(int count) { MutateRowsRequest.Builder request = MutateRowsRequest.newBuilder() .setTableName(NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, TABLE_ID)); for (int i = 0; i < count; i++) { Builder entry = Entry.newBuilder() .addMutations( Mutation.newBuilder() .setSetCell( SetCell.newBuilder() .setFamilyName("family") .setColumnQualifier(ByteString.copyFromUtf8("col" + i)) .setTimestampMicros(1000) .setValue(ByteString.copyFromUtf8("value" + i)))); request.addEntries(entry); } return request.build(); } }
@Test public void testNoRpcTimeout() { parentFuture.timedAttemptSettings = parentFuture.timedAttemptSettings.toBuilder().setRpcTimeout(Duration.ZERO).build(); MutateRowsRequest request = MutateRowsRequest.newBuilder().addEntries(Entry.getDefaultInstance()).build(); innerCallable.response.add( MutateRowsResponse.newBuilder() .addEntries( MutateRowsResponse.Entry.newBuilder().setIndex(0).setStatus(OK_STATUS_PROTO)) .build()); MutateRowsAttemptCallable attemptCallable = new MutateRowsAttemptCallable(innerCallable, request, callContext, retryCodes); attemptCallable.setExternalFuture(parentFuture); attemptCallable.call(); assertThat(innerCallable.lastContext.getTimeout()).isNull(); }
@Test public void singleEntrySuccessTest() throws Exception { MutateRowsRequest request = MutateRowsRequest.newBuilder().addEntries(Entry.getDefaultInstance()).build(); innerCallable.response.add( MutateRowsResponse.newBuilder() .addEntries( MutateRowsResponse.Entry.newBuilder().setIndex(0).setStatus(OK_STATUS_PROTO)) .build()); MutateRowsAttemptCallable attemptCallable = new MutateRowsAttemptCallable(innerCallable, request, callContext, retryCodes); attemptCallable.setExternalFuture(parentFuture); attemptCallable.call(); // Attempt completed successfully and the useless response has been suppressed assertThat(parentFuture.attemptFuture.get()).isNull(); // innerCallable received the request assertThat(innerCallable.lastRequest).isEqualTo(request); }
@Test public void requestBuilderTest() { RequestBuilder<MutateRowsRequest> builder = descriptor.getRequestBuilder(); MutateRowsRequest expected = createRequest(5); for (Entry entry : expected.getEntriesList()) { MutateRowsRequest singleReq = MutateRowsRequest.newBuilder() .setTableName(NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, TABLE_ID)) .addEntries(entry) .build(); builder.appendRequest(singleReq); } MutateRowsRequest actual = builder.build(); assertThat(actual).isEqualTo(expected); }
/** * Creates a single entry bulk {@link com.google.bigtable.v2.MutateRowsRequest}, which will be * merged by the batching logic in the callable chain. */ @InternalApi public MutateRowsRequest toBulkProto(RequestContext requestContext) { String tableName = NameUtil.formatTableName( requestContext.getProjectId(), requestContext.getInstanceId(), tableId); return MutateRowsRequest.newBuilder() .setAppProfileId(requestContext.getAppProfileId()) .setTableName(tableName) .addEntries( Entry.newBuilder().setRowKey(key).addAllMutations(mutation.getMutations()).build()) .build(); } }