All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.smallrye.reactive.messaging.providers.SubscriberWrapper Maven / Gradle / Ivy

package io.smallrye.reactive.messaging.providers;

import java.util.Objects;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;

import io.smallrye.mutiny.helpers.Subscriptions;

public class SubscriberWrapper implements Flow.Processor {

    /**
     * The subscriber provided by the user.
     */
    private final Subscriber delegate;
    private final BiFunction> postAck;

    private final AtomicReference upstream = new AtomicReference<>();

    private final Function mapper;

    public SubscriberWrapper(Subscriber userSubscriber, Function mapper,
            BiFunction> postAck) {
        this.delegate = Objects.requireNonNull(userSubscriber);
        this.mapper = Objects.requireNonNull(mapper);
        this.postAck = postAck;
    }

    /**
     * Gets called with the downstream subscriber (from reactive messaging).
     *
     * @param s the downstream subscriber
     */
    @Override
    public void subscribe(Subscriber s) {
        s.onSubscribe(new Flow.Subscription() {
            @Override
            public void request(long n) {
                // ignore requests
            }

            @Override
            public void cancel() {
                // cancel subscription upstream
                Flow.Subscription subscription = upstream.getAndSet(Subscriptions.CANCELLED);
                if (subscription != null) {
                    subscription.cancel();
                }
            }
        });
    }

    /**
     * Receives the subscription from the upstream.
     *
     * @param s the subscription
     */
    @Override
    public void onSubscribe(Flow.Subscription s) {

        if (!upstream.compareAndSet(null, s)) {
            throw new IllegalStateException("We already received a subscription");
        }

        // Pass the subscription to the user subscriber.
        delegate.onSubscribe(new Flow.Subscription() {
            @Override
            public void request(long n) {
                s.request(n);
            }

            @Override
            public void cancel() {
                Flow.Subscription subscription = upstream.getAndSet(Subscriptions.CANCELLED);
                if (subscription != null) {
                    subscription.cancel();
                }
            }
        });
    }

    @Override
    public void onNext(T item) {
        try {
            delegate.onNext(mapper.apply(item));
            if (postAck != null) {
                postAck.apply(item, null);
            }
        } catch (Exception e) {
            if (postAck != null) {
                postAck.apply(item, e);
            }
        }
    }

    @Override
    public void onError(Throwable error) {
        delegate.onError(error);
    }

    @Override
    public void onComplete() {
        delegate.onComplete();
    }
}