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

com.github.thorbenkuck.network.stream.SimpleSubscription Maven / Gradle / Ivy

The newest version!
package com.github.thorbenkuck.network.stream;

import com.github.thorbenkuck.network.exceptions.SubscriptionException;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

class SimpleSubscription implements NotifiableSubscription {

    private final List throwableBuffer = new ArrayList<>();
    private final Object mutexLock = new Object();
    private final Object cancelLock = new Object();
    private Subscriber subscriber;
    private boolean bufferErrors = true;
    private SubscriptionReference> subscriptionReference;
    private Runnable onCancel;
    private ExceptionalConsumer errorConsumer;

    SimpleSubscription(Subscriber subscriber, SubscriptionReference> subscriptionReference) {
        this.subscriber = subscriber;
        this.subscriptionReference = subscriptionReference;
    }

    private void runEncapsulated(ExceptionalRunnable exceptionalRunnable) {
        try {
            exceptionalRunnable.run();
        } catch (Throwable throwable) {
            if (throwable instanceof SubscriptionException) {
                throw (SubscriptionException) throwable;
            }
            throw new SubscriptionException(throwable);
        }
    }

    private void addThrowable(Throwable throwable) {
        try {
            subscriber.onError(throwable);
        } catch (Throwable e) {
            if (errorConsumer != null) {
                runEncapsulated(() -> errorConsumer.accept(e));
            } else {
                if (bufferErrors) {
                    throwableBuffer.add(throwable);
                } else {
                    runEncapsulated(() -> {
                        throw throwable;
                    });
                }
            }
        }
    }

    @Override
    public NotifiableSubscription onError(ExceptionalConsumer consumer) {
        this.errorConsumer = Objects.requireNonNull(consumer);

        return this;
    }

    @Override
    public void notify(T t) {
        synchronized (mutexLock) {
            if (!isCanceled()) {
                try {
                    subscriber.accept(t);
                } catch (Throwable throwable) {
                    addThrowable(throwable);
                }
            }
        }
    }

    @Override
    public void notify(Throwable throwable) {
        addThrowable(throwable);
    }

    @Override
    public boolean isCanceled() {
        return subscriber == null;
    }

    @Override
    public void cancel() {
        if (isCanceled()) {
            return;
        }
        synchronized (mutexLock) {
            if (subscriber != null) {
                subscriber.onCancel();
                subscriber = null;
            }

            if (subscriptionReference != null) {
                subscriptionReference.remove(this);
                subscriptionReference = null;
            }

            synchronized (cancelLock) {
                if (onCancel != null) {
                    try {
                        onCancel.run();
                    } catch (Throwable t) {
                        addThrowable(t);
                    }
                    onCancel = null;
                }
            }
        }
    }

    @Override
    public void setOnCancel(Runnable runnable) {
        synchronized (cancelLock) {
            this.onCancel = runnable;
        }
    }

    @Override
    public List drainEncountered() {
        List toReturn = new ArrayList<>(throwableBuffer);
        throwableBuffer.clear();
        return toReturn;
    }

    @Override
    public boolean hasEncounteredErrors() {
        return !throwableBuffer.isEmpty();
    }

    @Override
    public void preventErrorBuffer() {
        bufferErrors = false;
    }

    @Override
    public String toString() {
        return "SimpleSubscription{" + "subscriber=" + subscriber +
                ", throwableBuffer=" + throwableBuffer +
                ", onCancel=" + onCancel +
                '}';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy