/** * Blocking call with a different behavior based on the flush mode. PleaseThrottleException is * managed by this method and will not be thrown, unlike {@link AsyncKuduSession#apply}. * * <p> * * <ul> * <li>AUTO_FLUSH_SYNC: the call returns when the operation is persisted, else it throws an * exception. * <li>AUTO_FLUSH_BACKGROUND: the call returns when the operation has been added to the buffer. * This call should normally perform only fast in-memory operations but it may have to wait * when the buffer is full and there's another buffer being flushed. Row errors can be * checked by calling {@link #countPendingErrors()} and can be retrieved by calling {@link * #getPendingErrors()}. * <li>MANUAL_FLUSH: the call returns when the operation has been added to the buffer, else it * throws an exception such as a NonRecoverableException if the buffer is full. * </ul> * * @param operation operation to apply * @return an OperationResponse for the applied Operation * @throws Exception if anything went wrong */ public OperationResponse apply(Operation operation) throws Exception { while (true) { try { Deferred<OperationResponse> d = session.apply(operation); if (getFlushMode() == FlushMode.AUTO_FLUSH_SYNC) { return d.join(getTimeoutMillis()); } break; } catch (PleaseThrottleException ex) { try { ex.getDeferred().join(getTimeoutMillis()); } catch (Exception e) { // This is the error response from the buffer that was flushing, // we can't do much with it at this point. LOG.error("Previous batch had this exception", e); } } catch (Exception e) { throw e; } } return null; }