@Override public void onCompleted() { delegate.onCompleted(); } }
@Override public void onError(Throwable t) { delegate.onError(t); }
BlockingStreamObserver(CallStreamObserver<T> delegate) { this.delegate = delegate; final Runnable notifyAll = () -> { synchronized (lock) { lock.notifyAll(); // wake up our thread } }; this.delegate.setOnReadyHandler(notifyAll); if (delegate instanceof ServerCallStreamObserver) { ((ServerCallStreamObserver<T>) delegate).setOnCancelHandler(notifyAll); } }
@Override public void onNext(T value) { synchronized (lock) { // in theory we could implement ServerCallStreamObserver and expose isCancelled to our client, // but for current purposes we only need the StreamObserver API, so treat a cancelled observer // as something we just want to un-block from and return, and we'll trust the rest of our session // to shutdown accordingly. if (delegate instanceof ServerCallStreamObserver && ((ServerCallStreamObserver<T>) delegate).isCancelled()) { return; } while (!delegate.isReady()) { try { lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } } delegate.onNext(value); }
/** * Copy the values of an {@link Iterator} to the target {@link CallStreamObserver} while properly * accounting for outbound flow-control. * * <p>For clients this method is safe to call inside {@link ClientResponseObserver#beforeStart}, * on servers it is safe to call inside the service method implementation. * </p> * * @param source of values expressed as an {@link Iterator}. * @param target {@link CallStreamObserver} which accepts values from the source. */ public static <V> void copyWithFlowControl(final Iterator<V> source, final CallStreamObserver<V> target) { Preconditions.checkNotNull(source, "source"); Preconditions.checkNotNull(target, "target"); final class FlowControllingOnReadyHandler implements Runnable { @Override public void run() { while (target.isReady() && source.hasNext()) { target.onNext(source.next()); } if (!source.hasNext()) { target.onCompleted(); } } } target.setOnReadyHandler(new FlowControllingOnReadyHandler()); }