private <T> Predicate<T> getMutationRetryableFunction(Predicate<T> isRetryableMutation) { if (retryOptions.allowRetriesWithoutTimestamp()) { return Predicates.<T>alwaysTrue(); } else { return isRetryableMutation; } }
private ResultScanner<Row> streamRows(ReadRowsRequest request) { final Timer.Context timerContext = readRowsAsync.getRpcMetrics().timeRpc(); final AtomicBoolean wasCanceled = new AtomicBoolean(false); expandPoolIfNecessary(this.bigtableOptions.getChannelCount()); CallOptions callOptions = getCallOptions(readRowsAsync.getMethodDescriptor(), request); final ClientCall<ReadRowsRequest, ReadRowsResponse> readRowsCall = readRowsAsync.newCall(callOptions); ResponseQueueReader reader = new ResponseQueueReader( retryOptions.getReadPartialRowTimeoutMillis(), retryOptions.getStreamingBufferSize()); final StreamObserverAdapter<ReadRowsResponse> listener = new StreamObserverAdapter<>(readRowsCall, new RowMerger(reader)); readRowsAsync.start(readRowsCall, request, listener, createMetadata(request.getTableName())); // If the scanner is closed before we're done streaming, we want to cancel the RPC. CancellationToken cancellationToken = new CancellationToken(); cancellationToken.addListener( new Runnable() { @Override public synchronized void run() { if (!wasCanceled.get()) { timerContext.close(); wasCanceled.set(true); } if (!listener.hasStatusBeenRecieved()) { readRowsCall.cancel("User requested cancelation.", null); } } }, MoreExecutors.directExecutor()); return new StreamingBigtableResultScanner(reader, cancellationToken); }
/** * Calls {@link OAuth2Credentials#refreshAccessToken()}. In case of an IOException, retry the call * as per the {@link BackOff} policy defined by {@link RetryOptions#createBackoff()}. * * <p>This method retries until one of the following conditions occurs: * * <ol> * <li>An OAuth request was completed. If the value is null, return an exception. * <li>A non-IOException Exception is thrown - return an error status * <li>All retries have been exhausted, i.e. when the Backoff.nextBackOffMillis() returns * BackOff.STOP * <li>An interrupt occurs. * </ol> * * @return HeaderCacheElement containing either a valid {@link AccessToken} or an exception. */ protected HeaderCacheElement refreshCredentialsWithRetry() { BackOff backoff = null; while (true) { try { logger.info("Refreshing the OAuth token"); AccessToken newToken = credentials.refreshAccessToken(); if (newToken == null) { // The current implementations of refreshAccessToken() throws an IOException or return // a valid token. This handling is future proofing just in case credentials returns null // for // some reason. This case was caught by a poorly coded unit test. logger.info("Refreshed the OAuth token"); return new HeaderCacheElement( new IOException("Could not load the token for credentials: " + credentials)); } else { // Success! return new HeaderCacheElement(newToken); } } catch (IOException exception) { logger.warn("Got an unexpected IOException when refreshing google credentials.", exception); // An IOException occurred. Retry with backoff. if (backoff == null) { // initialize backoff. backoff = retryOptions.createBackoff(); } // Given the backoff, either sleep for a short duration, or terminate if the backoff has // reached its configured timeout limit. try { RetryState retryState = getRetryState(backoff); if (retryState != RetryState.PerformRetry) { return new HeaderCacheElement(exception); } // else Retry. } catch (IOException e) { logger.warn("Got an exception while trying to run backoff.nextBackOffMillis()", e); return new HeaderCacheElement(exception); } } catch (Exception e) { logger.warn("Got an unexpected exception while trying to refresh google credentials.", e); return new HeaderCacheElement(new IOException("Could not read headers", e)); } } }