Search in sources :

Example 16 with Subscriber

use of org.reactivestreams.Subscriber in project ratpack by ratpack.

the class DefaultResponseTransmitter method transmitter.

@Override
public Subscriber<ByteBuf> transmitter(HttpResponseStatus responseStatus) {
    return new Subscriber<ByteBuf>() {

        private Subscription subscription;

        private final AtomicBoolean done = new AtomicBoolean();

        private final ChannelFutureListener cancelOnFailure = future -> {
            if (!future.isSuccess()) {
                cancel();
            }
        };

        private final GenericFutureListener<Future<? super Void>> cancelOnCloseListener = c -> cancel();

        private void cancel() {
            channel.closeFuture().removeListener(cancelOnCloseListener);
            if (done.compareAndSet(false, true)) {
                subscription.cancel();
                post(responseStatus);
            }
        }

        @Override
        public void onSubscribe(Subscription subscription) {
            if (subscription == null) {
                throw new NullPointerException("'subscription' is null");
            }
            if (this.subscription != null) {
                subscription.cancel();
                return;
            }
            this.subscription = subscription;
            onWritabilityChanged = () -> {
                if (channel.isWritable() && !done.get()) {
                    this.subscription.request(1);
                }
            };
            channel.closeFuture().addListener(cancelOnCloseListener);
            ChannelFuture channelFuture = pre(responseStatus);
            if (channelFuture == null) {
                subscription.cancel();
                notifyListeners(responseStatus, channel.close());
            } else {
                channelFuture.addListener(cancelOnFailure);
                if (channel.isWritable()) {
                    this.subscription.request(1);
                }
            }
        }

        @Override
        public void onNext(ByteBuf o) {
            o.touch();
            if (channel.isOpen()) {
                channel.writeAndFlush(new DefaultHttpContent(o)).addListener(cancelOnFailure);
                if (channel.isWritable()) {
                    subscription.request(1);
                }
            } else {
                o.release();
                cancel();
            }
        }

        @Override
        public void onError(Throwable t) {
            if (t == null) {
                throw new NullPointerException("error is null");
            }
            LOGGER.warn("Exception thrown transmitting stream", t);
            if (done.compareAndSet(false, true)) {
                channel.closeFuture().removeListener(cancelOnCloseListener);
                post(responseStatus);
            }
        }

        @Override
        public void onComplete() {
            if (done.compareAndSet(false, true)) {
                channel.closeFuture().removeListener(cancelOnCloseListener);
                post(responseStatus);
            }
        }
    };
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Subscriber(org.reactivestreams.Subscriber) Subscription(org.reactivestreams.Subscription) ByteBuf(io.netty.buffer.ByteBuf) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener)

Example 17 with Subscriber

use of org.reactivestreams.Subscriber in project ratpack by ratpack.

the class ConcatPublisher method subscribe.

@Override
public void subscribe(Subscriber<? super T> s) {
    s.onSubscribe(new ManagedSubscription<T>(s, disposer) {

        Iterator<? extends Publisher<? extends T>> iterator = publishers.iterator();

        Subscription current;

        @Override
        protected void onRequest(long n) {
            if (current == null) {
                if (iterator.hasNext()) {
                    Publisher<? extends T> publisher = iterator.next();
                    publisher.subscribe(new Subscriber<T>() {

                        @Override
                        public void onSubscribe(Subscription s) {
                            current = s;
                            s.request(n);
                        }

                        @Override
                        public void onNext(T t) {
                            emitNext(t);
                        }

                        @Override
                        public void onError(Throwable t) {
                            emitError(t);
                        }

                        @Override
                        public void onComplete() {
                            current = null;
                            long demand = getDemand();
                            if (demand > 0) {
                                onRequest(demand);
                            }
                        }
                    });
                } else {
                    emitComplete();
                }
            } else {
                current.request(n);
            }
        }

        @Override
        protected void onCancel() {
            if (current != null) {
                current.cancel();
            }
        }
    });
}
Also used : Subscriber(org.reactivestreams.Subscriber) Publisher(org.reactivestreams.Publisher) TransformablePublisher(ratpack.stream.TransformablePublisher) Subscription(org.reactivestreams.Subscription)

Example 18 with Subscriber

use of org.reactivestreams.Subscriber in project ratpack by ratpack.

the class FanOutPublisher method subscribe.

@Override
public void subscribe(Subscriber<? super T> s) {
    s.onSubscribe(new ManagedSubscription<T>(s, disposer) {

        Iterator<? extends T> iterator;

        Subscription subscription;

        AtomicReference<State> state = new AtomicReference<>(State.UNSUBSCRIBED);

        @Override
        protected void onRequest(long n) {
            if (state.compareAndSet(State.UNSUBSCRIBED, State.PENDING_SUBSCRIBE)) {
                publisher.subscribe(new Subscriber<Iterable<? extends T>>() {

                    @Override
                    public void onSubscribe(Subscription s) {
                        subscription = s;
                        state.set(State.REQUESTED);
                        s.request(1);
                    }

                    @Override
                    public void onNext(Iterable<? extends T> ts) {
                        iterator = ts.iterator();
                        state.set(State.IDLE);
                        drain();
                    }

                    @Override
                    public void onError(Throwable t) {
                        emitError(t);
                        drain();
                    }

                    @Override
                    public void onComplete() {
                        subscription = null;
                        state.compareAndSet(State.REQUESTED, State.IDLE);
                        drain();
                    }
                });
            } else if (iterator != null) {
                drain();
            }
        }

        private void drain() {
            if (state.compareAndSet(State.IDLE, State.EMITTING)) {
                if (isDone()) {
                    while (iterator.hasNext()) {
                        dispose(iterator.next());
                    }
                    return;
                }
                boolean hasNext;
                while ((hasNext = iterator.hasNext()) && shouldEmit()) {
                    emitNext(iterator.next());
                }
                if (!hasNext) {
                    // iterator is empty
                    if (subscription == null) {
                        emitComplete();
                    } else if (hasDemand()) {
                        state.set(State.REQUESTED);
                        subscription.request(1);
                        return;
                    }
                }
                state.set(State.IDLE);
                if (hasDemand() || isDone()) {
                    drain();
                }
            }
        }

        @Override
        protected void onCancel() {
            if (subscription != null) {
                subscription.cancel();
            }
        }
    });
}
Also used : Subscriber(org.reactivestreams.Subscriber) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subscription(org.reactivestreams.Subscription)

Example 19 with Subscriber

use of org.reactivestreams.Subscriber in project ratpack by ratpack.

the class FlatMapPublisher method subscribe.

@Override
public void subscribe(final Subscriber<? super O> outSubscriber) {
    input.subscribe(new Subscriber<I>() {

        private Subscription subscription;

        private final AtomicBoolean done = new AtomicBoolean();

        @Override
        public void onSubscribe(Subscription subscription) {
            this.subscription = new Subscription() {

                @Override
                public void request(long n) {
                    subscription.request(n);
                }

                @Override
                public void cancel() {
                    subscription.cancel();
                }
            };
            outSubscriber.onSubscribe(this.subscription);
        }

        @Override
        public void onNext(I in) {
            if (done.get()) {
                return;
            }
            Promise<? extends O> out;
            try {
                out = function.apply(in);
            } catch (Throwable throwable) {
                subscription.cancel();
                innerOnError(throwable);
                return;
            }
            out.onError(e -> {
                subscription.cancel();
                innerOnError(e);
            }).then(v -> {
                if (!done.get()) {
                    outSubscriber.onNext(v);
                }
            });
        }

        @Override
        public void onError(Throwable t) {
            Promise.value(t).then(this::innerOnError);
        }

        public void innerOnError(Throwable t) {
            if (done.compareAndSet(false, true)) {
                outSubscriber.onError(t);
            }
        }

        @Override
        public void onComplete() {
            Operation.noop().then(() -> {
                if (done.compareAndSet(false, true)) {
                    outSubscriber.onComplete();
                }
            });
        }
    });
}
Also used : Function(ratpack.func.Function) Publisher(org.reactivestreams.Publisher) Subscription(org.reactivestreams.Subscription) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Operation(ratpack.exec.Operation) Promise(ratpack.exec.Promise) TransformablePublisher(ratpack.stream.TransformablePublisher) Subscriber(org.reactivestreams.Subscriber) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Promise(ratpack.exec.Promise) Subscription(org.reactivestreams.Subscription)

Example 20 with Subscriber

use of org.reactivestreams.Subscriber in project ratpack by ratpack.

the class FlattenPublisher method subscribe.

@Override
public void subscribe(Subscriber<? super T> subscriber) {
    subscriber.onSubscribe(new ManagedSubscription<T>(subscriber, disposer) {

        private Subscription outerSubscription;

        private Subscription innerSubscription;

        private final AtomicReference<State> state = new AtomicReference<>(State.INIT);

        volatile boolean pendingComplete;

        @Override
        protected void onRequest(long n) {
            if (state.compareAndSet(State.INIT, State.SUBSCRIBE)) {
                if (outerSubscription == null) {
                    subscribeUpstream();
                }
            } else if (innerSubscription != null) {
                innerSubscription.request(n);
            } else {
                nextPublisher();
            }
        }

        private void subscribeUpstream() {
            publisher.subscribe(new Subscriber<Publisher<T>>() {

                @Override
                public void onSubscribe(Subscription subscription) {
                    outerSubscription = subscription;
                    outerSubscription.request(1);
                }

                @Override
                public void onNext(Publisher<T> next) {
                    next.subscribe(new Subscriber<T>() {

                        @Override
                        public void onSubscribe(Subscription s) {
                            innerSubscription = s;
                            state.set(State.EMITTING);
                            innerSubscription.request(getDemand());
                        }

                        @Override
                        public void onNext(T t) {
                            emitNext(t);
                        }

                        @Override
                        public void onError(Throwable t) {
                            outerSubscription.cancel();
                            emitError(t);
                        }

                        @Override
                        public void onComplete() {
                            innerSubscription = null;
                            state.set(State.IDLE);
                            nextPublisher();
                        }
                    });
                }

                @Override
                public void onError(Throwable t) {
                    if (innerSubscription != null) {
                        innerSubscription.cancel();
                        innerSubscription = null;
                    }
                    emitError(t);
                }

                @Override
                public void onComplete() {
                    pendingComplete = true;
                }
            });
        }

        @Override
        protected void onCancel() {
            if (innerSubscription != null) {
                innerSubscription.cancel();
                innerSubscription = null;
            }
            if (outerSubscription != null) {
                outerSubscription.cancel();
                outerSubscription = null;
            }
        }

        private void nextPublisher() {
            if (state.compareAndSet(State.IDLE, State.PENDING)) {
                if (pendingComplete) {
                    emitComplete();
                } else if (hasDemand()) {
                    outerSubscription.request(1);
                } else {
                    state.set(State.IDLE);
                    if (hasDemand()) {
                        nextPublisher();
                    }
                }
            }
        }
    });
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) Publisher(org.reactivestreams.Publisher) TransformablePublisher(ratpack.stream.TransformablePublisher) Subscriber(org.reactivestreams.Subscriber) Subscription(org.reactivestreams.Subscription)

Aggregations

Subscriber (org.reactivestreams.Subscriber)26 Subscription (org.reactivestreams.Subscription)16 Publisher (org.reactivestreams.Publisher)8 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Test (org.junit.Test)5 ByteBuf (io.netty.buffer.ByteBuf)4 BooleanSubscription (io.reactivex.internal.subscriptions.BooleanSubscription)4 TestSubscriber (io.reactivex.subscribers.TestSubscriber)3 InetSocketAddress (java.net.InetSocketAddress)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 Exchange (org.apache.camel.Exchange)3 Test (org.testng.annotations.Test)3 TransformablePublisher (ratpack.stream.TransformablePublisher)3 ReactiveSubscription (reactor.rx.subscription.ReactiveSubscription)3 Flowable (io.reactivex.Flowable)2 TestException (io.reactivex.exceptions.TestException)2 ExecutorService (java.util.concurrent.ExecutorService)2 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)2 RouteBuilder (org.apache.camel.builder.RouteBuilder)2