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

io.smallrye.mutiny.vertx.MultiReadStream Maven / Gradle / Ivy

There is a newer version: 3.17.1
Show newest version
package io.smallrye.mutiny.vertx;

import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.helpers.Subscriptions;
import io.smallrye.mutiny.infrastructure.Infrastructure;
import io.smallrye.mutiny.operators.AbstractMulti;
import io.vertx.core.streams.ReadStream;

public class MultiReadStream extends AbstractMulti implements Multi {

    private final ReadStream source;
    private final Function transformation;
    private final AtomicReference upstream;

    public MultiReadStream(ReadStream source, Function transformation) {
        source.pause();
        this.source = source;
        this.transformation = Infrastructure.decorate(transformation);
        this.upstream = new AtomicReference<>();
    }

    private void release() {
        Subscription sub = upstream.get();
        if (sub != null) {
            if (upstream.compareAndSet(sub, null)) {
                try {
                    source.exceptionHandler(null);
                    source.endHandler(null);
                    source.handler(null);
                } catch (Exception ignore) {
                } finally {
                    try {
                        source.resume();
                    } catch (Exception ignore) {
                    }
                }
            }
        }
    }

    @Override
    public void subscribe(Subscriber downstream) {
        Subscription sub = new Subscription() {
            @Override
            public void request(long req) {
                if (upstream.get() == this) {
                    source.fetch(req);
                }
            }

            @Override
            public void cancel() {
                release();
            }
        };
        if (!upstream.compareAndSet(null, sub)) {
            Subscriptions.fail(downstream, new IllegalStateException("This processor allows only a single Subscriber"));
            return;
        }

        source.pause();

        source.endHandler(v -> {
            release();
            downstream.onComplete();
        });
        source.exceptionHandler(err -> {
            release();
            downstream.onError(err);
        });
        source.handler(item -> downstream.onNext(transformation.apply(item)));

        downstream.onSubscribe(sub);
    }
}