currentBatch = new Batch();
private void setupStalenessChecker() { Runnable runnable = new Runnable() { @Override public void run() { synchronized (Batch.this) { if (futures.isEmpty()) { setComplete(); } else if (isStale()) { setFailure( io.grpc.Status.INTERNAL.withDescription("Stale requests.").asRuntimeException()); } else { setupStalenessChecker(); } } } }; if (lastRpcSentTimeNanos != null) { long delay = calculateTimeUntilStaleNanos(); stalenessFuture = retryExecutorService.schedule(runnable, delay, TimeUnit.NANOSECONDS); } }
private void handleExtraFutures(List<Entry> entries) { Set<Integer> indexes = getIndexes(entries); long missingEntriesCount = 0; for (int i = 0; i < getRequestCount(); i++) { // If the indexes do not contain this future, then there's a problem. if (!indexes.remove(i)) { missingEntriesCount++; futures.get(i).setException(MISSING_ENTRY_EXCEPTION); } } if (missingEntriesCount > 0) { LOG.error("Missing %d responses for bulkWrite. Setting exceptions on the futures.", missingEntriesCount); } }
@VisibleForTesting synchronized void handleResult(List<MutateRowsResponse> results) { if (futures.isEmpty()) { LOG.warn("Got duplicate responses for bulk mutation."); setComplete(); return; } List<MutateRowsResponse.Entry> entries = new ArrayList<>(); for (MutateRowsResponse response : results) { entries.addAll(response.getEntriesList()); } if (entries.isEmpty()) { setFailure(io.grpc.Status.INTERNAL .withDescription("No MutateRowsResponses entries were found.").asRuntimeException()); return; } try { handleEntries(entries); handleExtraFutures(entries); setComplete(); } catch (Throwable e) { setFailure(e); } }
private void handleEntries(Iterable<MutateRowsResponse.Entry> entries) { for (MutateRowsResponse.Entry entry : entries) { int index = (int) entry.getIndex(); if (index >= getRequestCount()) { LOG.error("Got extra status: %s", entry); continue; } SettableFuture<MutateRowResponse> future = futures.get(index); if (future == null) { LOG.warn("Could not find a future for index %d.", index); continue; } Status status = entry.getStatus(); if (status.getCode() == io.grpc.Status.Code.OK.value()) { future.set(MutateRowResponse.getDefaultInstance()); } else { future.setException(toException(status)); } } }
private void run() { if (futures.isEmpty()) { setComplete(); return; } Preconditions.checkState(!completionFuture.isDone(), "The Batch was already run"); try { MutateRowsRequest request = builder.build(); mutateRowsFuture = client.mutateRowsAsync(request); lastRpcSentTimeNanos = clock.nanoTime(); } catch (Throwable e) { mutateRowsFuture = Futures.<List<MutateRowsResponse>> immediateFailedFuture(e); } finally { addCallback(mutateRowsFuture); } setupStalenessChecker(); }
@Override public void run() { synchronized (Batch.this) { if (futures.isEmpty()) { setComplete(); } else if (isStale()) { setFailure( io.grpc.Status.INTERNAL.withDescription("Stale requests.").asRuntimeException()); } else { setupStalenessChecker(); } } } };
/** * This would have happened after all retries are exhausted on the MutateRowsRequest. Don't * retry individual mutations. */ private void setFailure(Throwable t) { try { for (SettableFuture<MutateRowResponse> future : futures) { future.setException(t); } } finally { setComplete(); } }
@Override public void onSuccess(List<MutateRowsResponse> result) { handleResult(result); }
@VisibleForTesting boolean isStale() { return lastRpcSentTimeNanos != null && calculateTimeUntilStaleNanos() <= 0; }
private boolean wouldBeFull(MutateRowsRequest.Entry entry) { boolean hitMutationMax = numberOfMutations + entry.getMutationsCount() > MAX_NUMBER_OF_MUTATIONS; if (hitMutationMax) { LOG.debug( "Would overflow maximum number of mutations, current = %d, adding = %d", numberOfMutations, entry.getMutationsCount()); } return getRequestCount() + 1 > maxRowKeyCount || (approximateByteSize + entry.getSerializedSize() > maxRequestSize) || hitMutationMax; }