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

io.smallrye.mutiny.context.ContextPropagationMultiInterceptor Maven / Gradle / Ivy

There is a newer version: 0.13.0
Show newest version
package io.smallrye.mutiny.context;

import java.util.Objects;
import java.util.concurrent.Executor;

import org.eclipse.microprofile.context.ThreadContext;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.helpers.StrictMultiSubscriber;
import io.smallrye.mutiny.infrastructure.MultiInterceptor;
import io.smallrye.mutiny.operators.AbstractMulti;
import io.smallrye.mutiny.subscription.MultiSubscriber;

/**
 * Provides context propagation to Multi types.
 * Subclasses need to override this to provide the Context Propagation ThreadContext.
 */
public abstract class ContextPropagationMultiInterceptor implements MultiInterceptor {

    @Override
    public  Subscriber onSubscription(Publisher instance, Subscriber subscriber) {
        Executor executor = getThreadContext().currentContextExecutor();
        return new ContextPropagationSubscriber<>(executor, subscriber);
    }

    @Override
    public  Multi onMultiCreation(Multi multi) {
        Executor executor = getThreadContext().currentContextExecutor();
        return new ContextPropagationMulti<>(executor, multi);
    }

    /**
     * Gets the Context Propagation ThreadContext. External
     * implementations may implement this method.
     *
     * @return the ThreadContext
     * @see DefaultContextPropagationMultiInterceptor#getThreadContext()
     */
    protected abstract ThreadContext getThreadContext();

    private static class ContextPropagationMulti extends AbstractMulti {

        private final Executor executor;
        private final Multi multi;

        public ContextPropagationMulti(Executor executor, Multi multi) {
            this.executor = executor;
            this.multi = multi;
        }

        @Override
        public void subscribe(Subscriber subscriber) {
            Objects.requireNonNull(subscriber); // Required by reactive streams TCK
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    if (subscriber instanceof MultiSubscriber) {
                        multi.subscribe(subscriber);
                    } else {
                        multi.subscribe(new StrictMultiSubscriber<>(subscriber));
                    }
                }
            });
        }
    }

    @SuppressWarnings({ "ReactiveStreamsSubscriberImplementation" })
    public static class ContextPropagationSubscriber implements Subscriber {

        private final Executor executor;
        private final Subscriber subscriber;

        public ContextPropagationSubscriber(Executor executor, Subscriber subscriber) {
            this.executor = executor;
            this.subscriber = subscriber;
        }

        @Override
        public void onSubscribe(Subscription subscription) {
            executor.execute(() -> subscriber.onSubscribe(subscription));
        }

        @Override
        public void onNext(T item) {
            Objects.requireNonNull(item);
            executor.execute(() -> subscriber.onNext(item));
        }

        @Override
        public void onError(Throwable failure) {
            Objects.requireNonNull(failure);
            executor.execute(() -> subscriber.onError(failure));
        }

        @Override
        public void onComplete() {
            executor.execute(subscriber::onComplete);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy